BlockChain extends AbstractBlockChain { @Override public boolean add(FilteredBlock block) throws VerificationException, PrunedException { boolean success = super.add(block); if (success) { trackFilteredTransactions(block.getTransactionCount()); } return success; } BlockChain(NetworkParameters params, Wallet wallet, BlockStore blockStore);  BlockChain(NetworkParameters params, BlockStore blockStore);  BlockChain(NetworkParameters params, List<BlockChainListener> wallets,
                      BlockStore blockStore); @Override boolean add(FilteredBlock block);  }
@Test public void testBasicChaining() throws Exception { ListenableFuture<StoredBlock> future = testNetChain.getHeightFuture(2); Block b1 = getBlock1(); assertTrue(testNetChain.add(b1)); assertFalse(future.isDone()); Block b2 = getBlock2(); long n = b2.getNonce(); try { b2.setNonce(12345); testNetChain.add(b2); fail(); } catch (VerificationException e) { b2.setNonce(n); } assertTrue(testNetChain.add(b2)); assertTrue(future.isDone()); assertEquals(2, future.get().getHeight()); }
@Test public void receiveCoins() throws Exception { Transaction tx1 = createFakeTx(unitTestParams, Utils.toNanoCoins(1, 0), wallet.getKeys().get(0).toAddress(unitTestParams)); Block b1 = createFakeBlock(blockStore, tx1).block; chain.add(b1); assertTrue(wallet.getBalance().signum() > 0); }
@Test public void merkleRoots() throws Exception { Transaction tx1 = createFakeTx(unitTestParams, Utils.toNanoCoins(1, 0), wallet.getKeys().get(0).toAddress(unitTestParams)); Block b1 = createFakeBlock(blockStore, tx1).block; chain.add(b1); resetBlockStore(); Sha256Hash hash = b1.getMerkleRoot(); b1.setMerkleRoot(Sha256Hash.ZERO_HASH); try { chain.add(b1); fail(); } catch (VerificationException e) { b1.setMerkleRoot(hash); } Transaction tx2 = createFakeTx(unitTestParams, Utils.toNanoCoins(1, 0), new ECKey().toAddress(unitTestParams)); Block b2 = createFakeBlock(blockStore, tx2).block; b2.getMerkleRoot(); b2.setMerkleRoot(Sha256Hash.ZERO_HASH); b2.solve(); chain.add(b2); }
@Test public void unconnectedBlocks() throws Exception { Block b1 = unitTestParams.getGenesisBlock().createNextBlock(coinbaseTo); Block b2 = b1.createNextBlock(coinbaseTo); Block b3 = b2.createNextBlock(coinbaseTo); assertTrue(chain.add(b1)); assertFalse(chain.add(b3)); assertEquals(chain.getChainHead().getHeader(), b1.cloneAsHeader()); assertTrue(chain.add(b2)); assertEquals(chain.getChainHead().getHeader(), b3.cloneAsHeader()); }
@Test public void difficultyTransitions() throws Exception { Block prev = unitTestParams.getGenesisBlock(); Utils.setMockClock(System.currentTimeMillis()/1000); for (int i = 0; i < unitTestParams.getInterval() - 1; i++) { Block newBlock = prev.createNextBlock(coinbaseTo, Utils.currentTimeMillis()/1000); assertTrue(chain.add(newBlock)); prev = newBlock; Utils.rollMockClock(2); } try { chain.add(prev.createNextBlock(coinbaseTo, Utils.currentTimeMillis()/1000)); fail(); } catch (VerificationException e) { } Block b = prev.createNextBlock(coinbaseTo, Utils.currentTimeMillis()/1000); b.setDifficultyTarget(0x201fFFFFL); b.solve(); assertTrue(chain.add(b)); }
@Test public void badDifficulty() throws Exception { assertTrue(testNetChain.add(getBlock1())); Block b2 = getBlock2(); assertTrue(testNetChain.add(b2)); Block bad = new Block(testNet); bad.setMerkleRoot(new Sha256Hash("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")); bad.setNonce(140548933); bad.setTime(1279242649); bad.setPrevBlockHash(b2.getHash()); bad.setDifficultyTarget(Block.EASIEST_DIFFICULTY_TARGET); try { testNetChain.add(bad); fail(); } catch (VerificationException e) { assertTrue(e.getMessage(), e.getCause().getMessage().contains("Difficulty target is bad")); } BigInteger oldVal = testNet.getProofOfWorkLimit(); testNet.setProofOfWorkLimit(new BigInteger ("00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16)); try { testNetChain.add(bad); fail(); } catch (VerificationException e) { assertTrue(e.getMessage(), e.getCause().getMessage().contains("Unexpected change in difficulty")); } testNet.setProofOfWorkLimit(oldVal); }
@Test public void duplicates() throws Exception { Block b1 = unitTestParams.getGenesisBlock().createNextBlock(coinbaseTo); Block b2 = b1.createNextBlock(coinbaseTo); Block b3 = b2.createNextBlock(coinbaseTo); assertTrue(chain.add(b1)); assertEquals(b1, block[0].getHeader()); assertTrue(chain.add(b2)); assertEquals(b2, block[0].getHeader()); assertTrue(chain.add(b3)); assertEquals(b3, block[0].getHeader()); assertEquals(b3, chain.getChainHead().getHeader()); assertTrue(chain.add(b2)); assertEquals(b3, chain.getChainHead().getHeader()); assertEquals(b3, block[0].getHeader()); }
@Test public void intraBlockDependencies() throws Exception { Address somebodyElse = new ECKey().toAddress(unitTestParams); Block b1 = unitTestParams.getGenesisBlock().createNextBlock(somebodyElse); ECKey key = new ECKey(); wallet.addKey(key); Address addr = key.toAddress(unitTestParams); Transaction t1 = TestUtils.createFakeTx(unitTestParams, Utils.toNanoCoins(1, 0), addr); Transaction t2 = new Transaction(unitTestParams); t2.addInput(t1.getOutputs().get(0)); t2.addOutput(Utils.toNanoCoins(2, 0), somebodyElse); b1.addTransaction(t1); b1.addTransaction(t2); b1.solve(); chain.add(b1); assertEquals(BigInteger.ZERO, wallet.getBalance()); }
@Test public void coinbaseTransactionAvailability() throws Exception { Wallet wallet2 = new Wallet(unitTestParams); ECKey receiveKey = new ECKey(); wallet2.addKey(receiveKey); chain.addWallet(wallet2); Address addressToSendTo = receiveKey.toAddress(unitTestParams); Block b1 = unitTestParams.getGenesisBlock().createNextBlockWithCoinbase(wallet.getKeys().get(0).getPubKey()); chain.add(b1); assertNotNull(coinbaseTransaction); assertEquals(BigInteger.ZERO, wallet.getBalance()); assertEquals(wallet.getBalance(BalanceType.ESTIMATED), Utils.toNanoCoins(50, 0)); assertTrue(!coinbaseTransaction.isMature()); try { wallet.createSend(addressToSendTo, Utils.toNanoCoins(49, 0)); fail(); } catch (InsufficientMoneyException e) { } for (int i = 0; i < unitTestParams.getSpendableCoinbaseDepth() - 2; i++) { Transaction tx2 = createFakeTx(unitTestParams, Utils.toNanoCoins(1, 0), new ECKey().toAddress(unitTestParams)); Block b2 = createFakeBlock(blockStore, tx2).block; chain.add(b2); assertEquals(BigInteger.ZERO, wallet.getBalance()); assertEquals(wallet.getBalance(BalanceType.ESTIMATED), Utils.toNanoCoins(50, 0)); assertTrue(!coinbaseTransaction.isMature()); try { wallet.createSend(addressToSendTo, Utils.toNanoCoins(49, 0)); fail(); } catch (InsufficientMoneyException e) { } } Transaction tx3 = createFakeTx(unitTestParams, Utils.toNanoCoins(1, 0), new ECKey().toAddress(unitTestParams)); Block b3 = createFakeBlock(blockStore, tx3).block; chain.add(b3); assertEquals(wallet.getBalance(), Utils.toNanoCoins(50, 0)); assertEquals(wallet.getBalance(BalanceType.ESTIMATED), Utils.toNanoCoins(50, 0)); assertTrue(coinbaseTransaction.isMature()); Transaction coinbaseSend2 = wallet.createSend(addressToSendTo, Utils.toNanoCoins(49, 0)); assertNotNull(coinbaseSend2); wallet.commitTx(coinbaseSend2); assertEquals(wallet.getBalance(BalanceType.ESTIMATED), Utils.toNanoCoins(1, 0)); assertEquals(wallet.getBalance(BalanceType.AVAILABLE), Utils.toNanoCoins(0, 0)); Block b4 = createFakeBlock(blockStore, coinbaseSend2).block; chain.add(b4); assertEquals(wallet.getBalance(BalanceType.AVAILABLE), Utils.toNanoCoins(1, 0)); assertEquals(wallet2.getBalance(BalanceType.ESTIMATED), Utils.toNanoCoins(49, 0)); assertEquals(wallet2.getBalance(BalanceType.AVAILABLE), Utils.toNanoCoins(49, 0)); }