/** * 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 com.matthewmitchell.nubitsj.core; import com.matthewmitchell.nubitsj.params.*; import com.matthewmitchell.nubitsj.script.Script; import com.matthewmitchell.nubitsj.script.ScriptOpCodes; import com.matthewmitchell.nubitsj.net.discovery.HttpDiscovery; import com.google.common.base.Objects; import javax.annotation.Nullable; import java.io.ByteArrayOutputStream; import java.io.Serializable; import java.math.BigInteger; import java.util.*; import static com.google.common.base.Preconditions.checkState; import static com.matthewmitchell.nubitsj.core.Coin.*; import com.matthewmitchell.nubitsj.utils.MonetaryFormat; /** * <p>NetworkParameters contains the data needed for working with an instantiation of a Nubits 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 extends CoinDetails implements Serializable { /** * The protocol version this library implements. */ public static final int PROTOCOL_VERSION = 50000; /** The string returned by getId() for the main, production network where people trade things. */ public static final String ID_MAINNET = "org.nubits.production"; /** Unit test network. */ public static final String ID_UNITTESTNET = "com.matthewmitchell.nubitsj.unittest"; /** The string used by the payment protocol to represent the main net. */ public static final String PAYMENT_PROTOCOL_ID_MAINNET = "main"; protected Block genesisBlock; protected int port; protected long packetMagic; protected int dumpedPrivateKeyHeader; protected int interval; protected int targetTimespan; protected int bip32HeaderPub; protected int bip32HeaderPriv; /** * The depth of blocks required for a coinbase transaction to be spendable. */ protected int spendableCoinbaseDepth; protected String[] dnsSeeds; protected int[] addrSeeds; protected HttpDiscovery.Details[] httpSeeds = {}; protected Map<Integer, Sha256Hash> checkpoints = new HashMap<Integer, Sha256Hash>(); protected NetworkParameters() { genesisBlock = createGenesis(this); } private static Block createGenesis(NetworkParameters n) { Block genesisBlock = new Block(n); Transaction t = new Transaction(n, Transaction.NUSHARES); t.setTime(1407023435); try { // A script containing the difficulty bits and the following message: // // "Why Argentina's default feels like American bullying: Don Pittis" byte[] bytes = Utils.HEX.decode ("04ffff001d020f274c4c323031342d30382d30313a2057687920417267656e74696e6127732064656661756c74206665656c73206c696b6520416d65726963616e2062756c6c79696e673a20446f6e20506974746973"); t.addInput(new TransactionInput(n, t, bytes)); ByteArrayOutputStream scriptPubKeyBytes = new ByteArrayOutputStream(); t.addOutput(new TransactionOutput(n, t, ZERO, scriptPubKeyBytes.toByteArray())); } catch (Exception e) { // Cannot happen. throw new RuntimeException(e); } genesisBlock.addTransaction(t); String merkleHash = genesisBlock.getMerkleRoot().toString(); checkState(merkleHash.equals("3e6c2608685f1d66d8fe9cb798400ec16aec1574b7ad9a7a92a65c7fcea2d32a"), merkleHash); return genesisBlock; } public static final int TARGET_TIMESPAN = 7 * 24 * 60 * 60; // 1 day. public static final int TARGET_SPACING = 10 * 60; // 10 minutes per block. public static final int INTERVAL = 1; // Every block /** * 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; public static final long MAX_COINS = 200000000000L; public static final Coin MAX_MONEY = COIN.multiply(MAX_COINS); /** 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(); } public abstract String getPaymentProtocolId(); @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; NetworkParameters other = (NetworkParameters) o; return getId().equals(other.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_UNITTESTNET)) { return UnitTestParams.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 { return null; } } public int getSpendableCoinbaseDepth() { return spendableCoinbaseDepth; } /** * Returns true if the NetworkParameters is for a ShapeShift coin. ie. not NuBits */ @Override public boolean isShapeShift() { return false; } /** * 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; } /** 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 Nubits 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 prod networks contain the timestamp of when they were created, * and a message in the coinbase transaction. It says, <i>"Why Argentina's default feels like American * bullying: Don Pittis"</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 dumped private key. See {@link com.matthewmitchell.nubitsj.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 production Nubits networks use 2 weeks (1209600 seconds). */ public int getTargetTimespan() { return targetTimespan; } /** * 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. Nubits standardises this to be 2015. */ public int getInterval() { return interval; } /** * Used to parse a coin string into a Monetary for this network. */ @Override public Coin parseCoin(String str) { return Coin.parseCoin(str); } /** 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 getMinOutputValue(); /** * 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(); }