VerifyHeader() публичный Метод

Checks the block data to ensure it follows the rules laid out in the network parameters. Specifically, throws an exception if the proof of work is invalid, if the timestamp is too far from what it should be. This is not everything that is required for a block to be valid, only what is checkable independent of the chain and without a transaction index.
public VerifyHeader ( ) : void
Результат void
Пример #1
0
        /// <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);
        }
Пример #2
0
        /// <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;
            }
        }
Пример #3
0
        /// <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;
        }
Пример #4
0
        /// <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);
            }
        }