3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-02-07 14:54:15 +00:00

NetworkParameters: Refactor out into separate classes.

Hide fields behind getters and make unit tests create anonymous subclasses
to tweak them rather than overwriting global variables.

Introduce a regtest params class for use in the comparison tool.

Conflicts:
	core/src/test/java/com/google/bitcoin/core/BitcoindComparisonTool.java
	core/src/test/java/com/google/bitcoin/core/FullPrunedBlockChainTest.java
This commit is contained in:
Mike Hearn 2013-05-08 15:15:02 +02:00
parent f6f290cc05
commit 52586edb33
16 changed files with 424 additions and 236 deletions

View File

@ -716,7 +716,7 @@ public abstract class AbstractBlockChain {
Block prev = storedPrev.getHeader();
// Is this supposed to be a difficulty transition point?
if ((storedPrev.getHeight() + 1) % params.interval != 0) {
if ((storedPrev.getHeight() + 1) % params.getInterval() != 0) {
// TODO: Refactor this hack after 0.5 is released and we stop supporting deserialization compatibility.
// This should be a method of the NetworkParameters, which should in turn be using singletons and a subclass
@ -738,7 +738,7 @@ public abstract class AbstractBlockChain {
// two weeks after the initial block chain download.
long now = System.currentTimeMillis();
StoredBlock cursor = blockStore.get(prev.getHash());
for (int i = 0; i < params.interval - 1; i++) {
for (int i = 0; i < params.getInterval() - 1; i++) {
if (cursor == null) {
// This should never happen. If it does, it means we are following an incorrect or busted chain.
throw new VerificationException(
@ -763,9 +763,9 @@ public abstract class AbstractBlockChain {
newDifficulty = newDifficulty.multiply(BigInteger.valueOf(timespan));
newDifficulty = newDifficulty.divide(BigInteger.valueOf(targetTimespan));
if (newDifficulty.compareTo(params.proofOfWorkLimit) > 0) {
if (newDifficulty.compareTo(params.getProofOfWorkLimit()) > 0) {
log.info("Difficulty hit proof of work limit: {}", newDifficulty.toString(16));
newDifficulty = params.proofOfWorkLimit;
newDifficulty = params.getProofOfWorkLimit();
}
int accuracyBytes = (int) (nextBlock.getDifficultyTarget() >>> 24) - 3;
@ -793,8 +793,8 @@ public abstract class AbstractBlockChain {
// that difficulty is equal to that one.
StoredBlock cursor = storedPrev;
while (!cursor.getHeader().equals(params.getGenesisBlock()) &&
cursor.getHeight() % params.interval != 0 &&
cursor.getHeader().getDifficultyTargetAsInteger().equals(params.proofOfWorkLimit))
cursor.getHeight() % params.getInterval() != 0 &&
cursor.getHeader().getDifficultyTargetAsInteger().equals(params.getProofOfWorkLimit()))
cursor = cursor.getPrev(blockStore);
BigInteger cursorDifficulty = cursor.getHeader().getDifficultyTargetAsInteger();
BigInteger newDifficulty = next.getDifficultyTargetAsInteger();

View File

@ -114,7 +114,7 @@ public class AlertMessage extends Message {
* doesn't verify, because that would allow arbitrary attackers to spam your users.
*/
public boolean isSignatureValid() {
return ECKey.verify(Utils.doubleDigest(content), signature, params.alertSigningKey);
return ECKey.verify(Utils.doubleDigest(content), signature, params.getAlertSigningKey());
}
@Override

View File

@ -865,7 +865,7 @@ public class Block extends Message {
return new Date(getTimeSeconds()*1000);
}
void setTime(long time) {
public void setTime(long time) {
unCacheHeader();
this.time = time;
this.hash = null;

View File

@ -16,6 +16,10 @@
package com.google.bitcoin.core;
import com.google.bitcoin.params.MainNetParams;
import com.google.bitcoin.params.TestNet2Params;
import com.google.bitcoin.params.TestNet3Params;
import com.google.bitcoin.params.UnitTestParams;
import com.google.bitcoin.script.Script;
import com.google.bitcoin.script.ScriptOpCodes;
import com.google.common.base.Objects;
@ -28,15 +32,14 @@ import java.util.HashMap;
import java.util.Map;
import static com.google.bitcoin.core.Utils.COIN;
import static com.google.common.base.Preconditions.checkState;
/**
* <p>NetworkParameters contains the data needed for working with an instantiation of a Bitcoin chain.</p>
*
* <p></p>Currently there are only two, the production chain and the test chain. There is also a "unit test chain" which
* <p>Currently there are only two, the production chain and the test chain. There is also a "unit test chain" which
* is internal to bitcoinj and can't be used on a real network. In future there may be others. </p>
*/
public class NetworkParameters implements Serializable {
public abstract class NetworkParameters implements Serializable {
/**
* The protocol version this library implements.
*/
@ -58,148 +61,35 @@ public class NetworkParameters implements Serializable {
// TODO: Replace with getters and then finish making all these fields final.
private final Block genesisBlock;
/** What the easiest allowable proof of work should be. */
public /*final*/ BigInteger proofOfWorkLimit;
private final int port;
private final long packetMagic;
private final int addressHeader;
private final int dumpedPrivateKeyHeader;
/** How many blocks pass between difficulty adjustment periods. Bitcoin standardises this to be 2015. */
public /*final*/ int interval;
private final int targetTimespan;
/**
* The key used to sign {@link AlertMessage}s. You can use {@link ECKey#verify(byte[], byte[], byte[])} to verify
* signatures using it.
*/
public /*final*/ byte[] alertSigningKey;
protected Block genesisBlock;
protected BigInteger proofOfWorkLimit;
protected int port;
protected long packetMagic;
protected int addressHeader;
protected int dumpedPrivateKeyHeader;
protected int interval;
protected int targetTimespan;
protected byte[] alertSigningKey;
/**
* See getId(). This may be null for old deserialized wallets. In that case we derive it heuristically
* by looking at the port number.
*/
private final String id;
protected String id;
/**
* The depth of blocks required for a coinbase transaction to be spendable.
*/
private final int spendableCoinbaseDepth;
private /*final*/ int subsidyDecreaseBlockCount;
protected int spendableCoinbaseDepth;
protected int subsidyDecreaseBlockCount;
/**
* If we are running in testnet-in-a-box mode, we allow connections to nodes with 0 non-genesis blocks
*/
boolean allowEmptyPeerChains;
private final int[] acceptableAddressCodes;
private final String[] dnsSeeds;
private Map<Integer, Sha256Hash> checkpoints = new HashMap<Integer, Sha256Hash>();
protected int[] acceptableAddressCodes;
protected String[] dnsSeeds;
protected Map<Integer, Sha256Hash> checkpoints = new HashMap<Integer, Sha256Hash>();
private NetworkParameters(int type) {
protected NetworkParameters() {
alertSigningKey = SATOSHI_KEY;
genesisBlock = createGenesis(this);
if (type == 0) {
// Production.
interval = INTERVAL;
targetTimespan = TARGET_TIMESPAN;
proofOfWorkLimit = Utils.decodeCompactBits(0x1d00ffffL);
acceptableAddressCodes = new int[] { 0 };
dumpedPrivateKeyHeader = 128;
addressHeader = 0;
port = 8333;
packetMagic = 0xf9beb4d9L;
genesisBlock.setDifficultyTarget(0x1d00ffffL);
genesisBlock.setTime(1231006505L);
genesisBlock.setNonce(2083236893);
id = ID_PRODNET;
subsidyDecreaseBlockCount = 210000;
allowEmptyPeerChains = false;
spendableCoinbaseDepth = 100;
String genesisHash = genesisBlock.getHashAsString();
checkState(genesisHash.equals("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"),
genesisHash);
// This contains (at a minimum) the blocks which are not BIP30 compliant. BIP30 changed how duplicate
// transactions are handled. Duplicated transactions could occur in the case where a coinbase had the same
// extraNonce and the same outputs but appeared at different heights, and greatly complicated re-org handling.
// Having these here simplifies block connection logic considerably.
checkpoints.put(91722, new Sha256Hash("00000000000271a2dc26e7667f8419f2e15416dc6955e5a6c6cdf3f2574dd08e"));
checkpoints.put(91812, new Sha256Hash("00000000000af0aed4792b1acee3d966af36cf5def14935db8de83d6f9306f2f"));
checkpoints.put(91842, new Sha256Hash("00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec"));
checkpoints.put(91880, new Sha256Hash("00000000000743f190a18c5577a3c2d2a1f610ae9601ac046a38084ccb7cd721"));
checkpoints.put(200000, new Sha256Hash("000000000000034a7dedef4a161fa058a2d67a173a90155f3a2fe6fc132e0ebf"));
dnsSeeds = new String[] {
"seed.bitcoin.sipa.be", // Pieter Wuille
"dnsseed.bluematt.me", // Matt Corallo
"dnsseed.bitcoin.dashjr.org", // Luke Dashjr
"dnsseed.plan99.net", // Mike Hearn
};
} else if (type == 3) {
// Testnet3
id = ID_TESTNET;
// Genesis hash is 000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943
packetMagic = 0x0b110907;
interval = INTERVAL;
targetTimespan = TARGET_TIMESPAN;
proofOfWorkLimit = Utils.decodeCompactBits(0x1d00ffffL);
port = 18333;
addressHeader = 111;
acceptableAddressCodes = new int[] { 111 };
dumpedPrivateKeyHeader = 239;
genesisBlock.setTime(1296688602L);
genesisBlock.setDifficultyTarget(0x1d00ffffL);
genesisBlock.setNonce(414098458);
allowEmptyPeerChains = true;
spendableCoinbaseDepth = 100;
subsidyDecreaseBlockCount = 210000;
String genesisHash = genesisBlock.getHashAsString();
checkState(genesisHash.equals("000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943"),
genesisHash);
dnsSeeds = new String[] {
"testnet-seed.bitcoin.petertodd.org",
"testnet-seed.bluematt.me"
};
} else if (type == 2) {
id = ID_TESTNET;
packetMagic = 0xfabfb5daL;
port = 18333;
addressHeader = 111;
interval = INTERVAL;
targetTimespan = TARGET_TIMESPAN;
proofOfWorkLimit = Utils.decodeCompactBits(0x1d0fffffL);
acceptableAddressCodes = new int[] { 111 };
dumpedPrivateKeyHeader = 239;
genesisBlock.setTime(1296688602L);
genesisBlock.setDifficultyTarget(0x1d07fff8L);
genesisBlock.setNonce(384568319);
allowEmptyPeerChains = false;
spendableCoinbaseDepth = 100;
subsidyDecreaseBlockCount = 210000;
String genesisHash = genesisBlock.getHashAsString();
checkState(genesisHash.equals("00000007199508e34a9ff81e6ec0c477a4cccff2a4767a8eee39c11db367b008"),
genesisHash);
dnsSeeds = null;
} else if (type == -1) {
id = ID_UNITTESTNET;
packetMagic = 0x0b110907;
addressHeader = 111;
proofOfWorkLimit = new BigInteger("00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16);
genesisBlock.setTime(System.currentTimeMillis() / 1000);
genesisBlock.setDifficultyTarget(Block.EASIEST_DIFFICULTY_TARGET);
genesisBlock.solve();
port = 18333;
interval = 10;
dumpedPrivateKeyHeader = 239;
allowEmptyPeerChains = false;
targetTimespan = 200000000; // 6 years. Just a very big number.
spendableCoinbaseDepth = 5;
acceptableAddressCodes = new int[] { 111 };
subsidyDecreaseBlockCount = 100;
dnsSeeds = null;
} else {
throw new RuntimeException();
}
}
private static Block createGenesis(NetworkParameters n) {
@ -241,43 +131,29 @@ public class NetworkParameters implements Serializable {
*/
public static final BigInteger MAX_MONEY = new BigInteger("21000000", 10).multiply(COIN);
/** Returns whatever the latest testNet parameters are. Use this rather than the versioned equivalents. */
/** Alias for TestNet3Params.get(), use that instead. */
public static NetworkParameters testNet() {
return testNet3();
return TestNet3Params.get();
}
private static NetworkParameters tn2;
public synchronized static NetworkParameters testNet2() {
if (tn2 == null) {
tn2 = new NetworkParameters(2);
}
return tn2;
/** Alias for TestNet2Params.get(), use that instead. */
public static NetworkParameters testNet2() {
return TestNet2Params.get();
}
private static NetworkParameters tn3;
public synchronized static NetworkParameters testNet3() {
if (tn3 == null) {
tn3 = new NetworkParameters(3);
}
return tn3;
/** Alias for TestNet3Params.get(), use that instead. */
public static NetworkParameters testNet3() {
return TestNet3Params.get();
}
private static NetworkParameters pn;
/** The primary Bitcoin chain created by Satoshi. */
public synchronized static NetworkParameters prodNet() {
if (pn == null) {
pn = new NetworkParameters(0);
}
return pn;
/** Alias for MainNetParams.get(), use that instead */
public static NetworkParameters prodNet() {
return MainNetParams.get();
}
private static NetworkParameters ut;
/** Returns a testnet params modified to allow any difficulty target. */
public synchronized static NetworkParameters unitTests() {
if (ut == null) {
ut = new NetworkParameters(-1);
}
return ut;
public static NetworkParameters unitTests() {
return UnitTestParams.get();
}
/**
@ -336,10 +212,6 @@ public class NetworkParameters implements Serializable {
return subsidyDecreaseBlockCount;
}
public void setSubsidyDecreaseBlockCount(int value) {
subsidyDecreaseBlockCount = value;
}
/** Returns DNS names that when resolved, give IP addresses of active peers. */
public String[] getDnsSeeds() {
return dnsSeeds;
@ -401,4 +273,29 @@ public class NetworkParameters implements Serializable {
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 2015. */
public int getInterval() {
return interval;
}
/** What the easiest allowable proof of work should be. */
public BigInteger getProofOfWorkLimit() {
return proofOfWorkLimit;
}
/**
* The key used to sign {@link com.google.bitcoin.core.AlertMessage}s. You can use {@link com.google.bitcoin.core.ECKey#verify(byte[], byte[], byte[])} to verify
* signatures using it.
*/
public byte[] getAlertSigningKey() {
return alertSigningKey;
}
}

View File

@ -1253,7 +1253,7 @@ public class Peer {
// chainHeight should not be zero/negative because we shouldn't have given the user a Peer that is to another
// client-mode node, nor should it be unconnected. If that happens it means the user overrode us somewhere or
// there is a bug in the peer management code.
checkState(params.allowEmptyPeerChains || chainHeight > 0, "Connected to peer with zero/negative chain height", chainHeight);
checkState(params.allowEmptyPeerChain() || chainHeight > 0, "Connected to peer with zero/negative chain height", chainHeight);
return chainHeight - blockChain.getBestChainHeight();
}

View File

@ -158,7 +158,7 @@ public class TCPNetworkConnection implements NetworkConnection {
// implementations claim to have a block chain in their services field but then report a height of zero, filter
// them out here.
if (!versionMessage.hasBlockChain() ||
(!params.allowEmptyPeerChains && versionMessage.bestHeight <= 0)) {
(!params.allowEmptyPeerChain() && versionMessage.bestHeight <= 0)) {
// Shut down the channel
throw new ProtocolException("Peer does not have a copy of the block chain.");
}

View File

@ -0,0 +1,74 @@
/*
* Copyright 2013 Google Inc.
*
* 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.google.bitcoin.params;
import com.google.bitcoin.core.NetworkParameters;
import com.google.bitcoin.core.Sha256Hash;
import com.google.bitcoin.core.Utils;
import static com.google.common.base.Preconditions.checkState;
/**
* Parameters for the main production network on which people trade goods and services.
*/
public class MainNetParams extends NetworkParameters {
public MainNetParams() {
super();
interval = INTERVAL;
targetTimespan = TARGET_TIMESPAN;
proofOfWorkLimit = Utils.decodeCompactBits(0x1d00ffffL);
acceptableAddressCodes = new int[] { 0 };
dumpedPrivateKeyHeader = 128;
addressHeader = 0;
port = 8333;
packetMagic = 0xf9beb4d9L;
genesisBlock.setDifficultyTarget(0x1d00ffffL);
genesisBlock.setTime(1231006505L);
genesisBlock.setNonce(2083236893);
id = ID_PRODNET;
subsidyDecreaseBlockCount = 210000;
spendableCoinbaseDepth = 100;
String genesisHash = genesisBlock.getHashAsString();
checkState(genesisHash.equals("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"),
genesisHash);
// This contains (at a minimum) the blocks which are not BIP30 compliant. BIP30 changed how duplicate
// transactions are handled. Duplicated transactions could occur in the case where a coinbase had the same
// extraNonce and the same outputs but appeared at different heights, and greatly complicated re-org handling.
// Having these here simplifies block connection logic considerably.
checkpoints.put(91722, new Sha256Hash("00000000000271a2dc26e7667f8419f2e15416dc6955e5a6c6cdf3f2574dd08e"));
checkpoints.put(91812, new Sha256Hash("00000000000af0aed4792b1acee3d966af36cf5def14935db8de83d6f9306f2f"));
checkpoints.put(91842, new Sha256Hash("00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec"));
checkpoints.put(91880, new Sha256Hash("00000000000743f190a18c5577a3c2d2a1f610ae9601ac046a38084ccb7cd721"));
checkpoints.put(200000, new Sha256Hash("000000000000034a7dedef4a161fa058a2d67a173a90155f3a2fe6fc132e0ebf"));
dnsSeeds = new String[] {
"seed.bitcoin.sipa.be", // Pieter Wuille
"dnsseed.bluematt.me", // Matt Corallo
"dnsseed.bitcoin.dashjr.org", // Luke Dashjr
"dnsseed.plan99.net", // Mike Hearn
};
}
private static MainNetParams instance;
public static synchronized MainNetParams get() {
if (instance == null) {
instance = new MainNetParams();
}
return instance;
}
}

View File

@ -0,0 +1,58 @@
/*
* Copyright 2013 Google Inc.
*
* 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.google.bitcoin.params;
import com.google.bitcoin.core.Block;
import java.math.BigInteger;
import static com.google.common.base.Preconditions.checkState;
/**
* Network parameters for the regression test mode of bitcoind in which all blocks are trivially solvable.
*/
public class RegTestParams extends TestNet2Params {
private static final BigInteger PROOF_OF_WORK_LIMIT = new BigInteger("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16);
public RegTestParams() {
interval = 10000;
proofOfWorkLimit = PROOF_OF_WORK_LIMIT;
subsidyDecreaseBlockCount = 10000;
port = 18444;
}
@Override
public boolean allowEmptyPeerChain() {
return true;
}
private static Block genesis;
@Override
public Block getGenesisBlock() {
synchronized (RegTestParams.class) {
if (genesis == null) {
genesis = super.getGenesisBlock();
genesis.setNonce(2);
genesis.setDifficultyTarget(0x207fFFFFL);
genesis.setTime(1296688602L);
checkState(genesis.getHashAsString().toLowerCase().equals("0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206"));
}
return genesis;
}
}
}

View File

@ -0,0 +1,57 @@
/*
* Copyright 2013 Google Inc.
*
* 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.google.bitcoin.params;
import com.google.bitcoin.core.NetworkParameters;
import com.google.bitcoin.core.Utils;
import static com.google.common.base.Preconditions.checkState;
/**
* Parameters for the old version 2 testnet. This is not useful to you - it exists only because some unit tests are
* based on it.
*/
public class TestNet2Params extends NetworkParameters {
public TestNet2Params() {
super();
id = ID_TESTNET;
packetMagic = 0xfabfb5daL;
port = 18333;
addressHeader = 111;
interval = INTERVAL;
targetTimespan = TARGET_TIMESPAN;
proofOfWorkLimit = Utils.decodeCompactBits(0x1d0fffffL);
acceptableAddressCodes = new int[] { 111 };
dumpedPrivateKeyHeader = 239;
genesisBlock.setTime(1296688602L);
genesisBlock.setDifficultyTarget(0x1d07fff8L);
genesisBlock.setNonce(384568319);
spendableCoinbaseDepth = 100;
subsidyDecreaseBlockCount = 210000;
String genesisHash = genesisBlock.getHashAsString();
checkState(genesisHash.equals("00000007199508e34a9ff81e6ec0c477a4cccff2a4767a8eee39c11db367b008"));
dnsSeeds = null;
}
private static TestNet2Params instance;
public static synchronized TestNet2Params get() {
if (instance == null) {
instance = new TestNet2Params();
}
return instance;
}
}

View File

@ -0,0 +1,62 @@
/*
* Copyright 2013 Google Inc.
*
* 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.google.bitcoin.params;
import com.google.bitcoin.core.NetworkParameters;
import com.google.bitcoin.core.Utils;
import static com.google.common.base.Preconditions.checkState;
/**
* Parameters for the testnet, a separate public instance of Bitcoin that has relaxed rules suitable for development
* and testing of applications and new Bitcoin versions.
*/
public class TestNet3Params extends NetworkParameters {
public TestNet3Params() {
super();
id = ID_TESTNET;
// Genesis hash is 000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943
packetMagic = 0x0b110907;
interval = INTERVAL;
targetTimespan = TARGET_TIMESPAN;
proofOfWorkLimit = Utils.decodeCompactBits(0x1d00ffffL);
port = 18333;
addressHeader = 111;
acceptableAddressCodes = new int[] { 111 };
dumpedPrivateKeyHeader = 239;
genesisBlock.setTime(1296688602L);
genesisBlock.setDifficultyTarget(0x1d00ffffL);
genesisBlock.setNonce(414098458);
spendableCoinbaseDepth = 100;
subsidyDecreaseBlockCount = 210000;
String genesisHash = genesisBlock.getHashAsString();
checkState(genesisHash.equals("000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943"));
dnsSeeds = new String[] {
"testnet-seed.bitcoin.petertodd.org",
"testnet-seed.bluematt.me"
};
}
private static TestNet3Params instance;
public static synchronized TestNet3Params get() {
if (instance == null) {
instance = new TestNet3Params();
}
return instance;
}
}

View File

@ -0,0 +1,55 @@
/*
* Copyright 2013 Google Inc.
*
* 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.google.bitcoin.params;
import com.google.bitcoin.core.Block;
import com.google.bitcoin.core.NetworkParameters;
import java.math.BigInteger;
/**
* Network parameters used by the bitcoinj unit tests (and potentially your own). This lets you solve a block using
* {@link com.google.bitcoin.core.Block#solve()} by setting difficulty to the easiest possible.
*/
public class UnitTestParams extends NetworkParameters {
public UnitTestParams() {
super();
id = ID_UNITTESTNET;
packetMagic = 0x0b110907;
addressHeader = 111;
proofOfWorkLimit = new BigInteger("00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16);
genesisBlock.setTime(System.currentTimeMillis() / 1000);
genesisBlock.setDifficultyTarget(Block.EASIEST_DIFFICULTY_TARGET);
genesisBlock.solve();
port = 18333;
interval = 10;
dumpedPrivateKeyHeader = 239;
targetTimespan = 200000000; // 6 years. Just a very big number.
spendableCoinbaseDepth = 5;
acceptableAddressCodes = new int[] { 111 };
subsidyDecreaseBlockCount = 100;
dnsSeeds = null;
}
private static UnitTestParams instance;
public static synchronized UnitTestParams get() {
if (instance == null) {
instance = new UnitTestParams();
}
return instance;
}
}

View File

@ -16,6 +16,7 @@
package com.google.bitcoin.core;
import com.google.bitcoin.params.UnitTestParams;
import org.junit.Before;
import org.junit.Test;
import org.spongycastle.util.encoders.Hex;
@ -29,9 +30,13 @@ public class AlertMessageTest {
@Before
public void setUp() throws Exception {
ECKey key = new ECKey(TEST_KEY_PRIV, null);
params = NetworkParameters.unitTests();
params.alertSigningKey = key.getPubKey();
final ECKey key = new ECKey(TEST_KEY_PRIV, null);
params = new UnitTestParams() {
@Override
public byte[] getAlertSigningKey() {
return key.getPubKey();
}
};
}
@Test

View File

@ -16,6 +16,7 @@
package com.google.bitcoin.core;
import com.google.bitcoin.params.RegTestParams;
import com.google.bitcoin.store.BlockStoreException;
import com.google.bitcoin.store.FullPrunedBlockStore;
import com.google.bitcoin.store.H2FullPrunedBlockStore;
@ -58,38 +59,15 @@ public class BitcoindComparisonTool {
System.out.println("USAGE: bitcoinjBlockStoreLocation runLargeReorgs(1/0) [port=18444]");
boolean runLargeReorgs = Integer.parseInt(args[1]) == 1;
params = NetworkParameters.testNet2();
/**
* The following have been changed from the default and do not match bitcoind's default.
* In order for this test to work, bitcoind should be recompiled with the same values you see here.
* You can also opt to comment out these lines to use the default, however that will cause this tool to be
* very significantly less efficient and useful (it will likely run forever trying to mine new blocks).
*
* You could also simply use git apply to apply the test-patches included with bitcoind
*/
// bnProofOfWorkLimit set in main.cpp
params.proofOfWorkLimit = new BigInteger("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16);
// Also set hashGenesisBlock to 0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206 one line up
// constant (210000) in GetBlockValue (main.cpp)
params.setSubsidyDecreaseBlockCount(150);
// block.nNonce/block.nBits in LoadBlockIndex not the ones under "if (fTestNet)"
params.getGenesisBlock().setNonce(2);
params.getGenesisBlock().setDifficultyTarget(0x207fFFFFL);
// Also set block.nTime = 1296688602; in the same block
params = new RegTestParams();
File blockFile = File.createTempFile("testBlocks", ".dat");
blockFile.deleteOnExit();
FullBlockTestGenerator generator = new FullBlockTestGenerator(params);
BlockAndValidityList blockList = generator.getBlocksToTest(true, runLargeReorgs, blockFile);
Iterator<Block> blocks = new BlockFileLoader(params, Arrays.asList(blockFile));
// Only needs to be set in bitcoinj
params.allowEmptyPeerChains = true;
try {
store = new H2FullPrunedBlockStore(params, args[0], blockList.maximumReorgBlockCount);
((H2FullPrunedBlockStore)store).resetStore();
@ -104,7 +82,7 @@ public class BitcoindComparisonTool {
peers.setUserAgent("BlockAcceptanceComparisonTool", "1.0");
// bitcoind MUST be on localhost or we will get banned as a DoSer
peers.addAddress(new PeerAddress(InetAddress.getByName("localhost"), args.length > 2 ? Integer.parseInt(args[2]) : 18444));
peers.addAddress(new PeerAddress(InetAddress.getByName("localhost"), args.length > 2 ? Integer.parseInt(args[2]) : params.getPort()));
final Set<Sha256Hash> blocksRequested = Collections.synchronizedSet(new HashSet<Sha256Hash>());
peers.addEventListener(new AbstractPeerEventListener() {

View File

@ -17,6 +17,7 @@
package com.google.bitcoin.core;
import com.google.bitcoin.core.Wallet.BalanceType;
import com.google.bitcoin.params.TestNet2Params;
import com.google.bitcoin.store.BlockStore;
import com.google.bitcoin.store.MemoryBlockStore;
import com.google.bitcoin.utils.BriefLogFormatter;
@ -35,7 +36,6 @@ import static org.junit.Assert.*;
// Handling of chain splits/reorgs are in ChainSplitTests.
public class BlockChainTest {
private static final NetworkParameters testNet = NetworkParameters.testNet2();
private BlockChain testNetChain;
private Wallet wallet;
@ -46,6 +46,13 @@ public class BlockChainTest {
private final StoredBlock[] block = new StoredBlock[1];
private Transaction coinbaseTransaction;
private static class TweakableTestNet2Params extends TestNet2Params {
public void setProofOfWorkLimit(BigInteger limit) {
proofOfWorkLimit = limit;
}
}
private static final TweakableTestNet2Params testNet = new TweakableTestNet2Params();
private void resetBlockStore() {
blockStore = new MemoryBlockStore(unitTestParams);
}
@ -54,6 +61,7 @@ public class BlockChainTest {
public void setUp() throws Exception {
BriefLogFormatter.initVerbose();
testNetChain = new BlockChain(testNet, new Wallet(testNet), new MemoryBlockStore(testNet));
unitTestParams = NetworkParameters.unitTests();
wallet = new Wallet(unitTestParams) {
@Override
@ -161,7 +169,7 @@ public class BlockChainTest {
// artificially shortened period.
Block prev = unitTestParams.getGenesisBlock();
Block.fakeClock = System.currentTimeMillis() / 1000;
for (int i = 0; i < unitTestParams.interval - 1; i++) {
for (int i = 0; i < unitTestParams.getInterval() - 1; i++) {
Block newBlock = prev.createNextBlock(coinbaseTo, Block.fakeClock);
assertTrue(chain.add(newBlock));
prev = newBlock;
@ -209,9 +217,9 @@ public class BlockChainTest {
}
// Accept any level of difficulty now.
BigInteger oldVal = testNet.proofOfWorkLimit;
testNet.proofOfWorkLimit = new BigInteger
("00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16);
BigInteger oldVal = testNet.getProofOfWorkLimit();
testNet.setProofOfWorkLimit(new BigInteger
("00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16));
try {
testNetChain.add(bad);
// We should not get here as the difficulty target should not be changing at this point.
@ -219,7 +227,7 @@ public class BlockChainTest {
} catch (VerificationException e) {
assertTrue(e.getMessage(), e.getCause().getMessage().contains("Unexpected change in difficulty"));
}
testNet.proofOfWorkLimit = oldVal;
testNet.setProofOfWorkLimit(oldVal);
// TODO: Test difficulty change is not out of range when a transition period becomes valid.
}

View File

@ -18,13 +18,13 @@
package com.google.bitcoin.core;
import com.google.bitcoin.core.Transaction.SigHash;
import com.google.bitcoin.params.UnitTestParams;
import com.google.bitcoin.script.Script;
import com.google.bitcoin.store.BlockStoreException;
import com.google.bitcoin.store.FullPrunedBlockStore;
import com.google.bitcoin.store.MemoryFullPrunedBlockStore;
import com.google.bitcoin.utils.BlockFileLoader;
import com.google.bitcoin.utils.BriefLogFormatter;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
@ -45,33 +45,28 @@ import static org.junit.Assert.*;
public class FullPrunedBlockChainTest {
private static final Logger log = LoggerFactory.getLogger(FullPrunedBlockChainTest.class);
private NetworkParameters unitTestParams;
private NetworkParameters params;
private FullPrunedBlockChain chain;
private FullPrunedBlockStore store;
private int oldInterval;
@Before
public void setUp() throws Exception {
BriefLogFormatter.init();
unitTestParams = NetworkParameters.unitTests();
oldInterval = unitTestParams.interval;
unitTestParams.interval = 10000;
params = new UnitTestParams() {
@Override public int getInterval() {
return 10000;
}
};
}
@After
public void tearDown() {
unitTestParams.interval = oldInterval;
}
@Test
public void testGeneratedChain() throws Exception {
// Tests various test cases from FullBlockTestGenerator
FullBlockTestGenerator generator = new FullBlockTestGenerator(unitTestParams);
// Tests various test cases from FullBlockTestGenerator
FullBlockTestGenerator generator = new FullBlockTestGenerator(params);
BlockAndValidityList blockList = generator.getBlocksToTest(false, false, null);
store = new MemoryFullPrunedBlockStore(unitTestParams, blockList.maximumReorgBlockCount);
chain = new FullPrunedBlockChain(unitTestParams, store);
store = new MemoryFullPrunedBlockStore(params, blockList.maximumReorgBlockCount);
chain = new FullPrunedBlockChain(params, store);
for (BlockAndValidity block : blockList.list) {
boolean threw = false;
@ -109,8 +104,8 @@ public class FullPrunedBlockChainTest {
@Test
public void testFinalizedBlocks() throws Exception {
final int UNDOABLE_BLOCKS_STORED = 10;
store = new MemoryFullPrunedBlockStore(unitTestParams, UNDOABLE_BLOCKS_STORED);
chain = new FullPrunedBlockChain(unitTestParams, store);
store = new MemoryFullPrunedBlockStore(params, UNDOABLE_BLOCKS_STORED);
chain = new FullPrunedBlockChain(params, store);
// Check that we aren't accidentally leaving any references
// to the full StoredUndoableBlock's lying around (ie memory leaks)
@ -118,11 +113,11 @@ public class FullPrunedBlockChainTest {
ECKey outKey = new ECKey();
// Build some blocks on genesis block to create a spendable output
Block rollingBlock = unitTestParams.getGenesisBlock().createNextBlockWithCoinbase(outKey.getPubKey());
Block rollingBlock = params.getGenesisBlock().createNextBlockWithCoinbase(outKey.getPubKey());
chain.add(rollingBlock);
TransactionOutPoint spendableOutput = new TransactionOutPoint(unitTestParams, 0, rollingBlock.getTransactions().get(0).getHash());
TransactionOutPoint spendableOutput = new TransactionOutPoint(params, 0, rollingBlock.getTransactions().get(0).getHash());
byte[] spendableOutputScriptPubKey = rollingBlock.getTransactions().get(0).getOutputs().get(0).getScriptBytes();
for (int i = 1; i < unitTestParams.getSpendableCoinbaseDepth(); i++) {
for (int i = 1; i < params.getSpendableCoinbaseDepth(); i++) {
rollingBlock = rollingBlock.createNextBlockWithCoinbase(outKey.getPubKey());
chain.add(rollingBlock);
}
@ -131,9 +126,9 @@ public class FullPrunedBlockChainTest {
(store.getTransactionOutput(spendableOutput.getHash(), spendableOutput.getIndex()));
rollingBlock = rollingBlock.createNextBlock(null);
Transaction t = new Transaction(unitTestParams);
Transaction t = new Transaction(params);
// Entirely invalid scriptPubKey
t.addOutput(new TransactionOutput(unitTestParams, t, Utils.toNanoCoins(50, 0), new byte[] {}));
t.addOutput(new TransactionOutput(params, t, Utils.toNanoCoins(50, 0), new byte[] {}));
addInputToTransaction(t, spendableOutput, spendableOutputScriptPubKey, outKey);
rollingBlock.addTransaction(t);
rollingBlock.solve();
@ -161,7 +156,7 @@ public class FullPrunedBlockChainTest {
}
private void addInputToTransaction(Transaction t, TransactionOutPoint prevOut, byte[] prevOutScriptPubKey, ECKey sigKey) throws ScriptException {
TransactionInput input = new TransactionInput(unitTestParams, t, new byte[]{}, prevOut);
TransactionInput input = new TransactionInput(params, t, new byte[]{}, prevOut);
t.addInput(input);
Sha256Hash hash = t.hashTransactionForSignature(0, prevOutScriptPubKey, SigHash.ALL, false);

View File

@ -3,7 +3,6 @@ package com.google.bitcoin.tools;
import com.google.bitcoin.core.*;
import com.google.bitcoin.store.BlockStore;
import com.google.bitcoin.store.MemoryBlockStore;
import com.google.bitcoin.store.SPVBlockStore;
import com.google.bitcoin.utils.BriefLogFormatter;
import java.io.*;
@ -43,7 +42,7 @@ public class BuildCheckpoints {
@Override
public void notifyNewBestBlock(StoredBlock block) throws VerificationException {
int height = block.getHeight();
if (height % params.interval == 0 && block.getHeader().getTimeSeconds() <= oneMonthAgo) {
if (height % params.getInterval() == 0 && block.getHeader().getTimeSeconds() <= oneMonthAgo) {
System.out.println(String.format("Checkpointing block %s at height %d",
block.getHeader().getHash(), block.getHeight()));
checkpoints.put(height, block);