// Emulates receiving a valid block that builds on top of the chain. public static BlockPair CreateFakeBlock(NetworkParameters @params, IBlockStore blockStore, params Transaction[] transactions) { var b = MakeTestBlock(@params, blockStore); // Coinbase tx was already added. foreach (var tx in transactions) b.AddTransaction(tx); b.Solve(); var pair = new BlockPair(); pair.Block = b; pair.StoredBlock = blockStore.GetChainHead().Build(b); blockStore.Put(pair.StoredBlock); blockStore.SetChainHead(pair.StoredBlock); return pair; }
// Emulates receiving a valid block that builds on top of the chain. private BlockPair CreateFakeBlock(params Transaction[] transactions) { var b = _blockStore.GetChainHead().Header.CreateNextBlock(new EcKey().ToAddress(_params)); foreach (var tx in transactions) { b.AddTransaction(tx); } b.Solve(); var pair = new BlockPair(); pair.Block = b; pair.StoredBlock = _blockStore.GetChainHead().Build(b); _blockStore.Put(pair.StoredBlock); _blockStore.SetChainHead(pair.StoredBlock); return(pair); }
// Emulates receiving a valid block that builds on top of the chain. public static BlockPair CreateFakeBlock(NetworkParameters networkParams, IBlockStore blockStore, params Transaction[] transactions) { var b = MakeTestBlock(networkParams, blockStore); // Coinbase tx was already added. foreach (var tx in transactions) { b.AddTransaction(tx); } b.Solve(); var pair = new BlockPair(); pair.Block = b; pair.StoredBlock = blockStore.GetChainHead().Build(b); blockStore.Put(pair.StoredBlock); blockStore.SetChainHead(pair.StoredBlock); return(pair); }
/// <exception cref="BitCoinSharp.BlockStoreException" /> /// <exception cref="BitCoinSharp.VerificationException" /> /// <exception cref="BitCoinSharp.ScriptException" /> private bool Add(Block block, bool tryConnecting) { lock (this) { if (Environment.TickCount - _statsLastTime > 1000) { // More than a second passed since last stats logging. _log.InfoFormat("{0} blocks per second", _statsBlocksAdded); _statsLastTime = Environment.TickCount; _statsBlocksAdded = 0; } // We check only the chain head for double adds here to avoid potentially expensive block chain misses. if (block.Equals(_chainHead.Header)) { // Duplicate add of the block at the top of the chain, can be a natural artifact of the download process. return(true); } // Prove the block is internally valid: hash is lower than target, merkle root is correct and so on. try { block.Verify(); } catch (VerificationException e) { _log.Error("Failed to verify block:", e); _log.Error(block.ToString()); throw; } // Try linking it to a place in the currently known blocks. var storedPrev = _blockStore.Get(block.PrevBlockHash); if (storedPrev == null) { // We can't find the previous block. Probably we are still in the process of downloading the chain and a // block was solved whilst we were doing it. We put it to one side and try to connect it later when we // have more blocks. _log.WarnFormat("Block does not connect: {0}", block.HashAsString); _unconnectedBlocks.Add(block); return(false); } // It connects to somewhere on the chain. Not necessarily the top of the best known chain. // // Create a new StoredBlock from this block. It will throw away the transaction data so when block goes // out of scope we will reclaim the used memory. var newStoredBlock = storedPrev.Build(block); CheckDifficultyTransitions(storedPrev, newStoredBlock); _blockStore.Put(newStoredBlock); // block.transactions may be null here if we received only a header and not a full block. This does not // happen currently but might in future if GetHeaders is implemented. ConnectBlock(newStoredBlock, storedPrev, block.Transactions); if (tryConnecting) { TryConnectingUnconnected(); } _statsBlocksAdded++; return(true); } }
/// <exception cref="BlockStoreException"/> /// <exception cref="VerificationException"/> /// <exception cref="ScriptException"/> private bool Add(Block block, bool tryConnecting) { lock (this) { if (Environment.TickCount - _statsLastTime > 1000) { // More than a second passed since last stats logging. _log.InfoFormat("{0} blocks per second", _statsBlocksAdded); _statsLastTime = Environment.TickCount; _statsBlocksAdded = 0; } // We check only the chain head for double adds here to avoid potentially expensive block chain misses. if (block.Equals(_chainHead.Header)) { // Duplicate add of the block at the top of the chain, can be a natural artifact of the download process. return(true); } // Does this block contain any transactions we might care about? Check this up front before verifying the // blocks validity so we can skip the merkle root verification if the contents aren't interesting. This saves // a lot of time for big blocks. var contentsImportant = false; var walletToTxMap = new Dictionary <Wallet, List <Transaction> >(); if (block.Transactions != null) { ScanTransactions(block, walletToTxMap); contentsImportant = walletToTxMap.Count > 0; } // Prove the block is internally valid: hash is lower than target, etc. This only checks the block contents // if there is a tx sending or receiving coins using an address in one of our wallets. And those transactions // are only lightly verified: presence in a valid connecting block is taken as proof of validity. See the // article here for more details: http://code.google.com/p/bitcoinj/wiki/SecurityModel try { block.VerifyHeader(); if (contentsImportant) { block.VerifyTransactions(); } } catch (VerificationException e) { _log.Error("Failed to verify block:", e); _log.Error(block.HashAsString); throw; } // Try linking it to a place in the currently known blocks. var storedPrev = _blockStore.Get(block.PrevBlockHash); if (storedPrev == null) { // We can't find the previous block. Probably we are still in the process of downloading the chain and a // block was solved whilst we were doing it. We put it to one side and try to connect it later when we // have more blocks. _log.WarnFormat("Block does not connect: {0}", block.HashAsString); _unconnectedBlocks.Add(block); return(false); } // It connects to somewhere on the chain. Not necessarily the top of the best known chain. // // Create a new StoredBlock from this block. It will throw away the transaction data so when block goes // out of scope we will reclaim the used memory. var newStoredBlock = storedPrev.Build(block); CheckDifficultyTransitions(storedPrev, newStoredBlock); _blockStore.Put(newStoredBlock); ConnectBlock(newStoredBlock, storedPrev, walletToTxMap); if (tryConnecting) { TryConnectingUnconnected(); } _statsBlocksAdded++; return(true); } }