/// <summary> /// Constructor for memory pool error. /// </summary> /// <param name="consensusError">Error from consensus feature.</param> public MempoolError(ConsensusError consensusError) { this.ConsensusError = consensusError; }
/// <summary> /// This helper tests various scenarios related to the <see cref="PosColdStakingRule"/>. The parameters determine the test cases. /// </summary> /// <param name="isColdCoinStake">Tests the scenario where a hotPubKey was used to spend a cold stake transaction input.</param> /// <param name="inputScriptPubKeysDiffer">Tests the scenario where some of the input scriptPubKeys differ.</param> /// <param name="outputScriptPubKeysDiffer">Tests the scenario where some of the output scriptPubKeys differ.</param> /// <param name="badSecondOutput">Tests the scenario where the second output is not an OP_RETURN followed by some data.</param> /// <param name="inputsExceedOutputs">Tests the scenario where the input amount exceeds the output amount.</param> /// <param name="inputsWithoutOutputs">Tests the scenario where the some inputs have no incoming outputs.</param> /// <param name="expectedError">The error expected by running this test. Set to <c>null</c> if no error is expected.</param> private async Task PosColdStakingRuleTestHelperAsync(bool isColdCoinStake, bool inputScriptPubKeysDiffer, bool outputScriptPubKeysDiffer, bool badSecondOutput, bool inputsExceedOutputs, bool inputsWithoutOutputs, ConsensusError expectedError) { Block block = this.ruleContext.ValidationContext.BlockToValidate; // Create two scripts that are different. var scriptPubKey1 = new Script(OpcodeType.OP_1); var scriptPubKey2 = new Script(OpcodeType.OP_2); // Add dummy first transaction. Transaction transaction = this.network.CreateTransaction(); transaction.Outputs.Add(new TxOut(Money.Zero, (IDestination)null)); block.Transactions.Add(transaction); // Create a previous transaction with scriptPubKey outputs. Transaction prevTransaction = this.network.CreateTransaction(); prevTransaction.Outputs.Add(new TxOut(15, scriptPubKey1)); prevTransaction.Outputs.Add(new TxOut(25, inputScriptPubKeysDiffer ? scriptPubKey2 : scriptPubKey1)); // Record the spendable outputs. var posRuleContext = this.ruleContext as PosRuleContext; posRuleContext.UnspentOutputSet.Update(this.network, prevTransaction, 0); // Create cold coin stake transaction. Transaction coinstakeTransaction = this.network.CreateTransaction(); coinstakeTransaction.Inputs.Add(new TxIn() { PrevOut = new OutPoint(prevTransaction, 0), ScriptSig = new Script() }); coinstakeTransaction.Inputs.Add(new TxIn() { PrevOut = new OutPoint(prevTransaction, inputsWithoutOutputs ? 2 : 1), ScriptSig = new Script() }); coinstakeTransaction.Outputs.Add(new TxOut(Money.Zero, (IDestination)null)); coinstakeTransaction.Outputs.Add(new TxOut(Money.Zero, badSecondOutput ? new Script() : new Script(OpcodeType.OP_RETURN, Op.GetPushOp(new Key().PubKey.Compress().ToBytes())))); coinstakeTransaction.Outputs.Add(new TxOut(inputsExceedOutputs ? 10 : 15, scriptPubKey1)); coinstakeTransaction.Outputs.Add(new TxOut(25, outputScriptPubKeysDiffer ? scriptPubKey2 : scriptPubKey1)); // Set this flag which is expected to be set by the preceding PosCoinview rule if this were run in an integrated scenario. (coinstakeTransaction as PosTransaction).IsColdCoinStake = isColdCoinStake; block.Transactions.Add(coinstakeTransaction); // Finalize the block and add it to the chain. block.Header.HashPrevBlock = this.ChainIndexer.Tip.HashBlock; block.Header.Time = (uint)1483747200; block.UpdateMerkleRoot(); Assert.True(BlockStake.IsProofOfStake(block)); this.ChainIndexer.SetTip(block.Header); // Execute the rule and check the outcome against what is expected. var rule = this.CreateRule <PosColdStakingRule>(); // Initialize the rule context. posRuleContext.ValidationContext.ChainedHeaderToValidate = this.ChainIndexer.Tip; posRuleContext.CoinStakePrevOutputs = coinstakeTransaction.Inputs.ToDictionary(txin => txin, txin => posRuleContext.UnspentOutputSet.GetOutputFor(txin)); posRuleContext.TotalCoinStakeValueIn = posRuleContext.CoinStakePrevOutputs.Sum(a => a.Value?.Value ?? 0); // If an error is expeected then capture the error and compare it against the expected error. if (expectedError != null) { ConsensusErrorException exception = Assert.Throws <ConsensusErrorException>(() => rule.RunAsync(this.ruleContext).GetAwaiter().GetResult()); Assert.Equal(expectedError, exception.ConsensusError); return; } // No error is expected. Attempt to run the rule normally. await rule.RunAsync(this.ruleContext); }