Skip to content

Commit 39f79a7

Browse files
committed
Fix build and tests and bugs related to PSBTs
1 parent 660ef7e commit 39f79a7

File tree

8 files changed

+48
-29
lines changed

8 files changed

+48
-29
lines changed

NBitcoin.Tests/PSBT2Tests.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,6 @@ public void PSBT2_CreateAndSerialize()
206206
// Create a simple dummy unsigned transaction with more inputs and outputs.
207207
Transaction tx = Network.Main.CreateTransaction();
208208

209-
210209
tx.Inputs.Add(new TxIn(new OutPoint(uint256.Zero, 0)));
211210
tx.Outputs.Add(new TxOut(Money.Coins(1.0m), new Script()));
212211
tx.Inputs.Add(new TxIn(new OutPoint(uint256.Zero, 1)));

NBitcoin.Tests/PSBTTests.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,11 @@ public static void ShouldThrowExceptionForInvalidData()
3939
}
4040
}
4141

42-
[Fact]
42+
[Theory]
43+
[InlineData(PSBTVersion.PSBTv0)]
44+
[InlineData(PSBTVersion.PSBTv2)]
4345
[Trait("UnitTest", "UnitTest")]
44-
public static void ShouldCalculateBalanceOfHDKey()
46+
public static void ShouldCalculateBalanceOfHDKey(PSBTVersion version)
4547
{
4648
foreach (var network in new[] { Network.Main, Altcoins.BGold.Instance.Mainnet })
4749
{
@@ -77,7 +79,7 @@ public static void ShouldCalculateBalanceOfHDKey()
7779
builder.SetChange(bob);
7880
builder.SendFees(Money.Coins(0.001m));
7981

80-
var psbt = builder.BuildPSBT(false);
82+
var psbt = builder.BuildPSBT(false, version);
8183
psbt.AddKeyPath(aliceMaster, new KeyPath("1/2/3"));
8284
psbt.AddKeyPath(bobMaster, new KeyPath("4/5/6"));
8385

@@ -382,9 +384,11 @@ public void ShouldFailToSignForTestcaseInvalidForSigner()
382384
}
383385
}
384386

385-
[Fact]
387+
[Theory]
388+
[InlineData(PSBTVersion.PSBTv0)]
389+
[InlineData(PSBTVersion.PSBTv2)]
386390
[Trait("UnitTest", "UnitTest")]
387-
public void OutputKeyPathCorrect()
391+
public void OutputKeyPathCorrect(PSBTVersion version)
388392
{
389393
var keys = Enumerable.Range(0, 5).Select(_ => new ExtKey()).ToArray();
390394

@@ -403,7 +407,7 @@ public void OutputKeyPathCorrect()
403407
builder.SendEstimatedFees(new FeeRate(1.0m));
404408
builder.Send(BitcoinAddress.Create("bc1qeef3jecqytj8j2xnjzduf5mu9c6jsqwd4hmvyv2zw8hzpf7a47nqrws5sn", Network.Main), Money.Coins(0.2m));
405409
builder.SetChange(changeRedeem.WitHash.ScriptPubKey);
406-
var psbt = builder.BuildPSBT(false);
410+
var psbt = builder.BuildPSBT(false, version);
407411
psbt.AddScripts(changeRedeem);
408412
foreach (var k in accountKeys)
409413
{

NBitcoin.Tests/RPCClientTests.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1763,8 +1763,10 @@ public async Task CanGenerateBlocks(RPCWalletType walletType)
17631763
}
17641764
}
17651765

1766-
[Fact]
1767-
public async Task UpdatePSBTInRPCShouldIncludePreviousTX()
1766+
[Theory]
1767+
[InlineData(PSBTVersion.PSBTv0)]
1768+
[InlineData(PSBTVersion.PSBTv2)]
1769+
public async Task UpdatePSBTInRPCShouldIncludePreviousTX(PSBTVersion version)
17681770
{
17691771
using (var builder = NodeBuilderEx.Create())
17701772
{
@@ -1779,7 +1781,7 @@ public async Task UpdatePSBTInRPCShouldIncludePreviousTX()
17791781
txbuilder.SetChange(await client.GetNewAddressAsync());
17801782
txbuilder.SendFees(Money.Satoshis(1000));
17811783
txbuilder.Send(new Key().PubKey.GetScriptPubKey(ScriptPubKeyType.Legacy), Money.Coins(1.0m));
1782-
var psbt = txbuilder.BuildPSBT(false);
1784+
var psbt = txbuilder.BuildPSBT(false, version);
17831785

17841786
var resp = await client.WalletProcessPSBTAsync(psbt, false);
17851787
Assert.NotNull(resp.PSBT.Inputs[0].NonWitnessUtxo);

NBitcoin.Tests/sample_tests.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -250,9 +250,11 @@ public void CanBuildSegwitP2SHMultisigTransactions()
250250
}
251251
}
252252

