/*
* Copyright 2011 Google Inc.
* Copyright 2014 Andreas Schildbach
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.bitcoinj.core;
import com.google.common.base.Objects;
import org.bitcoinj.core.Block;
import org.bitcoinj.core.StoredBlock;
import org.bitcoinj.core.VerificationException;
import org.bitcoinj.net.discovery.*;
import org.bitcoinj.params.*;
import org.bitcoinj.script.*;
import org.bitcoinj.store.BlockStore;
import org.bitcoinj.store.BlockStoreException;
import org.bitcoinj.utils.MonetaryFormat;
import javax.annotation.*;
import java.io.*;
import java.math.*;
import java.util.*;
import static org.bitcoinj.core.Coin.*;
import org.bitcoinj.utils.VersionTally;
/**
* <p>NetworkParameters contains the data needed for working with an instantiation of a Bitcoin chain.</p>
*
* <p>This is an abstract class, concrete instantiations can be found in the params package. There are four:
* one for the main network ({@link MainNetParams}), one for the public test network, and two others that are
* intended for unit testing and local app development purposes. Although this class contains some aliases for
* them, you are encouraged to call the static get() methods on each specific params class directly.</p>
*/
public abstract class NetworkParameters {
/**
* The alert signing key originally owned by Satoshi, and now passed on to Gavin along with a few others.
*/
public static final byte[] SATOSHI_KEY = Utils.HEX.decode("04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284");
/** The string returned by getId() for the main, production network where people trade things. */
public static final String ID_MAINNET = "org.bitcoin.production";
/** The string returned by getId() for the testnet. */
public static final String ID_TESTNET = "org.bitcoin.test";
/** The string returned by getId() for regtest mode. */
public static final String ID_REGTEST = "org.bitcoin.regtest";
/** Unit test network. */
public static final String ID_UNITTESTNET = "org.bitcoinj.unittest";
/** The string used by the payment protocol to represent the main net. */
public static final String PAYMENT_PROTOCOL_ID_MAINNET = "main";
/** The string used by the payment protocol to represent the test net. */
public static final String PAYMENT_PROTOCOL_ID_TESTNET = "test";
/** The string used by the payment protocol to represent unit testing (note that this is non-standard). */
public static final String PAYMENT_PROTOCOL_ID_UNIT_TESTS = "unittest";
public static final String PAYMENT_PROTOCOL_ID_REGTEST = "regtest";
// TODO: Seed nodes should be here as well.
protected Block genesisBlock;
protected BigInteger maxTarget;
protected int port;
protected long packetMagic; // Indicates message origin network and is used to seek to the next message when stream state is unknown.
protected int addressHeader;
protected int p2shHeader;
protected int dumpedPrivateKeyHeader;
protected int interval;
protected int targetTimespan;
protected byte[] alertSigningKey;
protected int bip32HeaderPub;
protected int bip32HeaderPriv;
/** Used to check majorities for block version upgrade */
protected int majorityEnforceBlockUpgrade;
protected int majorityRejectBlockOutdated;
protected int majorityWindow;
/**
* See getId(). This may be null for old deserialized wallets. In that case we derive it heuristically
* by looking at the port number.
*/
protected String id;
/**
* The depth of blocks required for a coinbase transaction to be spendable.
*/
protected int spendableCoinbaseDepth;
protected int subsidyDecreaseBlockCount;
protected int[] acceptableAddressCodes;
protected String[] dnsSeeds;
protected int[] addrSeeds;
protected HttpDiscovery.Details[] httpSeeds = {};
protected Map<Integer, Sha256Hash> checkpoints = new HashMap<Integer, Sha256Hash>();
protected transient MessageSerializer defaultSerializer = null;
protected NetworkParameters() {
alertSigningKey = SATOSHI_KEY;
genesisBlock = createGenesis(this);
}
private static Block createGenesis(NetworkParameters n) {
Block genesisBlock = new Block(n, Block.BLOCK_VERSION_GENESIS);
Transaction t = new Transaction(n);
try {
// A script containing the difficulty bits and the following message:
//
// "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks"
byte[] bytes = Utils.HEX.decode
("04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73");
t.addInput(new TransactionInput(n, t, bytes));
ByteArrayOutputStream scriptPubKeyBytes = new ByteArrayOutputStream();
Script.writeBytes(scriptPubKeyBytes, Utils.HEX.decode
("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f"));
scriptPubKeyBytes.write(ScriptOpCodes.OP_CHECKSIG);
t.addOutput(new TransactionOutput(n, t, FIFTY_COINS, scriptPubKeyBytes.toByteArray()));
} catch (Exception e) {
// Cannot happen.
throw new RuntimeException(e);
}
genesisBlock.addTransaction(t);
return genesisBlock;
}
public static final int TARGET_TIMESPAN = 14 * 24 * 60 * 60; // 2 weeks per difficulty cycle, on average.
public static final int TARGET_SPACING = 10 * 60; // 10 minutes per block.
public static final int INTERVAL = TARGET_TIMESPAN / TARGET_SPACING;
/**
* Blocks with a timestamp after this should enforce BIP 16, aka "Pay to script hash". This BIP changed the
* network rules in a soft-forking manner, that is, blocks that don't follow the rules are accepted but not
* mined upon and thus will be quickly re-orged out as long as the majority are enforcing the rule.
*/
public static final int BIP16_ENFORCE_TIME = 1333238400;
/**
* The maximum number of coins to be generated
*/
public static final long MAX_COINS = 21000000;
/**
* The maximum money to be generated
*/
public static final Coin MAX_MONEY = COIN.multiply(MAX_COINS);
/** Alias for TestNet3Params.get(), use that instead. */
@Deprecated
public static NetworkParameters testNet() {
return TestNet3Params.get();
}
/** Alias for TestNet2Params.get(), use that instead. */
@Deprecated
public static NetworkParameters testNet2() {
return TestNet2Params.get();
}
/** Alias for TestNet3Params.get(), use that instead. */
@Deprecated
public static NetworkParameters testNet3() {
return TestNet3Params.get();
}
/** Alias for MainNetParams.get(), use that instead */
@Deprecated
public static NetworkParameters prodNet() {
return MainNetParams.get();
}
/** Returns a testnet params modified to allow any difficulty target. */
@Deprecated
public static NetworkParameters unitTests() {
return UnitTestParams.get();
}
/** Returns a standard regression test params (similar to unitTests) */
@Deprecated
public static NetworkParameters regTests() {
return RegTestParams.get();
}
/**
* A Java package style string acting as unique ID for these parameters
*/
public String getId() {
return id;
}
public abstract String getPaymentProtocolId();
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
return getId().equals(((NetworkParameters)o).getId());
}
@Override
public int hashCode() {
return Objects.hashCode(getId());
}
/** Returns the network parameters for the given string ID or NULL if not recognized. */
@Nullable
public static NetworkParameters fromID(String id) {
if (id.equals(ID_MAINNET)) {
return MainNetParams.get();
} else if (id.equals(ID_TESTNET)) {
return TestNet3Params.get();
} else if (id.equals(ID_UNITTESTNET)) {
return UnitTestParams.get();
} else if (id.equals(ID_REGTEST)) {
return RegTestParams.get();
} else {
return null;
}
}
/** Returns the network parameters for the given string paymentProtocolID or NULL if not recognized. */
@Nullable
public static NetworkParameters fromPmtProtocolID(String pmtProtocolId) {
if (pmtProtocolId.equals(PAYMENT_PROTOCOL_ID_MAINNET)) {
return MainNetParams.get();
} else if (pmtProtocolId.equals(PAYMENT_PROTOCOL_ID_TESTNET)) {
return TestNet3Params.get();
} else if (pmtProtocolId.equals(PAYMENT_PROTOCOL_ID_UNIT_TESTS)) {
return UnitTestParams.get();
} else if (pmtProtocolId.equals(PAYMENT_PROTOCOL_ID_REGTEST)) {
return RegTestParams.get();
} else {
return null;
}
}
public int getSpendableCoinbaseDepth() {
return spendableCoinbaseDepth;
}
/**
* Throws an exception if the block's difficulty is not correct.
*
* @throws VerificationException if the block's difficulty is not correct.
*/
public abstract void checkDifficultyTransitions(StoredBlock storedPrev, Block next, final BlockStore blockStore) throws VerificationException, BlockStoreException;
/**
* Returns true if the block height is either not a checkpoint, or is a checkpoint and the hash matches.
*/
public boolean passesCheckpoint(int height, Sha256Hash hash) {
Sha256Hash checkpointHash = checkpoints.get(height);
return checkpointHash == null || checkpointHash.equals(hash);
}
/**
* Returns true if the given height has a recorded checkpoint.
*/
public boolean isCheckpoint(int height) {
Sha256Hash checkpointHash = checkpoints.get(height);
return checkpointHash != null;
}
public int getSubsidyDecreaseBlockCount() {
return subsidyDecreaseBlockCount;
}
/** Returns DNS names that when resolved, give IP addresses of active peers. */
public String[] getDnsSeeds() {
return dnsSeeds;
}
/** Returns IP address of active peers. */
public int[] getAddrSeeds() {
return addrSeeds;
}
/** Returns discovery objects for seeds implementing the Cartographer protocol. See {@link org.bitcoinj.net.discovery.HttpDiscovery} for more info. */
public HttpDiscovery.Details[] getHttpSeeds() {
return httpSeeds;
}
/**
* <p>Genesis block for this chain.</p>
*
* <p>The first block in every chain is a well known constant shared between all Bitcoin implemenetations. For a
* block to be valid, it must be eventually possible to work backwards to the genesis block by following the
* prevBlockHash pointers in the block headers.</p>
*
* <p>The genesis blocks for both test and main networks contain the timestamp of when they were created,
* and a message in the coinbase transaction. It says, <i>"The Times 03/Jan/2009 Chancellor on brink of second
* bailout for banks"</i>.</p>
*/
public Block getGenesisBlock() {
return genesisBlock;
}
/** Default TCP port on which to connect to nodes. */
public int getPort() {
return port;
}
/** The header bytes that identify the start of a packet on this network. */
public long getPacketMagic() {
return packetMagic;
}
/**
* First byte of a base58 encoded address. See {@link org.bitcoinj.core.Address}. This is the same as acceptableAddressCodes[0] and
* is the one used for "normal" addresses. Other types of address may be encountered with version codes found in
* the acceptableAddressCodes array.
*/
public int getAddressHeader() {
return addressHeader;
}
/**
* First byte of a base58 encoded P2SH address. P2SH addresses are defined as part of BIP0013.
*/
public int getP2SHHeader() {
return p2shHeader;
}
/** First byte of a base58 encoded dumped private key. See {@link org.bitcoinj.core.DumpedPrivateKey}. */
public int getDumpedPrivateKeyHeader() {
return dumpedPrivateKeyHeader;
}
/**
* How much time in seconds is supposed to pass between "interval" blocks. If the actual elapsed time is
* significantly different from this value, the network difficulty formula will produce a different value. Both
* test and main Bitcoin networks use 2 weeks (1209600 seconds).
*/
public int getTargetTimespan() {
return targetTimespan;
}
/**
* The version codes that prefix addresses which are acceptable on this network. Although Satoshi intended these to
* be used for "versioning", in fact they are today used to discriminate what kind of data is contained in the
* address and to prevent accidentally sending coins across chains which would destroy them.
*/
public int[] getAcceptableAddressCodes() {
return acceptableAddressCodes;
}
/**
* If we are running in testnet-in-a-box mode, we allow connections to nodes with 0 non-genesis blocks.
*/
public boolean allowEmptyPeerChain() {
return true;
}
/** How many blocks pass between difficulty adjustment periods. Bitcoin standardises this to be 2016. */
public int getInterval() {
return interval;
}
/** Maximum target represents the easiest allowable proof of work. */
public BigInteger getMaxTarget() {
return maxTarget;
}
/**
* The key used to sign {@link org.bitcoinj.core.AlertMessage}s. You can use {@link org.bitcoinj.core.ECKey#verify(byte[], byte[], byte[])} to verify
* signatures using it.
*/
public byte[] getAlertSigningKey() {
return alertSigningKey;
}
/** Returns the 4 byte header for BIP32 (HD) wallet - public key part. */
public int getBip32HeaderPub() {
return bip32HeaderPub;
}
/** Returns the 4 byte header for BIP32 (HD) wallet - private key part. */
public int getBip32HeaderPriv() {
return bip32HeaderPriv;
}
/**
* Returns the number of coins that will be produced in total, on this
* network. Where not applicable, a very large number of coins is returned
* instead (i.e. the main coin issue for Dogecoin).
*/
public abstract Coin getMaxMoney();
/**
* Any standard (ie pay-to-address) output smaller than this value will
* most likely be rejected by the network.
*/
public abstract Coin getMinNonDustOutput();
/**
* The monetary object for this currency.
*/
public abstract MonetaryFormat getMonetaryFormat();
/**
* Scheme part for URIs, for example "bitcoin".
*/
public abstract String getUriScheme();
/**
* Returns whether this network has a maximum number of coins (finite supply) or
* not. Always returns true for Bitcoin, but exists to be overriden for other
* networks.
*/
public abstract boolean hasMaxMoney();
/**
* Return the default serializer for this network. This is a shared serializer.
* @return
*/
public final MessageSerializer getDefaultSerializer() {
// Construct a default serializer if we don't have one
if (null == this.defaultSerializer) {
// Don't grab a lock unless we absolutely need it
synchronized(this) {
// Now we have a lock, double check there's still no serializer
// and create one if so.
if (null == this.defaultSerializer) {
// As the serializers are intended to be immutable, creating
// two due to a race condition should not be a problem, however
// to be safe we ensure only one exists for each network.
this.defaultSerializer = getSerializer(false);
}
}
}
return defaultSerializer;
}
/**
* Construct and return a custom serializer.
*/
public abstract BitcoinSerializer getSerializer(boolean parseRetain);
/**
* The number of blocks in the last {@link getMajorityWindow()} blocks
* at which to trigger a notice to the user to upgrade their client, where
* the client does not understand those blocks.
*/
public int getMajorityEnforceBlockUpgrade() {
return majorityEnforceBlockUpgrade;
}
/**
* The number of blocks in the last {@link getMajorityWindow()} blocks
* at which to enforce the requirement that all new blocks are of the
* newer type (i.e. outdated blocks are rejected).
*/
public int getMajorityRejectBlockOutdated() {
return majorityRejectBlockOutdated;
}
/**
* The sampling window from which the version numbers of blocks are taken
* in order to determine if a new block version is now the majority.
*/
public int getMajorityWindow() {
return majorityWindow;
}
/**
* The flags indicating which block validation tests should be applied to
* the given block. Enables support for alternative blockchains which enable
* tests based on different criteria.
*
* @param block block to determine flags for.
* @param height height of the block, if known, null otherwise. Returned
* tests should be a safe subset if block height is unknown.
*/
public EnumSet<Block.VerifyFlag> getBlockVerificationFlags(final Block block,
final VersionTally tally, final Integer height) {
final EnumSet<Block.VerifyFlag> flags = EnumSet.noneOf(Block.VerifyFlag.class);
if (block.isBIP34()) {
final Integer count = tally.getCountAtOrAbove(Block.BLOCK_VERSION_BIP34);
if (null != count && count >= getMajorityEnforceBlockUpgrade()) {
flags.add(Block.VerifyFlag.HEIGHT_IN_COINBASE);
}
}
return flags;
}
/**
* The flags indicating which script validation tests should be applied to
* the given transaction. Enables support for alternative blockchains which enable
* tests based on different criteria.
*
* @param block block the transaction belongs to.
* @param transaction to determine flags for.
* @param height height of the block, if known, null otherwise. Returned
* tests should be a safe subset if block height is unknown.
*/
public EnumSet<Script.VerifyFlag> getTransactionVerificationFlags(final Block block,
final Transaction transaction, final VersionTally tally, final Integer height) {
final EnumSet<Script.VerifyFlag> verifyFlags = EnumSet.noneOf(Script.VerifyFlag.class);
if (block.getTimeSeconds() >= NetworkParameters.BIP16_ENFORCE_TIME)
verifyFlags.add(Script.VerifyFlag.P2SH);
// Start enforcing CHECKLOCKTIMEVERIFY, (BIP65) for block.nVersion=4
// blocks, when 75% of the network has upgraded:
if (block.getVersion() >= Block.BLOCK_VERSION_BIP65 &&
tally.getCountAtOrAbove(Block.BLOCK_VERSION_BIP65) > this.getMajorityEnforceBlockUpgrade()) {
verifyFlags.add(Script.VerifyFlag.CHECKLOCKTIMEVERIFY);
}
return verifyFlags;
}
public abstract int getProtocolVersionNum(final ProtocolVersion version);
public static enum ProtocolVersion {
MINIMUM(70000),
PONG(60001),
BLOOM_FILTER(70000),
CURRENT(70001);
private final int bitcoinProtocol;
ProtocolVersion(final int bitcoinProtocol) {
this.bitcoinProtocol = bitcoinProtocol;
}
public int getBitcoinProtocolVersion() {
return bitcoinProtocol;
}
}
}