Add getters/setters and a solve method to the Block object. Use this in a new proof of work unit test.

Introduce a unit test NetworkParameters that has very easy difficulty.
Correct some assertTrue(false) type checks to use fail() instead.
Make ALLOWED_TIME_DRIFT non-public until I have a good explanation in the javadocs of what it's for.
Simplify Block.equals
This commit is contained in:
Mike Hearn
2011-03-08 15:23:06 +00:00
parent 38bf9a8a80
commit 4003eee3fe
11 changed files with 533 additions and 124 deletions

View File

@@ -24,6 +24,7 @@ import java.math.BigInteger;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
// Tests still to write:
// - Rest of checkDifficultyTransitions: verify we don't accept invalid transitions.
@@ -50,18 +51,13 @@ public class BlockChainTest {
Block b2 = getBlock2();
// Let's try adding an invalid block.
long n = b2.nonce;
long n = b2.getNonce();
try {
// TODO: Encapsulate these fields behind setters that recalc the hash automatically.
b2.nonce = 12345;
b2.hash = null;
b2.setNonce(12345);
chain.add(b2);
// We should not get here.
assertTrue(false);
fail();
} catch (VerificationException e) {
// Pass.
b2.nonce = n;
b2.hash = null;
b2.setNonce(n);
}
assertTrue(chain.add(b2));
}
@@ -74,20 +70,20 @@ public class BlockChainTest {
NetworkParameters params2 = NetworkParameters.testNet();
Block bad = new Block(params2);
// Merkle root can be anything here, doesn't matter.
bad.merkleRoot = Hex.decode("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
bad.setMerkleRoot(Hex.decode("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
// Nonce was just some number that made the hash < difficulty limit set below, it can be anything.
bad.nonce = 140548933;
bad.time = 1279242649;
bad.prevBlockHash = b2.getHash();
bad.setNonce(140548933);
bad.setTime(1279242649);
bad.setPrevBlockHash(b2.getHash());
// We're going to make this block so easy 50% of solutions will pass, and check it gets rejected for having a
// bad difficulty target. Unfortunately the encoding mechanism means we cannot make one that accepts all
// solutions.
bad.difficultyTarget = 0x207fFFFFL;
bad.setDifficultyTarget(Block.EASIEST_DIFFICULTY_TARGET);
try {
chain.add(bad);
// The difficulty target above should be rejected on the grounds of being easier than the networks
// allowable difficulty.
assertTrue(false);
fail();
} catch (VerificationException e) {
assertTrue(e.getMessage(), e.getMessage().indexOf("Difficulty target is bad") >= 0);
}
@@ -98,7 +94,7 @@ public class BlockChainTest {
try {
chain.add(bad);
// We should not get here as the difficulty target should not be changing at this point.
assertTrue(false);
fail();
} catch (VerificationException e) {
assertTrue(e.getMessage(), e.getMessage().indexOf("Unexpected change in difficulty") >= 0);
}
@@ -108,11 +104,10 @@ public class BlockChainTest {
private Block getBlock2() throws Exception {
Block b2 = new Block(params);
b2.merkleRoot = Hex.decode("addc858a17e21e68350f968ccd384d6439b64aafa6c193c8b9dd66320470838b");
b2.nonce = 2642058077L;
b2.time = 1296734343;
b2.prevBlockHash =
Hex.decode("000000033cc282bc1fa9dcae7a533263fd7fe66490f550d80076433340831604");
b2.setMerkleRoot(Hex.decode("addc858a17e21e68350f968ccd384d6439b64aafa6c193c8b9dd66320470838b"));
b2.setNonce(2642058077L);
b2.setTime(1296734343L);
b2.setPrevBlockHash(Hex.decode("000000033cc282bc1fa9dcae7a533263fd7fe66490f550d80076433340831604"));
assertEquals("000000037b21cac5d30fc6fda2581cf7b2612908aed2abbcc429c45b0557a15f", b2.getHashAsString());
b2.verify();
return b2;
@@ -120,10 +115,10 @@ public class BlockChainTest {
private Block getBlock1() throws Exception {
Block b1 = new Block(params);
b1.merkleRoot = Hex.decode("0e8e58ecdacaa7b3c6304a35ae4ffff964816d2b80b62b58558866ce4e648c10");
b1.nonce = 236038445;
b1.time = 1296734340;
b1.prevBlockHash = Hex.decode("00000007199508e34a9ff81e6ec0c477a4cccff2a4767a8eee39c11db367b008");
b1.setMerkleRoot(Hex.decode("0e8e58ecdacaa7b3c6304a35ae4ffff964816d2b80b62b58558866ce4e648c10"));
b1.setNonce(236038445);
b1.setTime(1296734340);
b1.setPrevBlockHash(Hex.decode("00000007199508e34a9ff81e6ec0c477a4cccff2a4767a8eee39c11db367b008"));
assertEquals("000000033cc282bc1fa9dcae7a533263fd7fe66490f550d80076433340831604", b1.getHashAsString());
b1.verify();
return b1;

View File

@@ -25,13 +25,10 @@ import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Arrays;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.*;
public class BlockTest {
static final NetworkParameters params = NetworkParameters.testNet();
static final byte[] blockBytes;
static {
@@ -44,6 +41,38 @@ public class BlockTest {
public void testBlockVerification() throws Exception {
Block block = new Block(params, blockBytes);
block.verify();
assertEquals("00000000a6e5eb79dcec11897af55e90cd571a4335383a3ccfbc12ec81085935", block.getHashAsString());
}
@Test
public void testProofOfWork() throws Exception {
// This params accepts any difficulty target.
NetworkParameters params = NetworkParameters.unitTests();
Block block = new Block(params, blockBytes);
block.setNonce(12346);
try {
block.verify();
fail();
} catch (VerificationException e) {
// Expected.
}
// Blocks contain their own difficulty target. The BlockChain verification mechanism is what stops real blocks
// from containing artificially weak difficulties.
block.setDifficultyTarget(Block.EASIEST_DIFFICULTY_TARGET);
// Now it should pass.
block.verify();
// Break the nonce again at the lower difficulty level so we can try solving for it.
block.setNonce(1);
try {
block.verify();
fail();
} catch (VerificationException e) {
// Expected to fail as the nonce is no longer correct.
}
// Should find an acceptable nonce.
block.solve();
block.verify();
assertEquals(block.getNonce(), 2);
}
@Test
@@ -56,7 +85,7 @@ public class BlockTest {
block.transactions.set(1, tx1);
try {
block.verify();
assertTrue("Verified when should not.", false);
fail();
} catch (VerificationException e) {
// We should get here.
}