253-
[Fact]
253+
[Theory]
254+
[InlineData(PSBTVersion.PSBTv0)]
255+
[InlineData(PSBTVersion.PSBTv2)]
254256
[Trait("UnitTest", "UnitTest")]
255-
public void CanBuildSegwitP2SHMultisigTransactionsWithPSBT()
257+
public void CanBuildSegwitP2SHMultisigTransactionsWithPSBT(PSBTVersion version)
256258
{
257259
using (var nodeBuilder = NodeBuilderEx.Create())
258260
{
@@ -287,7 +289,7 @@ public void CanBuildSegwitP2SHMultisigTransactionsWithPSBT()
287289
.SubtractFees()
288290
.SetChange(new Key())
289291
.SendEstimatedFees(rate)
290-
.BuildPSBT(true);
292+
.BuildPSBT(true, version);
291293
Assert.True(partiallySignedTx.Inputs.All(i => i.PartialSigs.Count == 1));
292294

293295
partiallySignedTx = PSBT.Load(partiallySignedTx.ToBytes(), Network.Main);
@@ -308,9 +310,11 @@ public void CanBuildSegwitP2SHMultisigTransactionsWithPSBT()
308310
}
309311

310312

311-
[Fact]
313+
[Theory]
314+
[InlineData(PSBTVersion.PSBTv0)]
315+
[InlineData(PSBTVersion.PSBTv2)]
312316
[Trait("UnitTest", "UnitTest")]
313-
public void CanSignPSBTWithRootAndAccountKey()
317+
public void CanSignPSBTWithRootAndAccountKey(PSBTVersion version)
314318
{
315319
using (var nodeBuilder = NodeBuilderEx.Create())
316320
{
@@ -360,7 +364,7 @@ public void CanSignPSBTWithRootAndAccountKey()
360364
.Send(destination, amount)
361365
.SetChange(changeAddress.Address)
362366
.SendFees(fee)
363-
.BuildPSBT(false);
367+
.BuildPSBT(false, version);
364368
partiallySignedTx.AddKeyPath(masterKey, addresses.Concat(new[] { changeAddress }).Select(a => a.FullAddressPath.KeyPath).ToArray());
365369
var expectedBalance = -amount - fee;
366370
var actualBalance = partiallySignedTx.GetBalance(ScriptPubKeyType.Segwit, accountKey, accountKeyPath);

NBitcoin.Tests/transaction_tests.cs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2358,6 +2358,7 @@ public void CanBuildTransaction(PSBTVersion version)
23582358
txBuilder.StandardTransactionPolicy = EasyPolicy;
23592359
txBuilder.MergeOutputs = false;
23602360
var tx = txBuilder
2361+
.SetLockTime(1)
23612362
.AddCoins(allCoins)
23622363
.AddKeys(keys)
23632364
.Send(destinations[0], Money.Parse("6") * 2)
@@ -2370,7 +2371,8 @@ public void CanBuildTransaction(PSBTVersion version)
23702371
Assert.True(txBuilder.Verify(tx, "0.0001"));
23712372

23722373
// Let's check if PSBT can be finalized
2373-
var psbt = txBuilder.BuildPSBT(true);
2374+
var psbt = txBuilder.BuildPSBT(true, version);
2375+
Assert.Equal(new LockTime(1), psbt.GetGlobalTransaction().LockTime);
23742376
Assert.All(psbt.Inputs, input => input.PartialSigs.Any()); // All inputs should have partial sigs
23752377
Assert.False(psbt.IsAllFinalized());
23762378
Assert.False(psbt.TryFinalize(out _));
@@ -3191,9 +3193,11 @@ public void CanCreateBigTransactionsWithLotsOfInputs()
31913193
var ex = Assert.Throws<NotEnoughFundsException>(() => tx = builder.BuildTransaction(true));
31923194
Assert.Contains("You may have", ex.Message);
31933195
}
3194-
[Fact]
3196+
[Theory]
3197+
[InlineData(PSBTVersion.PSBTv0)]
3198+
[InlineData(PSBTVersion.PSBTv2)]
31953199
[Trait("UnitTest", "UnitTest")]
3196-
public void CanSignWithCoinSpecificKey()
3200+
public void CanSignWithCoinSpecificKey(PSBTVersion version)
31973201
{
31983202
var k = new Key();
31993203
var addr = k.GetScriptPubKey(ScriptPubKeyType.Segwit);
@@ -3206,7 +3210,7 @@ public void CanSignWithCoinSpecificKey()
32063210
builder.SetChange(new Key());
32073211
builder.SendAllRemainingToChange();
32083212
builder.SendEstimatedFees(new FeeRate(1.0m));
3209-
var psbt = builder.BuildPSBT(true);
3213+
var psbt = builder.BuildPSBT(true, version);
32103214
Assert.True(psbt.Inputs.FindIndexedInput(coins[0].Outpoint).TryFinalizeInput(out _));
32113215
Assert.False(psbt.Inputs.FindIndexedInput(coins[1].Outpoint).TryFinalizeInput(out _));
32123216
}
@@ -3281,10 +3285,12 @@ public void TransactionBuilderDoesNotRunForever()
32813285
Assert.Equal(3, tx.Inputs.Count);
32823286
}
32833287

3284-
[Fact]
3288+
[Theory]
3289+
[InlineData(PSBTVersion.PSBTv0)]
3290+
[InlineData(PSBTVersion.PSBTv2)]
32853291
[Trait("UnitTest", "UnitTest")]
32863292
// Fix https://github.com/MetacoSA/NBitcoin/issues/746
3287-
public void TransactionBuilderDoesNotCreateInvalidTx()
3293+
public void TransactionBuilderDoesNotCreateInvalidTx(PSBTVersion version)
32883294
{
32893295
var masterKey = new ExtKey();
32903296
var keys = Enumerable.Range(0, 4).Select(x => masterKey.Derive((uint)x)).ToArray();
@@ -3300,7 +3306,7 @@ public void TransactionBuilderDoesNotCreateInvalidTx()
33003306
builder.SendAllRemaining(new Key());
33013307
builder.SendEstimatedFees(new FeeRate(10m));
33023308

3303-
var psbt = builder.BuildPSBT(false);
3309+
var psbt = builder.BuildPSBT(false, version);
33043310
builder = builder.AddKeys(keys.ToArray());
33053311
builder.SignPSBT(psbt);
33063312
psbt.Finalize();

NBitcoin/BIP174/Maps.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ public Map() : base(BytesComparer.Instance)
8383
{
8484

8585
}
86-
86+
public void Add<T>(byte key, T val) => Add<T>([key], val);
8787
public void Add<T>(byte[] key, T val)
8888
{
8989
if (typeof(T) == typeof(byte[]))
@@ -110,6 +110,8 @@ public void Add<T>(byte[] key, T val)
110110
{
111111
base.Add(key, ((VarInt)(object)val!).ToBytes());
112112
}
113+
else
114+
throw new NotSupportedException("Does not support adding " + typeof(T).Name);
113115
}
114116

115117
public IEnumerable<KeyValuePair<byte[], T>> RemoveAll<T>(byte prefixKey) => RemoveAll<T>([prefixKey]);

NBitcoin/BIP370/PSBT2.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,11 @@ private static Maps CreateMap(Transaction tx, Network network)
1919
{
2020
var m = new Maps();
2121
var global = m.NewMap();
22-
global.Add([PSBT2Constants.PSBT_GLOBAL_TX_VERSION], tx.Version);
23-
global.Add([PSBT2Constants.PSBT_GLOBAL_INPUT_COUNT], new VarInt((uint)tx.Inputs.Count));
24-
global.Add([PSBT2Constants.PSBT_GLOBAL_OUTPUT_COUNT], new VarInt((uint)tx.Outputs.Count));
25-
22+
global.Add(PSBT2Constants.PSBT_GLOBAL_TX_VERSION, tx.Version);
23+
global.Add(PSBT2Constants.PSBT_GLOBAL_INPUT_COUNT, new VarInt((uint)tx.Inputs.Count));
24+
global.Add(PSBT2Constants.PSBT_GLOBAL_OUTPUT_COUNT, new VarInt((uint)tx.Outputs.Count));
25+
if (tx.LockTime != LockTime.Zero)
26+
global.Add(PSBT2Constants.PSBT_GLOBAL_FALLBACK_LOCKTIME, (uint)tx.LockTime);
2627
foreach (var txin in tx.Inputs)
2728
{
2829
PSBT2Input.FillMap(m.NewMap(), txin);

NBitcoin/TransactionBuilder.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,7 @@ private static Transaction RemoveSigs(Transaction tx)
495495
if (!hasSig)
496496
return tx;
497497
tx = tx.Clone();
498+
tx.RemoveSignatures();
498499
return tx;
499500
}
500501

@@ -1699,7 +1700,7 @@ public TransactionBuilder ExtractSignatures(PSBT psbt, Transaction transaction)
16991700
throw new ArgumentNullException(nameof(psbt));
17001701
if (transaction is null)
17011702
throw new ArgumentNullException(nameof(transaction));
1702-
var signingContext = new TransactionSigningContext(this, transaction, psbt.Version, signingOptions);
1703+
var signingContext = new TransactionSigningContext(this, psbt, transaction, signingOptions);
17031704
ExtractExistingSignatures(signingContext);
17041705
psbt.Combine(signingContext.PSBT);
17051706
return this;

0 commit comments

Comments
 (0)