public void ShouldPassTheLongestTestInBIP174() { JObject testcase = (JObject)testdata["final"]; var network = Network.TestNet; var master = ExtKey.Parse((string)testcase["master"], network); var masterFP = master.PrivateKey.PubKey.GetHDFingerPrint(); var tx = network.CreateTransaction(); tx.Version = 2; var scriptPubKey1 = Script.FromBytesUnsafe(Encoders.Hex.DecodeData((string)testcase["out1"]["script"])); var money1 = Money.Coins((decimal)testcase["out1"]["value"]); var scriptPubKey2 = Script.FromBytesUnsafe(Encoders.Hex.DecodeData((string)testcase["out2"]["script"])); var money2 = Money.Coins((decimal)testcase["out2"]["value"]); tx.Outputs.Add(new TxOut(value: money1, scriptPubKey: scriptPubKey1)); tx.Outputs.Add(new TxOut(value: money2, scriptPubKey: scriptPubKey2)); tx.Inputs.Add(new OutPoint(uint256.Parse((string)testcase["in1"]["txid"]), (uint)testcase["in1"]["index"])); tx.Inputs.Add(new OutPoint(uint256.Parse((string)testcase["in2"]["txid"]), (uint)testcase["in2"]["index"])); var expected = PSBT.Parse((string)testcase["psbt1"], Network.Main); var psbt = PSBT.FromTransaction(tx, Network.Main); Assert.Equal(expected, psbt, ComparerInstance); var prevtx1 = Transaction.Parse((string)testcase["prevtx1"], network); var prevtx2 = Transaction.Parse((string)testcase["prevtx2"], network); psbt.AddTransactions(prevtx1, prevtx2); var redeem1 = Script.FromBytesUnsafe(Encoders.Hex.DecodeData((string)testcase["redeem1"])); var redeem2 = Script.FromBytesUnsafe(Encoders.Hex.DecodeData((string)testcase["redeem2"])); var witness_script1 = Script.FromBytesUnsafe(Encoders.Hex.DecodeData((string)testcase["witness1"])); psbt.AddScripts(new[] { redeem1, redeem2, witness_script1 }); for (int i = 0; i < 6; i++) { var pk = testcase[$"pubkey{i}"]; var pubkey = new PubKey((string)pk["hex"]); var path = KeyPath.Parse((string)pk["path"]); psbt.AddKeyPath(pubkey, new RootedKeyPath(masterFP, path)); } expected = PSBT.Parse((string)testcase["psbt2"], Network.Main); Assert.Equal(expected, psbt, ComparerInstance); foreach(var psbtin in psbt.Inputs) psbtin.SighashType = SigHash.All; expected = PSBT.Parse((string)testcase["psbt3"], Network.Main); Assert.Equal(expected, psbt, ComparerInstance); psbt.AssertSanity(); var psbtForBob = psbt.Clone(); // path 1 ... alice Assert.Equal(psbt, psbtForBob, ComparerInstance); var aliceKey1 = master.Derive(new KeyPath((string)testcase["key7"]["path"])).PrivateKey; var aliceKey2 = master.Derive(new KeyPath((string)testcase["key8"]["path"])).PrivateKey; psbt.SignWithKeys(aliceKey1, aliceKey2); expected = PSBT.Parse((string)testcase["psbt4"], Network.Main); Assert.Equal(expected, psbt); // path 2 ... bob. var bobKey1 = master.Derive(new KeyPath((string)testcase["key9"]["path"])).PrivateKey; var bobKey2 = master.Derive(new KeyPath((string)testcase["key10"]["path"])).PrivateKey; var bobKeyhex1 = (string)testcase["key9"]["wif"]; var bobKeyhex2 = (string)testcase["key10"]["wif"]; Assert.Equal(bobKey1, new BitcoinSecret(bobKeyhex1, network).PrivateKey); Assert.Equal(bobKey2, new BitcoinSecret(bobKeyhex2, network).PrivateKey); psbtForBob.Settings.UseLowR = false; psbtForBob.SignWithKeys(bobKey1, bobKey2); expected = PSBT.Parse((string)testcase["psbt5"], Network.Main); Assert.Equal(expected, psbtForBob); // merge above 2 var combined = psbt.Combine(psbtForBob); expected = PSBT.Parse((string)testcase["psbtcombined"], Network.Main); Assert.Equal(expected, combined); Assert.True(combined.TryGetFee(out var fee)); Assert.Equal(Money.Coins(0.00010000m), fee); Assert.True(combined.TryGetEstimatedFeeRate(out var feeRate)); Assert.Equal(new FeeRate(21.6m).SatoshiPerByte, feeRate.SatoshiPerByte, 1); var finalized = psbt.Finalize(); expected = PSBT.Parse((string)testcase["psbtfinalized"], Network.Main); Assert.Equal(expected, finalized); var finalTX = psbt.ExtractTransaction(); var expectedTX = Transaction.Parse((string)testcase["txextracted"], network); AssertEx.CollectionEquals(expectedTX.ToBytes(), finalTX.ToBytes()); Assert.True(psbt.TryGetFee(out fee)); Assert.Equal(Money.Coins(0.00010000m), fee); Assert.True(psbt.TryGetEstimatedFeeRate(out feeRate)); Assert.Equal(new FeeRate(21.6m).SatoshiPerByte, feeRate.SatoshiPerByte, 2); }