/**
* 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();
}