Skip to content

Commit 6794746

Browse files
committed
Add Coin.IsMalleable, rename HashVersion.Witness to WitnessV0
1 parent 914d4f1 commit 6794746

10 files changed

+36
-30
lines changed

NBitcoin.Altcoins/Elements/ElementsTransaction.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -743,7 +743,7 @@ internal void ReadWrite(BitcoinStream stream)
743743

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

906906
private uint256 GetIssuanceHash()
907907
{
908-
BitcoinStream ss = CreateHashWriter(HashVersion.Witness);
908+
BitcoinStream ss = CreateHashWriter(HashVersion.WitnessV0);
909909
for (int i = 0; i < this.Inputs.Count; i++)
910910
{
911911
if (Inputs[i] is ElementsTxIn elemInput && elemInput.HasAssetIssuance)

NBitcoin.Altcoins/ForkIdTransaction.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public override uint256 GetSignatureHash(Script scriptCode, int nIn, SigHash nHa
4545
if(UsesForkId(nHashType))
4646
nForkHashType |= ForkId << 8;
4747

48-
if((SupportSegwit && sigversion == HashVersion.Witness) || UsesForkId(nHashType))
48+
if((SupportSegwit && sigversion == HashVersion.WitnessV0) || UsesForkId(nHashType))
4949
{
5050
if (spentOutput?.Value == null || spentOutput.Value == TxOut.NullMoney)
5151
throw new ArgumentException("The output being signed with the amount must be provided", nameof(spentOutput));
@@ -191,7 +191,7 @@ private static uint256 GetHash(BitcoinStream stream)
191191
internal override uint256 GetHashOutputs()
192192
{
193193
uint256 hashOutputs;
194-
BitcoinStream ss = CreateHashWriter(HashVersion.Witness);
194+
BitcoinStream ss = CreateHashWriter(HashVersion.WitnessV0);
195195
foreach(var txout in Outputs)
196196
{
197197
ss.ReadWrite(txout);
@@ -203,7 +203,7 @@ internal override uint256 GetHashOutputs()
203203
internal override uint256 GetHashSequence()
204204
{
205205
uint256 hashSequence;
206-
BitcoinStream ss = CreateHashWriter(HashVersion.Witness);
206+
BitcoinStream ss = CreateHashWriter(HashVersion.WitnessV0);
207207
foreach(var input in Inputs)
208208
{
209209
ss.ReadWrite(input.Sequence);
@@ -215,7 +215,7 @@ internal override uint256 GetHashSequence()
215215
internal override uint256 GetHashPrevouts()
216216
{
217217
uint256 hashPrevouts;
218-
BitcoinStream ss = CreateHashWriter(HashVersion.Witness);
218+
BitcoinStream ss = CreateHashWriter(HashVersion.WitnessV0);
219219
foreach(var input in Inputs)
220220
{
221221
ss.ReadWrite(input.PrevOut);

NBitcoin.Tests/transaction_tests.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -3251,7 +3251,7 @@ public void bip143Test()
32513251
{
32523252
Transaction tx = Transaction.Parse("0100000002fff7f7881a8099afa6940d42d1e7f6362bec38171ea3edf433541db4e4ad969f0000000000eeffffffef51e1b804cc89d182d279655c3aa89e815b1b309fe287d9b2b55d57b90ec68a0100000000ffffffff02202cb206000000001976a9148280b37df378db99f66f85c95a783a76ac7a6d5988ac9093510d000000001976a9143bde42dbee7e4dbe6a21b2d50ce2f0167faa815988ac11000000", Network);
32533253
var output = tx.Outputs.CreateNewTxOut(Money.Satoshis(0x23c34600L), new Script(Encoders.Hex.DecodeData("76a9141d0f172a0ecb48aee1be1f2687d2963ae33f71a188ac")));
3254-
var h = tx.GetSignatureHash(output.ScriptPubKey, 1, SigHash.All, output, HashVersion.Witness);
3254+
var h = tx.GetSignatureHash(output.ScriptPubKey, 1, SigHash.All, output, HashVersion.WitnessV0);
32553255
Assert.Equal(new uint256(Encoders.Hex.DecodeData("c37af31116d1b27caf68aae9e3ac82f1477929014d5b917657d0eb49478cb670"), true), h);
32563256
}
32573257
[Fact]
@@ -3490,21 +3490,21 @@ public void CheckScriptCoinIsCoherent()
34903490
scriptCoin = new ScriptCoin(c, key.PubKey.WitHash.ScriptPubKey);
34913491
Assert.True(scriptCoin.RedeemType == RedeemType.P2SH);
34923492
Assert.True(scriptCoin.IsP2SH);
3493-
Assert.True(scriptCoin.GetHashVersion() == HashVersion.Witness);
3493+
Assert.True(scriptCoin.GetHashVersion() == HashVersion.WitnessV0);
34943494

34953495
//P2WSH
34963496
c.ScriptPubKey = key.PubKey.ScriptPubKey.WitHash.ScriptPubKey;
34973497
scriptCoin = new ScriptCoin(c, key.PubKey.ScriptPubKey);
34983498
Assert.True(scriptCoin.RedeemType == RedeemType.WitnessV0);
34993499
Assert.True(!scriptCoin.IsP2SH);
3500-
Assert.True(scriptCoin.GetHashVersion() == HashVersion.Witness);
3500+
Assert.True(scriptCoin.GetHashVersion() == HashVersion.WitnessV0);
35013501

35023502
//P2SH(P2WSH)
35033503
c.ScriptPubKey = key.PubKey.ScriptPubKey.WitHash.ScriptPubKey.Hash.ScriptPubKey;
35043504
scriptCoin = new ScriptCoin(c, key.PubKey.ScriptPubKey);
35053505
Assert.True(scriptCoin.RedeemType == RedeemType.WitnessV0);
35063506
Assert.True(scriptCoin.IsP2SH);
3507-
Assert.True(scriptCoin.GetHashVersion() == HashVersion.Witness);
3507+
Assert.True(scriptCoin.GetHashVersion() == HashVersion.WitnessV0);
35083508

35093509

35103510
Assert.Throws<ArgumentException>(() => new ScriptCoin(c, key.PubKey.ScriptPubKey.WitHash.ScriptPubKey));

NBitcoin/BIP174/PSBTInput.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ public void UpdateFromCoin(ICoin coin)
306306
}
307307
}
308308
if (Parent.Network.Consensus.NeverNeedPreviousTxForSigning ||
309-
coin.GetHashVersion() == HashVersion.Witness || witness_script != null)
309+
!coin.IsMalleable || witness_script != null)
310310
{
311311
witness_utxo = coin.TxOut;
312312
non_witness_utxo = null;
@@ -934,7 +934,7 @@ public bool TrySlimUTXO()
934934
return false;
935935

936936
if (Parent.Network.Consensus.NeverNeedPreviousTxForSigning ||
937-
coin.GetHashVersion() == HashVersion.Witness)
937+
!coin.IsMalleable)
938938
{
939939
if (WitnessUtxo == null)
940940
{

NBitcoin/Coin.cs

+9-5
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ bool CanGetScriptCode
4444
get;
4545
}
4646
HashVersion GetHashVersion();
47+
bool IsMalleable
48+
{
49+
get;
50+
}
4751
}
4852

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

65-
69+
public bool IsMalleable => Bearer.IsMalleable;
6670
public AssetId AssetId
6771
{
6872
get
@@ -235,7 +239,7 @@ public AssetId AssetId
235239
return Amount.Id;
236240
}
237241
}
238-
242+
public bool IsMalleable => TxOut.ScriptPubKey.IsMalleable;
239243
public AssetMoney Amount
240244
{
241245
get;
@@ -444,7 +448,7 @@ public virtual Script GetScriptCode()
444448
return key.AsKeyId().ScriptPubKey;
445449
return ScriptPubKey;
446450
}
447-
451+
public virtual bool IsMalleable => GetHashVersion() != HashVersion.WitnessV0;
448452
public virtual bool CanGetScriptCode
449453
{
450454
get
@@ -456,7 +460,7 @@ public virtual bool CanGetScriptCode
456460
public virtual HashVersion GetHashVersion()
457461
{
458462
if (PayToWitTemplate.Instance.CheckScriptPubKey(ScriptPubKey))
459-
return HashVersion.Witness;
463+
return HashVersion.WitnessV0;
460464
return HashVersion.Original;
461465
}
462466

@@ -769,7 +773,7 @@ public override HashVersion GetHashVersion()
769773
var isWitness = PayToWitTemplate.Instance.CheckScriptPubKey(ScriptPubKey) ||
770774
PayToWitTemplate.Instance.CheckScriptPubKey(Redeem) ||
771775
RedeemType == NBitcoin.RedeemType.WitnessV0;
772-
return isWitness ? HashVersion.Witness : HashVersion.Original;
776+
return isWitness ? HashVersion.WitnessV0 : HashVersion.Original;
773777
}
774778

775779
/// <summary>

NBitcoin/Policy/StandardTransactionPolicy.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ public TransactionPolicyError[] Check(Transaction transaction, ICoin[] spentCoin
111111
foreach (var input in transaction.Inputs.AsIndexedInputs())
112112
{
113113
var coin = spentCoins.FirstOrDefault(s => s.Outpoint == input.PrevOut);
114-
if (coin != null && coin.GetHashVersion() != HashVersion.Witness)
114+
if (coin != null && coin.IsMalleable)
115115
errors.Add(new InputPolicyError("Malleable input detected", input));
116116
}
117117
}

NBitcoin/Script.cs

+4-2
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,9 @@ public enum OpcodeType : byte
335335
public enum HashVersion
336336
{
337337
Original = 0,
338-
Witness = 1
338+
[Obsolete("Use HashVersion.WitnessV0 instead")]
339+
Witness = 1,
340+
WitnessV0 = 1
339341
}
340342

341343
public enum ScriptType
@@ -1095,7 +1097,7 @@ public static ScriptSigs CombineSignatures(Script scriptPubKey, TransactionCheck
10951097
{
10961098
scriptSig1 = input1.WitSig.ToScript();
10971099
scriptSig2 = input2.WitSig.ToScript();
1098-
hashVersion = HashVersion.Witness;
1100+
hashVersion = HashVersion.WitnessV0;
10991101
}
11001102

11011103
var context = new ScriptEvaluationContext();

NBitcoin/ScriptEvaluationContext.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -855,7 +855,7 @@ bool EvalScript(Script s, TransactionChecker checker, int hashversion)
855855

856856
var vch = _stack.Top(-1);
857857

858-
if (hashversion == (int)HashVersion.Witness && (ScriptVerify & ScriptVerify.MinimalIf) != 0)
858+
if (hashversion == (int)HashVersion.WitnessV0 && (ScriptVerify & ScriptVerify.MinimalIf) != 0)
859859
{
860860
if (vch.Length > 1)
861861
return SetError(ScriptError.MinimalIf);
@@ -1655,7 +1655,7 @@ private bool CheckPubKeyEncoding(byte[] vchPubKey, int sigversion)
16551655
Error = ScriptError.PubKeyType;
16561656
return false;
16571657
}
1658-
if ((ScriptVerify & ScriptVerify.WitnessPubkeyType) != 0 && sigversion == (int)HashVersion.Witness && !IsCompressedPubKey(vchPubKey))
1658+
if ((ScriptVerify & ScriptVerify.WitnessPubkeyType) != 0 && sigversion == (int)HashVersion.WitnessV0 && !IsCompressedPubKey(vchPubKey))
16591659
{
16601660
return SetError(ScriptError.WitnessPubkeyType);
16611661
}

NBitcoin/Transaction.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1988,7 +1988,7 @@ public TransactionCheckResult Check()
19881988

19891989
public virtual uint256 GetSignatureHash(Script scriptCode, int nIn, SigHash nHashType, TxOut spentOutput, HashVersion sigversion, PrecomputedTransactionData precomputedTransactionData)
19901990
{
1991-
if (sigversion == HashVersion.Witness)
1991+
if (sigversion == HashVersion.WitnessV0)
19921992
{
19931993
if (spentOutput?.Value == null || spentOutput.Value == TxOut.NullMoney)
19941994
throw new ArgumentException("The output being signed with the amount must be provided", nameof(spentOutput));
@@ -2146,7 +2146,7 @@ private static uint256 GetHash(BitcoinStream stream)
21462146
internal virtual uint256 GetHashOutputs()
21472147
{
21482148
uint256 hashOutputs;
2149-
BitcoinStream ss = CreateHashWriter(HashVersion.Witness);
2149+
BitcoinStream ss = CreateHashWriter(HashVersion.WitnessV0);
21502150
foreach (var txout in Outputs)
21512151
{
21522152
txout.ReadWrite(ss);
@@ -2158,7 +2158,7 @@ internal virtual uint256 GetHashOutputs()
21582158
internal virtual uint256 GetHashSequence()
21592159
{
21602160
uint256 hashSequence;
2161-
BitcoinStream ss = CreateHashWriter(HashVersion.Witness);
2161+
BitcoinStream ss = CreateHashWriter(HashVersion.WitnessV0);
21622162
foreach (var input in Inputs)
21632163
{
21642164
ss.ReadWrite((uint)input.Sequence);
@@ -2170,7 +2170,7 @@ internal virtual uint256 GetHashSequence()
21702170
internal virtual uint256 GetHashPrevouts()
21712171
{
21722172
uint256 hashPrevouts;
2173-
BitcoinStream ss = CreateHashWriter(HashVersion.Witness);
2173+
BitcoinStream ss = CreateHashWriter(HashVersion.WitnessV0);
21742174
foreach (var input in Inputs)
21752175
{
21762176
ss.ReadWrite(input.PrevOut);

NBitcoin/TransactionBuilder.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -2194,7 +2194,7 @@ public void EstimateSizes(Transaction tx, out int witSize, out int baseSize)
21942194
var coin = FindSignableCoin(txin) ?? FindCoin(txin.PrevOut);
21952195
if (coin == null)
21962196
throw CoinNotFound(txin);
2197-
if (coin.GetHashVersion() == HashVersion.Witness)
2197+
if (!coin.IsMalleable)
21982198
hasWitness = true;
21992199
else
22002200
nonWitnessCount++;
@@ -2263,7 +2263,7 @@ private void EstimateScriptSigSize(ICoin coin, ref int witSize, ref int baseSize
22632263

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

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

23632363
signatures = CombineScriptSigs(coin, scriptSig, signatures);
23642364

2365-
if (coin.GetHashVersion() == HashVersion.Witness)
2365+
if (!coin.IsMalleable)
23662366
{
23672367
txIn.WitScript = signatures;
23682368
if (scriptCoin != null)

0 commit comments

Comments
 (0)