public void CanCheckBlockWithWitness()
        {
            var block = new Block(Encoders.Hex.DecodeData("000000202f6f6a130549473222411b5c6f54150d63b32aadf10e57f7d563cfc7010000001e28204471ef9ef11acd73543894a96a3044932b85e99889e731322a8ec28a9f9ae9fc56ffff011d0011b40202010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff2c028027266a24aa21a9ed09154465f26a2a4144739eba3e83b3e9ae6a1f69566eae7dc3747d48f1183779010effffffff0250b5062a0100000023210263ed47e995cbbf1bc560101e3b76c6bdb1b094a185450cea533781ce598ff2b6ac0000000000000000266a24aa21a9ed09154465f26a2a4144739eba3e83b3e9ae6a1f69566eae7dc3747d48f1183779012000000000000000000000000000000000000000000000000000000000000000000000000001000000000101cecd90cd38ac6858c47f2fe9f28145d6e18f9c5abc7ef1a41e2f19e6fe0362580100000000ffffffff0130b48d06000000001976a91405481b7f1d90c5a167a15b00e8af76eb6984ea5988ac0247304402206104c335e4adbb920184957f9f710b09de17d015329fde6807b9d321fd2142db02200b24ad996b4aa4ff103000348b5ad690abfd9fddae546af9e568394ed4a83113012103a65786c1a48d4167aca08cf6eb8eed081e13f45c02dc6000fd8f3bb16242579a00000000"));

            var consensusFlags = new ConsensusFlags()
            {
                ScriptFlags   = ScriptVerify.Witness | ScriptVerify.P2SH | ScriptVerify.Standard,
                LockTimeFlags = LockTimeFlags.MedianTimePast,
                EnforceBIP34  = true
            };

            var context = new ContextInformation()
            {
                BestBlock = new ContextBlockInformation()
                {
                    MedianTimePast = DateTimeOffset.Parse("2016-03-31T09:02:19+00:00", CultureInfo.InvariantCulture),
                    Height         = 10111
                },
                NextWorkRequired = block.Header.Bits,
                Time             = DateTimeOffset.UtcNow,
                BlockResult      = new BlockResult {
                    Block = block
                },
                Flags = consensusFlags,
            };

            Network.Main.Consensus.Options = new PowConsensusOptions();
            var validator = new PowConsensusValidator(Network.Main);

            //validator.CheckBlockHeader(context);
            validator.ContextualCheckBlock(context);
            validator.CheckBlock(context);
        }
        private Task TryPrefetchAsync(ConsensusFlags flags)
        {
            Task prefetching = Task.FromResult <bool>(true);

            if (this.UTXOSet is CachedCoinView)
            {
                var nextBlock = this.Puller.TryGetLookahead(0);
                if (nextBlock != null)
                {
                    prefetching = this.UTXOSet.FetchCoinsAsync(GetIdsToFetch(nextBlock, flags.EnforceBIP30));
                }
            }
            return(prefetching);
        }
예제 #3
0
        public long GetTransactionSigOpCost(Transaction tx, UnspentOutputSet inputs, ConsensusFlags flags)
        {
            long nSigOps = this.GetLegacySigOpCount(tx) * this.consensusOptions.WITNESS_SCALE_FACTOR;

            if (tx.IsCoinBase)
            {
                return(nSigOps);
            }

            if (flags.ScriptFlags.HasFlag(ScriptVerify.P2SH))
            {
                nSigOps += this.GetP2SHSigOpCount(tx, inputs) * this.consensusOptions.WITNESS_SCALE_FACTOR;
            }

            for (var i = 0; i < tx.Inputs.Count; i++)
            {
                var prevout = inputs.GetOutputFor(tx.Inputs[i]);
                nSigOps += this.CountWitnessSigOps(tx.Inputs[i].ScriptSig, prevout.ScriptPubKey, tx.Inputs[i].WitScript, flags);
            }
            return(nSigOps);
        }
예제 #4
0
        private long WitnessSigOps(WitProgramParameters witParams, WitScript witScript, ConsensusFlags flags)
        {
            if (witParams.Version == 0)
            {
                if (witParams.Program.Length == 20)
                {
                    return(1);
                }

                if (witParams.Program.Length == 32 && witScript.PushCount > 0)
                {
                    Script subscript = Script.FromBytesUnsafe(witScript.GetUnsafePush(witScript.PushCount - 1));
                    return(subscript.GetSigOpCount(true));
                }
            }

            // Future flags may be implemented here.
            return(0);
        }
예제 #5
0
        private long CountWitnessSigOps(Script scriptSig, Script scriptPubKey, WitScript witness, ConsensusFlags flags)
        {
            witness = witness ?? WitScript.Empty;
            if (!flags.ScriptFlags.HasFlag(ScriptVerify.Witness))
            {
                return(0);
            }
            var witParams = PayToWitTemplate.Instance.ExtractScriptPubKeyParameters2(scriptPubKey);

            if (witParams != null)
            {
                return(this.WitnessSigOps(witParams, witness, flags));
            }

            if (scriptPubKey.IsPayToScriptHash && scriptSig.IsPushOnly)
            {
                var data      = scriptSig.ToOps().Select(o => o.PushData).LastOrDefault() ?? new byte[0];
                var subScript = Script.FromBytesUnsafe(data);

                witParams = PayToWitTemplate.Instance.ExtractScriptPubKeyParameters2(scriptPubKey);
                if (witParams != null)
                {
                    return(this.WitnessSigOps(witParams, witness, flags));
                }
            }
            return(0);
        }
예제 #6
0
        public virtual void ExecuteBlock(ContextInformation context, TaskScheduler taskScheduler)
        {
            Block            block = context.BlockResult.Block;
            ChainedBlock     index = context.BlockResult.ChainedBlock;
            ConsensusFlags   flags = context.Flags;
            UnspentOutputSet view  = context.Set;

            this.PerformanceCounter.AddProcessedBlocks(1);
            taskScheduler = taskScheduler ?? TaskScheduler.Default;
            if (flags.EnforceBIP30)
            {
                foreach (var tx in block.Transactions)
                {
                    var coins = view.AccessCoins(tx.GetHash());
                    if (coins != null && !coins.IsPrunable)
                    {
                        ConsensusErrors.BadTransactionBIP30.Throw();
                    }
                }
            }
            long  nSigOpsCost = 0;
            Money nFees       = Money.Zero;
            List <Task <bool> > checkInputs = new List <Task <bool> >();

            for (int i = 0; i < block.Transactions.Count; i++)
            {
                this.PerformanceCounter.AddProcessedTransactions(1);
                var tx = block.Transactions[i];
                if (!tx.IsCoinBase && (!context.IsPoS || (context.IsPoS && !tx.IsCoinStake)))
                {
                    int[] prevheights;

                    if (!view.HaveInputs(tx))
                    {
                        ConsensusErrors.BadTransactionMissingInput.Throw();
                    }

                    prevheights = new int[tx.Inputs.Count];
                    // Check that transaction is BIP68 final
                    // BIP68 lock checks (as opposed to nLockTime checks) must
                    // be in ConnectBlock because they require the UTXO set
                    for (var j = 0; j < tx.Inputs.Count; j++)
                    {
                        prevheights[j] = (int)view.AccessCoins(tx.Inputs[j].PrevOut.Hash).Height;
                    }

                    if (!tx.CheckSequenceLocks(prevheights, index, flags.LockTimeFlags))
                    {
                        ConsensusErrors.BadTransactionNonFinal.Throw();
                    }
                }
                // GetTransactionSigOpCost counts 3 types of sigops:
                // * legacy (always)
                // * p2sh (when P2SH enabled in flags and excludes coinbase)
                // * witness (when witness enabled in flags and excludes coinbase)
                nSigOpsCost += this.GetTransactionSigOpCost(tx, view, flags);
                if (nSigOpsCost > this.consensusOptions.MAX_BLOCK_SIGOPS_COST)
                {
                    ConsensusErrors.BadBlockSigOps.Throw();
                }

                if (!tx.IsCoinBase && (!context.IsPoS || (context.IsPoS && !tx.IsCoinStake)))
                {
                    this.CheckInputs(tx, view, index.Height);
                    nFees += view.GetValueIn(tx) - tx.TotalOut;
                    int ii      = i;
                    var localTx = tx;
                    PrecomputedTransactionData txData = new PrecomputedTransactionData(tx);
                    for (int iInput = 0; iInput < tx.Inputs.Count; iInput++)
                    {
                        this.PerformanceCounter.AddProcessedInputs(1);
                        var input      = tx.Inputs[iInput];
                        int iiIntput   = iInput;
                        var txout      = view.GetOutputFor(input);
                        var checkInput = new Task <bool>(() =>
                        {
                            if (this.UseConsensusLib)
                            {
                                Script.BitcoinConsensusError error;
                                return(Script.VerifyScriptConsensus(txout.ScriptPubKey, tx, (uint)iiIntput, flags.ScriptFlags, out error));
                            }
                            else
                            {
                                var checker      = new TransactionChecker(tx, iiIntput, txout.Value, txData);
                                var ctx          = new ScriptEvaluationContext();
                                ctx.ScriptVerify = flags.ScriptFlags;
                                return(ctx.VerifyScript(input.ScriptSig, txout.ScriptPubKey, checker));
                            }
                        });
                        checkInput.Start(taskScheduler);
                        checkInputs.Add(checkInput);
                    }
                }

                this.UpdateCoinView(context, tx);
            }

            this.CheckBlockReward(context, nFees, index, block);

            var passed = checkInputs.All(c => c.GetAwaiter().GetResult());

            if (!passed)
            {
                ConsensusErrors.BadTransactionScriptError.Throw();
            }
        }