/// <summary> /// Returns a solved block that builds on top of this one. This exists for unit tests. /// </summary> internal Block CreateNextBlock(Address to, uint time) { var b = new Block(Params); b.DifficultyTarget = _difficultyTarget; b.AddCoinbaseTransaction(_emptyBytes); // Add a transaction paying 50 coins to the "to" address. var t = new Transaction(Params); t.AddOutput(new TransactionOutput(Params, t, Utils.ToNanoCoins(50, 0), to)); // The input does not really need to be a valid signature, as long as it has the right general form. var input = new TransactionInput(Params, t, Script.CreateInputScript(_emptyBytes, _emptyBytes)); // Importantly the outpoint hash cannot be zero as that's how we detect a coinbase transaction in isolation // but it must be unique to avoid 'different' transactions looking the same. var counter = new byte[32]; counter[0] = (byte)_txCounter++; input.Outpoint.Hash = new Sha256Hash(counter); t.AddInput(input); b.AddTransaction(t); b.PrevBlockHash = Hash; b.TimeSeconds = time; b.Solve(); b.VerifyHeader(); return(b); }
/// <summary> /// Returns a solved block that builds on top of this one. This exists for unit tests. /// </summary> internal Block CreateNextBlock(Address to, uint time) { var b = new Block(Params); b.DifficultyTarget = _difficultyTarget; b.AddCoinbaseTransaction(_emptyBytes); // Add a transaction paying 50 coins to the "to" address. var t = new Transaction(Params); t.AddOutput(new TransactionOutput(Params, t, Utils.ToNanoCoins(50, 0), to)); // The input does not really need to be a valid signature, as long as it has the right general form. var input = new TransactionInput(Params, t, Script.CreateInputScript(_emptyBytes, _emptyBytes)); // Importantly the outpoint hash cannot be zero as that's how we detect a coinbase transaction in isolation // but it must be unique to avoid 'different' transactions looking the same. var counter = new byte[32]; counter[0] = (byte) _txCounter++; input.Outpoint.Hash = new Sha256Hash(counter); t.AddInput(input); b.AddTransaction(t); b.PrevBlockHash = Hash; b.TimeSeconds = time; b.Solve(); b.VerifyHeader(); return b; }
/// <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; } }
/// <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); } }