Commit 06fd8d31 authored by Sergei Zubov's avatar Sergei Zubov

Fix fees check in consensus

InputScriptPubKeys from different transactions could mix and corrupt
validation context. PubKeys moved from list to dictionary of lists,
with transaction hash as key.
parent 13cd7055
......@@ -9,7 +9,7 @@ namespace Stratis.Bitcoin.Features.Consensus
/// <summary>
/// ScriptPubKeys of inputs spent in transaction
/// </summary>
List<Script> InputScriptPubKeys { get; set; }
IDictionary<uint256, List<Script>> InputScriptPubKeys { get; set; }
/// <summary>
/// Sum of inputs spent in transaction
......@@ -30,7 +30,7 @@ namespace Stratis.Bitcoin.Features.Consensus
}
/// <inheritdoc />
public List<Script> InputScriptPubKeys { get; set; }
public IDictionary<uint256, List<Script>> InputScriptPubKeys { get; set; }
/// <inheritdoc />
......@@ -50,7 +50,7 @@ namespace Stratis.Bitcoin.Features.Consensus
}
/// <inheritdoc />
public List<Script> InputScriptPubKeys { get; set; }
public IDictionary<uint256, List<Script>> InputScriptPubKeys { get; set; }
/// <inheritdoc />
public IDictionary<uint256, Money> TotalIn { get; set; } = new Dictionary<uint256, Money>();
......
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
......@@ -55,11 +55,11 @@ namespace Stratis.Bitcoin.Features.Consensus.Rules.CommonRules
return outputsToFeeWallet.Single().Value;
}
private long GetExpectedFee(Block block, IDictionary<uint256, Money> totalIn, ICollection<Script> inputScriptPubKeys)
private long GetExpectedFee(Block block, IDictionary<uint256, Money> totalIn, IDictionary<uint256, List<Script>> inputScriptPubKeys)
{
return block.Transactions.Where(p => !p.IsCoinBase && !p.IsCoinStake).Sum(p => this.GetFeeInTransaction(p,
totalIn[p.GetHash()], p.Outputs
.Select(q => q.ScriptPubKey).Intersect(inputScriptPubKeys)
.Select(q => q.ScriptPubKey).Intersect(inputScriptPubKeys[p.GetHash()])
.Concat(p.Inputs.GetChangePointers()
.Select(q => p.Outputs[q].ScriptPubKey))
.Distinct()
......
......@@ -11,7 +11,7 @@ using Stratis.Bitcoin.Utilities;
namespace Stratis.Bitcoin.Features.Consensus.Rules.CommonRules
{
/// <summary>
/// CoinViewRule that prevents verifing ChangePointer input
/// CoinViewRule that prevents verifing ChangePointer input
/// </summary>
public abstract class DeStreamCoinViewRule : CoinViewRule
{
......@@ -94,9 +94,11 @@ namespace Stratis.Bitcoin.Features.Consensus.Rules.CommonRules
ctx.VerifyScript(input.ScriptSig, txout.ScriptPubKey, checker);
if (verifyScriptResult == false)
{
this.Logger.LogTrace(
"Verify script for transaction '{0}' failed, ScriptSig = '{1}', ScriptPubKey = '{2}', script evaluation error = '{3}'",
tx.GetHash(), input.ScriptSig, txout.ScriptPubKey, ctx.Error);
}
return verifyScriptResult;
});
......@@ -123,8 +125,10 @@ namespace Stratis.Bitcoin.Features.Consensus.Rules.CommonRules
}
}
else
{
this.Logger.LogTrace("BIP68, SigOp cost, and block reward validation skipped for block at height {0}.",
index.Height);
}
this.Logger.LogTrace("(-)");
}
......@@ -223,7 +227,7 @@ namespace Stratis.Bitcoin.Features.Consensus.Rules.CommonRules
protected override void UpdateUTXOSet(RuleContext context, Transaction transaction)
{
// Saves script pub keys and total amount of spent inputs to context
this.Logger.LogTrace("()");
ChainedHeader index = context.ValidationContext.ChainedHeader;
......@@ -232,13 +236,16 @@ namespace Stratis.Bitcoin.Features.Consensus.Rules.CommonRules
switch (context)
{
case DeStreamPowRuleContext deStreamPowRuleContext:
deStreamPowRuleContext.InputScriptPubKeys.AddRange(transaction.Inputs.RemoveChangePointer()
.Select(p => view.GetOutputFor(p).ScriptPubKey));
deStreamPowRuleContext.InputScriptPubKeys.AddOrReplace(transaction.GetHash(), transaction.Inputs
.RemoveChangePointer()
.Select(p => view.GetOutputFor(p).ScriptPubKey).ToList());
deStreamPowRuleContext.TotalIn.Add(transaction.GetHash(), view.GetValueIn(transaction));
break;
case DeStreamRuleContext deStreamPosRuleContext:
deStreamPosRuleContext.InputScriptPubKeys.AddRange(transaction.Inputs.RemoveChangePointer()
.Select(p => view.GetOutputFor(p).ScriptPubKey));
deStreamPosRuleContext.InputScriptPubKeys.AddOrReplace(transaction.GetHash(), transaction.Inputs
.RemoveChangePointer()
.Select(p => view.GetOutputFor(p).ScriptPubKey).ToList());
deStreamPosRuleContext.TotalIn.Add(transaction.GetHash(), view.GetValueIn(transaction));
break;
default:
......
......@@ -25,10 +25,10 @@ namespace Stratis.Bitcoin.Features.Consensus.Rules.CommonRules
switch (utxoRuleContext)
{
case DeStreamPowRuleContext deStreamPowRuleContext:
deStreamPowRuleContext.InputScriptPubKeys = new List<Script>();
deStreamPowRuleContext.InputScriptPubKeys = new Dictionary<uint256, List<Script>>();
break;
case DeStreamRuleContext deStreamPosRuleContext:
deStreamPosRuleContext.InputScriptPubKeys = new List<Script>();
deStreamPosRuleContext.InputScriptPubKeys = new Dictionary<uint256, List<Script>>();
break;
default:
throw new NotSupportedException(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment