Skip to content

Commit

Permalink
Add Coin.IsMalleable, rename HashVersion.Witness to WitnessV0
Browse files Browse the repository at this point in the history
  • Loading branch information
NicolasDorier committed Oct 21, 2020
1 parent 914d4f1 commit 9592fb6
Show file tree
Hide file tree
Showing 10 changed files with 36 additions and 30 deletions.
4 changes: 2 additions & 2 deletions NBitcoin.Altcoins/Elements/ElementsTransaction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -743,7 +743,7 @@ internal void ReadWrite(BitcoinStream stream)

public override uint256 GetSignatureHash(Script scriptCode, int nIn, SigHash nHashType, TxOut spentOutput, HashVersion sigversion, PrecomputedTransactionData precomputedTransactionData)
{
if (sigversion == HashVersion.Witness)
if (sigversion == HashVersion.WitnessV0)
{
var spentOutputElem = spentOutput as ElementsTxOut;
if (spentOutputElem == null)
Expand Down Expand Up @@ -905,7 +905,7 @@ private static void WriteScriptCode(BitcoinStream stream, Script scriptCode)

private uint256 GetIssuanceHash()
{
BitcoinStream ss = CreateHashWriter(HashVersion.Witness);
BitcoinStream ss = CreateHashWriter(HashVersion.WitnessV0);
for (int i = 0; i < this.Inputs.Count; i++)
{
if (Inputs[i] is ElementsTxIn elemInput && elemInput.HasAssetIssuance)
Expand Down
8 changes: 4 additions & 4 deletions NBitcoin.Altcoins/ForkIdTransaction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public override uint256 GetSignatureHash(Script scriptCode, int nIn, SigHash nHa
if(UsesForkId(nHashType))
nForkHashType |= ForkId << 8;

if((SupportSegwit && sigversion == HashVersion.Witness) || UsesForkId(nHashType))
if((SupportSegwit && sigversion == HashVersion.WitnessV0) || UsesForkId(nHashType))
{
if (spentOutput?.Value == null || spentOutput.Value == TxOut.NullMoney)
throw new ArgumentException("The output being signed with the amount must be provided", nameof(spentOutput));
Expand Down Expand Up @@ -191,7 +191,7 @@ private static uint256 GetHash(BitcoinStream stream)
internal override uint256 GetHashOutputs()
{
uint256 hashOutputs;
BitcoinStream ss = CreateHashWriter(HashVersion.Witness);
BitcoinStream ss = CreateHashWriter(HashVersion.WitnessV0);
foreach(var txout in Outputs)
{
ss.ReadWrite(txout);
Expand All @@ -203,7 +203,7 @@ internal override uint256 GetHashOutputs()
internal override uint256 GetHashSequence()
{
uint256 hashSequence;
BitcoinStream ss = CreateHashWriter(HashVersion.Witness);
BitcoinStream ss = CreateHashWriter(HashVersion.WitnessV0);
foreach(var input in Inputs)
{
ss.ReadWrite(input.Sequence);
Expand All @@ -215,7 +215,7 @@ internal override uint256 GetHashSequence()
internal override uint256 GetHashPrevouts()
{
uint256 hashPrevouts;
BitcoinStream ss = CreateHashWriter(HashVersion.Witness);
BitcoinStream ss = CreateHashWriter(HashVersion.WitnessV0);
foreach(var input in Inputs)
{
ss.ReadWrite(input.PrevOut);
Expand Down
8 changes: 4 additions & 4 deletions NBitcoin.Tests/transaction_tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3251,7 +3251,7 @@ public void bip143Test()
{
Transaction tx = Transaction.Parse("0100000002fff7f7881a8099afa6940d42d1e7f6362bec38171ea3edf433541db4e4ad969f0000000000eeffffffef51e1b804cc89d182d279655c3aa89e815b1b309fe287d9b2b55d57b90ec68a0100000000ffffffff02202cb206000000001976a9148280b37df378db99f66f85c95a783a76ac7a6d5988ac9093510d000000001976a9143bde42dbee7e4dbe6a21b2d50ce2f0167faa815988ac11000000", Network);
var output = tx.Outputs.CreateNewTxOut(Money.Satoshis(0x23c34600L), new Script(Encoders.Hex.DecodeData("76a9141d0f172a0ecb48aee1be1f2687d2963ae33f71a188ac")));
var h = tx.GetSignatureHash(output.ScriptPubKey, 1, SigHash.All, output, HashVersion.Witness);
var h = tx.GetSignatureHash(output.ScriptPubKey, 1, SigHash.All, output, HashVersion.WitnessV0);
Assert.Equal(new uint256(Encoders.Hex.DecodeData("c37af31116d1b27caf68aae9e3ac82f1477929014d5b917657d0eb49478cb670"), true), h);
}
[Fact]
Expand Down Expand Up @@ -3490,21 +3490,21 @@ public void CheckScriptCoinIsCoherent()
scriptCoin = new ScriptCoin(c, key.PubKey.WitHash.ScriptPubKey);
Assert.True(scriptCoin.RedeemType == RedeemType.P2SH);
Assert.True(scriptCoin.IsP2SH);
Assert.True(scriptCoin.GetHashVersion() == HashVersion.Witness);
Assert.True(scriptCoin.GetHashVersion() == HashVersion.WitnessV0);

//P2WSH
c.ScriptPubKey = key.PubKey.ScriptPubKey.WitHash.ScriptPubKey;
scriptCoin = new ScriptCoin(c, key.PubKey.ScriptPubKey);
Assert.True(scriptCoin.RedeemType == RedeemType.WitnessV0);
Assert.True(!scriptCoin.IsP2SH);
Assert.True(scriptCoin.GetHashVersion() == HashVersion.Witness);
Assert.True(scriptCoin.GetHashVersion() == HashVersion.WitnessV0);

//P2SH(P2WSH)
c.ScriptPubKey = key.PubKey.ScriptPubKey.WitHash.ScriptPubKey.Hash.ScriptPubKey;
scriptCoin = new ScriptCoin(c, key.PubKey.ScriptPubKey);
Assert.True(scriptCoin.RedeemType == RedeemType.WitnessV0);
Assert.True(scriptCoin.IsP2SH);
Assert.True(scriptCoin.GetHashVersion() == HashVersion.Witness);
Assert.True(scriptCoin.GetHashVersion() == HashVersion.WitnessV0);


Assert.Throws<ArgumentException>(() => new ScriptCoin(c, key.PubKey.ScriptPubKey.WitHash.ScriptPubKey));
Expand Down
4 changes: 2 additions & 2 deletions NBitcoin/BIP174/PSBTInput.cs
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ public void UpdateFromCoin(ICoin coin)
}
}
if (Parent.Network.Consensus.NeverNeedPreviousTxForSigning ||
coin.GetHashVersion() == HashVersion.Witness || witness_script != null)
!coin.IsMalleable || witness_script != null)
{
witness_utxo = coin.TxOut;
non_witness_utxo = null;
Expand Down Expand Up @@ -934,7 +934,7 @@ public bool TrySlimUTXO()
return false;

if (Parent.Network.Consensus.NeverNeedPreviousTxForSigning ||
coin.GetHashVersion() == HashVersion.Witness)
!coin.IsMalleable)
{
if (WitnessUtxo == null)
{
Expand Down
14 changes: 9 additions & 5 deletions NBitcoin/Coin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ bool CanGetScriptCode
get;
}
HashVersion GetHashVersion();
bool IsMalleable
{
get;
}
}

public class IssuanceCoin : IColoredCoin
Expand All @@ -62,7 +66,7 @@ public IssuanceCoin(OutPoint outpoint, TxOut txout)
Bearer = new Coin(outpoint, txout);
}


public bool IsMalleable => Bearer.IsMalleable;
public AssetId AssetId
{
get
Expand Down Expand Up @@ -235,7 +239,7 @@ public AssetId AssetId
return Amount.Id;
}
}

public bool IsMalleable => Bearer.IsMalleable;
public AssetMoney Amount
{
get;
Expand Down Expand Up @@ -444,7 +448,7 @@ public virtual Script GetScriptCode()
return key.AsKeyId().ScriptPubKey;
return ScriptPubKey;
}

public bool IsMalleable => GetHashVersion() != HashVersion.WitnessV0;
public virtual bool CanGetScriptCode
{
get
Expand All @@ -456,7 +460,7 @@ public virtual bool CanGetScriptCode
public virtual HashVersion GetHashVersion()
{
if (PayToWitTemplate.Instance.CheckScriptPubKey(ScriptPubKey))
return HashVersion.Witness;
return HashVersion.WitnessV0;
return HashVersion.Original;
}

Expand Down Expand Up @@ -769,7 +773,7 @@ public override HashVersion GetHashVersion()
var isWitness = PayToWitTemplate.Instance.CheckScriptPubKey(ScriptPubKey) ||
PayToWitTemplate.Instance.CheckScriptPubKey(Redeem) ||
RedeemType == NBitcoin.RedeemType.WitnessV0;
return isWitness ? HashVersion.Witness : HashVersion.Original;
return isWitness ? HashVersion.WitnessV0 : HashVersion.Original;
}

/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion NBitcoin/Policy/StandardTransactionPolicy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public TransactionPolicyError[] Check(Transaction transaction, ICoin[] spentCoin
foreach (var input in transaction.Inputs.AsIndexedInputs())
{
var coin = spentCoins.FirstOrDefault(s => s.Outpoint == input.PrevOut);
if (coin != null && coin.GetHashVersion() != HashVersion.Witness)
if (coin != null && coin.IsMalleable)
errors.Add(new InputPolicyError("Malleable input detected", input));
}
}
Expand Down
6 changes: 4 additions & 2 deletions NBitcoin/Script.cs
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,9 @@ public enum OpcodeType : byte
public enum HashVersion
{
Original = 0,
Witness = 1
[Obsolete("Use HashVersion.WitnessV0 instead")]
Witness = 1,
WitnessV0 = 1
}

public enum ScriptType
Expand Down Expand Up @@ -1095,7 +1097,7 @@ public static ScriptSigs CombineSignatures(Script scriptPubKey, TransactionCheck
{
scriptSig1 = input1.WitSig.ToScript();
scriptSig2 = input2.WitSig.ToScript();
hashVersion = HashVersion.Witness;
hashVersion = HashVersion.WitnessV0;
}

var context = new ScriptEvaluationContext();
Expand Down
4 changes: 2 additions & 2 deletions NBitcoin/ScriptEvaluationContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -855,7 +855,7 @@ bool EvalScript(Script s, TransactionChecker checker, int hashversion)

var vch = _stack.Top(-1);

if (hashversion == (int)HashVersion.Witness && (ScriptVerify & ScriptVerify.MinimalIf) != 0)
if (hashversion == (int)HashVersion.WitnessV0 && (ScriptVerify & ScriptVerify.MinimalIf) != 0)
{
if (vch.Length > 1)
return SetError(ScriptError.MinimalIf);
Expand Down Expand Up @@ -1655,7 +1655,7 @@ private bool CheckPubKeyEncoding(byte[] vchPubKey, int sigversion)
Error = ScriptError.PubKeyType;
return false;
}
if ((ScriptVerify & ScriptVerify.WitnessPubkeyType) != 0 && sigversion == (int)HashVersion.Witness && !IsCompressedPubKey(vchPubKey))
if ((ScriptVerify & ScriptVerify.WitnessPubkeyType) != 0 && sigversion == (int)HashVersion.WitnessV0 && !IsCompressedPubKey(vchPubKey))
{
return SetError(ScriptError.WitnessPubkeyType);
}
Expand Down
8 changes: 4 additions & 4 deletions NBitcoin/Transaction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1988,7 +1988,7 @@ public TransactionCheckResult Check()

public virtual uint256 GetSignatureHash(Script scriptCode, int nIn, SigHash nHashType, TxOut spentOutput, HashVersion sigversion, PrecomputedTransactionData precomputedTransactionData)
{
if (sigversion == HashVersion.Witness)
if (sigversion == HashVersion.WitnessV0)
{
if (spentOutput?.Value == null || spentOutput.Value == TxOut.NullMoney)
throw new ArgumentException("The output being signed with the amount must be provided", nameof(spentOutput));
Expand Down Expand Up @@ -2146,7 +2146,7 @@ private static uint256 GetHash(BitcoinStream stream)
internal virtual uint256 GetHashOutputs()
{
uint256 hashOutputs;
BitcoinStream ss = CreateHashWriter(HashVersion.Witness);
BitcoinStream ss = CreateHashWriter(HashVersion.WitnessV0);
foreach (var txout in Outputs)
{
txout.ReadWrite(ss);
Expand All @@ -2158,7 +2158,7 @@ internal virtual uint256 GetHashOutputs()
internal virtual uint256 GetHashSequence()
{
uint256 hashSequence;
BitcoinStream ss = CreateHashWriter(HashVersion.Witness);
BitcoinStream ss = CreateHashWriter(HashVersion.WitnessV0);
foreach (var input in Inputs)
{
ss.ReadWrite((uint)input.Sequence);
Expand All @@ -2170,7 +2170,7 @@ internal virtual uint256 GetHashSequence()
internal virtual uint256 GetHashPrevouts()
{
uint256 hashPrevouts;
BitcoinStream ss = CreateHashWriter(HashVersion.Witness);
BitcoinStream ss = CreateHashWriter(HashVersion.WitnessV0);
foreach (var input in Inputs)
{
ss.ReadWrite(input.PrevOut);
Expand Down
8 changes: 4 additions & 4 deletions NBitcoin/TransactionBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2194,7 +2194,7 @@ public void EstimateSizes(Transaction tx, out int witSize, out int baseSize)
var coin = FindSignableCoin(txin) ?? FindCoin(txin.PrevOut);
if (coin == null)
throw CoinNotFound(txin);
if (coin.GetHashVersion() == HashVersion.Witness)
if (!coin.IsMalleable)
hasWitness = true;
else
nonWitnessCount++;
Expand Down Expand Up @@ -2263,7 +2263,7 @@ private void EstimateScriptSigSize(ICoin coin, ref int witSize, ref int baseSize

if (scriptSigSize == -1)
scriptSigSize += coin.TxOut.ScriptPubKey.Length; //Using heurestic to approximate size of unknown scriptPubKey
if (coin.GetHashVersion() == HashVersion.Witness)
if (!coin.IsMalleable)
{
baseSize += new Protocol.VarInt((ulong)p2shPushRedeemSize).GetSerializedSize();
witSize += scriptSigSize + new Protocol.VarInt((ulong)(scriptSigSize + segwitPushRedeemSize)).GetSerializedSize();
Expand Down Expand Up @@ -2341,7 +2341,7 @@ private void Sign(TransactionSigningContext ctx, ICoin coin, IndexedTxIn txIn)
ScriptCoin? scriptCoin = coin as ScriptCoin;

Script? signatures = null;
if (coin.GetHashVersion() == HashVersion.Witness)
if (!coin.IsMalleable)
{
signatures = txIn.WitScript;
if (scriptCoin != null)
Expand All @@ -2362,7 +2362,7 @@ private void Sign(TransactionSigningContext ctx, ICoin coin, IndexedTxIn txIn)

signatures = CombineScriptSigs(coin, scriptSig, signatures);

if (coin.GetHashVersion() == HashVersion.Witness)
if (!coin.IsMalleable)
{
txIn.WitScript = signatures;
if (scriptCoin != null)
Expand Down

0 comments on commit 9592fb6

Please sign in to comment.