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); }
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); }
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); }
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); }
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(); } }