@Bean public BlockChain bitcoinBlockchain(SPVBlockStore blockStore, Context bitcoinContext, NetworkParameters chainNetworkParameters) throws IOException, BlockStoreException { if (chainNetworkParameters.equals(MainNetParams.get())) { InputStream checkPoints = BitcoinMonitor.class.getClassLoader().getResourceAsStream("checkpoints.txt"); CheckpointManager.checkpoint(chainNetworkParameters, checkPoints, blockStore, 1498867200L); } else if (chainNetworkParameters.equals(TestNet3Params.get())) { InputStream checkPoints = BitcoinMonitor.class.getClassLoader().getResourceAsStream("checkpoints-testnet.txt"); CheckpointManager.checkpoint(chainNetworkParameters, checkPoints, blockStore, 1498867200L); } return new BlockChain(bitcoinContext, blockStore); }
blockChain = new BlockChain(networkParameters, blockStore); blockChain.addWallet(wallet); log.debug("Created block chain '{}' with height '{}'", blockChain, blockChain.getBestChainHeight());
@Test public void falsePositives() throws Exception { double decay = AbstractBlockChain.FP_ESTIMATOR_ALPHA; assertTrue(0 == chain.getFalsePositiveRate()); // Exactly chain.trackFalsePositives(55); assertEquals(decay * 55, chain.getFalsePositiveRate(), 1e-4); chain.trackFilteredTransactions(550); double rate1 = chain.getFalsePositiveRate(); // Run this scenario a few more time for the filter to converge for (int i = 1 ; i < 10 ; i++) { chain.trackFalsePositives(55); chain.trackFilteredTransactions(550); } // Ensure we are within 10% assertEquals(0.1, chain.getFalsePositiveRate(), 0.01); // Check that we get repeatable results after a reset chain.resetFalsePositiveEstimate(); assertTrue(0 == chain.getFalsePositiveRate()); // Exactly chain.trackFalsePositives(55); assertEquals(decay * 55, chain.getFalsePositiveRate(), 1e-4); chain.trackFilteredTransactions(550); assertEquals(rate1, chain.getFalsePositiveRate(), 1e-4); }
@Override protected void rollbackBlockStore(int height) throws BlockStoreException { lock.lock(); try { int currentHeight = getBestChainHeight(); checkArgument(height >= 0 && height <= currentHeight, "Bad height: %s", height); if (height == currentHeight) return; // nothing to do // Look for the block we want to be the new chain head StoredBlock newChainHead = blockStore.getChainHead(); while (newChainHead.getHeight() > height) { newChainHead = newChainHead.getPrev(blockStore); if (newChainHead == null) throw new BlockStoreException("Unreachable height"); } // Modify store directly blockStore.put(newChainHead); this.setChainHead(newChainHead); } finally { lock.unlock(); } }
BlockChain chain = new BlockChain(params, chainStore); PeerGroup peers = new PeerGroup(params, chain); peers.addPeerDiscovery(new DnsDiscovery(params)); chain.addWallet(wallet); peers.addWallet(wallet);
@Test public void rollbackBlockStore() throws Exception { // This test simulates an issue on Android, that causes the VM to crash while receiving a block, so that the // block store is persisted but the wallet is not. Block b1 = PARAMS.getGenesisBlock().createNextBlock(coinbaseTo); Block b2 = b1.createNextBlock(coinbaseTo); // Add block 1, no frills. assertTrue(chain.add(b1)); assertEquals(b1.cloneAsHeader(), chain.getChainHead().getHeader()); assertEquals(1, chain.getBestChainHeight()); assertEquals(1, wallet.getLastBlockSeenHeight()); // Add block 2 while wallet is disconnected, to simulate crash. chain.removeWallet(wallet); assertTrue(chain.add(b2)); assertEquals(b2.cloneAsHeader(), chain.getChainHead().getHeader()); assertEquals(2, chain.getBestChainHeight()); assertEquals(1, wallet.getLastBlockSeenHeight()); // Add wallet back. This will detect the height mismatch and repair the damage done. chain.addWallet(wallet); assertEquals(b1.cloneAsHeader(), chain.getChainHead().getHeader()); assertEquals(1, chain.getBestChainHeight()); assertEquals(1, wallet.getLastBlockSeenHeight()); // Now add block 2 correctly. assertTrue(chain.add(b2)); assertEquals(b2.cloneAsHeader(), chain.getChainHead().getHeader()); assertEquals(2, chain.getBestChainHeight()); assertEquals(2, wallet.getLastBlockSeenHeight()); } }
/** * <p>Constructs a BlockChain connected to the given wallet and store. To obtain a {@link Wallet} you can construct * one from scratch, or you can deserialize a saved wallet from disk using * {@link Wallet#loadFromFile(java.io.File, WalletExtension...)}</p> * * <p>For the store, you should use {@link org.bitcoinj.store.SPVBlockStore} or you could also try a * {@link org.bitcoinj.store.MemoryBlockStore} if you want to hold all headers in RAM and don't care about * disk serialization (this is rare).</p> */ public BlockChain(Context context, Wallet wallet, BlockStore blockStore) throws BlockStoreException { this(context, new ArrayList<Wallet>(), blockStore); addWallet(wallet); }
private void testDeprecatedBlockVersion(final long deprecatedVersion, final long newVersion) throws Exception { final BlockStore versionBlockStore = new MemoryBlockStore(PARAMS); final BlockChain versionChain = new BlockChain(PARAMS, versionBlockStore); // Build a historical chain of version 3 blocks long timeSeconds = 1231006505; int height = 0; FakeTxBuilder.BlockPair chainHead = null; // Put in just enough v2 blocks to be a minority for (height = 0; height < (PARAMS.getMajorityWindow() - PARAMS.getMajorityRejectBlockOutdated()); height++) { chainHead = FakeTxBuilder.createFakeBlock(versionBlockStore, deprecatedVersion, timeSeconds, height); versionChain.add(chainHead.block); timeSeconds += 60; } // Fill the rest of the window with v3 blocks for (; height < PARAMS.getMajorityWindow(); height++) { chainHead = FakeTxBuilder.createFakeBlock(versionBlockStore, newVersion, timeSeconds, height); versionChain.add(chainHead.block); timeSeconds += 60; } chainHead = FakeTxBuilder.createFakeBlock(versionBlockStore, deprecatedVersion, timeSeconds, height); // Trying to add a new v2 block should result in rejection thrown.expect(VerificationException.BlockVersionOutOfDate.class); try { versionChain.add(chainHead.block); } catch(final VerificationException ex) { throw (Exception) ex.getCause(); } }
final BlockChain chain = new BlockChain(PARAMS, store); final PeerGroup peerGroup = new PeerGroup(PARAMS, chain); peerGroup.addPeerDiscovery(new DnsDiscovery(PARAMS)); chain.addListener(new AbstractBlockChainListener() { @Override public void notifyNewBestBlock(StoredBlock block) throws VerificationException {
@Test public void estimatedBlockTime() throws Exception { NetworkParameters params = MainNetParams.get(); BlockChain prod = new BlockChain(new Context(params), new MemoryBlockStore(params)); Date d = prod.estimateBlockTime(200000); // The actual date of block 200,000 was 2012-09-22 10:47:00 assertEquals(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US).parse("2012-10-23T08:35:05.000-0700"), d); }
final BlockChain chain = new BlockChain(params, store); final PeerGroup peerGroup = new PeerGroup(params, chain); System.out.println("Connecting to " + peerAddress + "..."); System.out.println("Checkpointing up to " + Utils.dateTimeFormat(timeAgo * 1000)); chain.addNewBestBlockListener(Threading.SAME_THREAD, new NewBestBlockListener() { @Override public void notifyNewBestBlock(StoredBlock block) throws VerificationException {
@Override protected void doneDownload() { LOG.info("Download done, now sending block numbers."); final int startBlockHeight = bitcoinBlockchain.getBestChainHeight(); messageService.send(new BlockNRBitcoinMessage((long) startBlockHeight, new Date().getTime())); bitcoinPeerGroup.addBlocksDownloadedEventListener((peer, block, filteredBlock, blocksLeft) -> { if (bitcoinBlockchain.getBestChainHeight() > startBlockHeight) { messageService.send(new BlockNRBitcoinMessage((long) bitcoinBlockchain.getBestChainHeight(), new Date().getTime())); } }); }
@Override public boolean add(FilteredBlock block) throws VerificationException, PrunedException { boolean success = super.add(block); if (success) { trackFilteredTransactions(block.getTransactionCount()); } return success; } }
@Test public void unconnectedBlocks() throws Exception { Block b1 = PARAMS.getGenesisBlock().createNextBlock(coinbaseTo); Block b2 = b1.createNextBlock(coinbaseTo); Block b3 = b2.createNextBlock(coinbaseTo); // Connected. assertTrue(chain.add(b1)); // Unconnected but stored. The head of the chain is still b1. assertFalse(chain.add(b3)); assertEquals(chain.getChainHead().getHeader(), b1.cloneAsHeader()); // Add in the middle block. assertTrue(chain.add(b2)); assertEquals(chain.getChainHead().getHeader(), b3.cloneAsHeader()); }
@Override public Integer getblockcount() { if(!kit.isRunning()) { return null; } return kit.chain().getChainHead().getHeight(); }
vChain = new BlockChain(params, vStore); vPeerGroup = createPeerGroup(); if (this.userAgent != null) vPeerGroup.addPeerDiscovery(discovery != null ? discovery : new DnsDiscovery(params)); vChain.addWallet(vWallet); vPeerGroup.addWallet(vWallet); onSetupCompleted();
@Override protected void rollbackBlockStore(int height) throws BlockStoreException { lock.lock(); try { int currentHeight = getBestChainHeight(); checkArgument(height >= 0 && height <= currentHeight, "Bad height: %s", height); if (height == currentHeight) return; // nothing to do // Look for the block we want to be the new chain head StoredBlock newChainHead = blockStore.getChainHead(); while (newChainHead.getHeight() > height) { newChainHead = newChainHead.getPrev(blockStore); if (newChainHead == null) throw new BlockStoreException("Unreachable height"); } // Modify store directly blockStore.put(newChainHead); this.setChainHead(newChainHead); } finally { lock.unlock(); } }
/** * <p>Constructs a BlockChain connected to the given wallet and store. To obtain a {@link Wallet} you can construct * one from scratch, or you can deserialize a saved wallet from disk using * {@link Wallet#loadFromFile(java.io.File, WalletExtension...)}</p> * * <p>For the store, you should use {@link org.bitcoinj.store.SPVBlockStore} or you could also try a * {@link org.bitcoinj.store.MemoryBlockStore} if you want to hold all headers in RAM and don't care about * disk serialization (this is rare).</p> */ public BlockChain(Context context, Wallet wallet, BlockStore blockStore) throws BlockStoreException { this(context, new ArrayList<Wallet>(), blockStore); addWallet(wallet); }
@Test public void coinbaseTxns() throws Exception { // Covers issue 420 where the outpoint index of a coinbase tx input was being mis-serialized. Block b = PARAMS.getGenesisBlock().createNextBlockWithCoinbase(Block.BLOCK_VERSION_GENESIS, myKey.getPubKey(), FIFTY_COINS, Block.BLOCK_HEIGHT_GENESIS); Transaction coinbase = b.getTransactions().get(0); assertTrue(coinbase.isCoinBase()); BlockChain chain = new BlockChain(PARAMS, myWallet, new MemoryBlockStore(PARAMS)); assertTrue(chain.add(b)); // Wallet now has a coinbase tx in it. assertEquals(1, myWallet.getTransactions(true).size()); assertTrue(myWallet.getTransaction(coinbase.getHash()).isCoinBase()); Wallet wallet2 = roundTrip(myWallet); assertEquals(1, wallet2.getTransactions(true).size()); assertTrue(wallet2.getTransaction(coinbase.getHash()).isCoinBase()); }