diff --git a/src/com/google/bitcoin/core/BlockChain.java b/src/com/google/bitcoin/core/BlockChain.java index c4d7c184..b6299a69 100644 --- a/src/com/google/bitcoin/core/BlockChain.java +++ b/src/com/google/bitcoin/core/BlockChain.java @@ -113,22 +113,9 @@ public class BlockChain { LOG(block.toString()); throw e; } - // If this block is a full block, scan, otherwise it's just headers (eg from getheaders or a unit test). - if (block.transactions != null) { - // Scan the transactions to find out if any sent money to us. We don't care about the rest. - // TODO: We should also scan to see if any of our own keys sent money to somebody else and became spent. - for (Transaction tx : block.transactions) { - try { - scanTransaction(tx); - } catch (ScriptException e) { - // We don't want scripts we don't understand to break the block chain, - // so just note that this tx was not scanned here and continue. - LOG("Failed to parse a script: " + e.toString()); - } - } - } - // We don't need the transaction data anymore. Free up some memory. - block.transactions = null; + // Inform the wallet about transactions relevant to our keys, then throw away the transaction data. + extractRelevantTransactions(block); + assert block.transactions == null; if (blockStore.get(block.getHash()) != null) { LOG("Already have block"); @@ -143,27 +130,9 @@ public class BlockChain { unconnectedBlocks.add(block); return false; } else { - // The block connects to somewhere on the chain. Not necessarily the top of the best known chain. + // It connects to somewhere on the chain. Not necessarily the top of the best known chain. checkDifficultyTransitions(storedPrev, block); - StoredBlock newStoredBlock = storedPrev.build(block); - // Store it. - blockStore.put(newStoredBlock); - if (storedPrev.equals(chainHead)) { - // This block connects to the best known block, it is a normal continuation of the system. - setChainHead(newStoredBlock); - LOG("Received block " + block.getHashAsString() + ", chain is now " + chainHead.getHeight() + - " blocks high"); - } else { - // This block connects to somewhere other than the top of the chain. - if (newStoredBlock.moreWorkThan(chainHead)) { - // This chain has overtaken the one we currently believe is best. Reorganize is required. - wallet.reorganize(chainHead, newStoredBlock); - // Update the pointer to the best known block. - setChainHead(newStoredBlock); - } else { - LOG("Received a block which forks the chain, but it did not cause a reorganize."); - } - } + connectAndStoreBlock(block, storedPrev); } if (tryConnecting) @@ -172,6 +141,48 @@ public class BlockChain { return true; } + private void connectAndStoreBlock(Block block, StoredBlock storedPrev) throws BlockStoreException, VerificationException { + StoredBlock newStoredBlock = storedPrev.build(block); + blockStore.put(newStoredBlock); + if (storedPrev.equals(chainHead)) { + // This block connects to the best known block, it is a normal continuation of the system. + setChainHead(newStoredBlock); + LOG("Received block " + block.getHashAsString() + ", chain is now " + chainHead.getHeight() + + " blocks high"); + } else { + // This block connects to somewhere other than the top of the chain. + if (newStoredBlock.moreWorkThan(chainHead)) { + // This chain has overtaken the one we currently believe is best. Reorganize is required. + wallet.reorganize(chainHead, newStoredBlock); + // Update the pointer to the best known block. + setChainHead(newStoredBlock); + } else { + LOG("Received a block which forks the chain, but it did not cause a reorganize."); + } + } + } + + private void extractRelevantTransactions(Block block) throws VerificationException { + // If this block is a full block, scan, otherwise it's just headers (eg from getheaders or a unit test). + if (block.transactions != null) { + // Scan the transactions to find out if any sent money to us. We don't care about the rest. + // TODO: We should also scan to see if any of our own keys sent money to somebody else and became spent. + for (Transaction tx : block.transactions) { + try { + scanTransaction(tx); + } catch (ScriptException e) { + // We don't want scripts we don't understand to break the block chain, + // so just note that this tx was not scanned here and continue. + LOG("Failed to parse a script: " + e.toString()); + } + } + } + // Throw away the transactions. We have to do this because we can't hold all the transaction data for the + // production chain in memory at once. Because BitCoinJ implements client mode/simplified payment + // verification we don't store the transactions to disk or use them later anyway. + block.transactions = null; + } + private void setChainHead(StoredBlock chainHead) { this.chainHead = chainHead; try {