Branch data Line data Source code
1 : : // Copyright (c) 2022 The Bitcoin Core developers
2 : : // Distributed under the MIT software license, see the accompanying
3 : : // file COPYING or https://www.opensource.org/licenses/mit-license.php.
4 : :
5 : : #include <psbt.h>
6 : :
7 : : #include <boost/test/unit_test.hpp>
8 : : #include <test/util/setup_common.h>
9 : :
10 : : BOOST_FIXTURE_TEST_SUITE(psbt_tests, BasicTestingSetup)
11 : :
12 : 10 : void CheckTimeLock(const std::string& base64_psbt, std::optional<uint32_t> timelock)
13 : : {
14 : 10 : util::Result<PartiallySignedTransaction> psbt = DecodeBase64PSBT(base64_psbt);
15 [ + - + - ]: 20 : BOOST_CHECK(psbt);
16 : :
17 [ + - ]: 10 : std::optional<uint32_t> computed_timelock = psbt->ComputeTimeLock();
18 [ + - ]: 10 : std::optional<CMutableTransaction> tx = psbt->GetUnsignedTx();
19 [ + + ]: 10 : if (timelock) {
20 [ + - + - : 18 : BOOST_CHECK(computed_timelock);
+ - ]
21 [ + - + - ]: 9 : BOOST_CHECK_EQUAL(*computed_timelock, *timelock);
22 [ + - + - : 18 : BOOST_CHECK(tx);
+ - ]
23 [ + - + - ]: 9 : BOOST_CHECK_EQUAL(tx->nLockTime, *timelock);
24 : : } else {
25 [ + - + - : 2 : BOOST_CHECK(!computed_timelock);
+ - ]
26 [ + - + - : 11 : BOOST_CHECK(!tx);
+ + ]
27 : : }
28 : 10 : }
29 : :
30 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(psbt2_timelock_test)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
31 : : {
32 [ + - ]: 1 : CheckTimeLock("cHNidP8BAgQCAAAAAQQBAQEFAQIB+wQCAAAAAAEOIAsK2SFBnByHGXNdctxzn56p4GONH+TB7vD5lECEgV/IAQ8EAAAAAAABAwgACK8vAAAAAAEEFgAUxDD2TEdW2jENvRoIVXLvKZkmJywAAQMIi73rCwAAAAABBBYAFE3Rk6yWSlasG54cyoRU/i9HT4UTAA==", 0);
33 [ + - ]: 1 : CheckTimeLock("cHNidP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEBAfsEAgAAAAABDiAPdY2/vU2nwWyKMwnDyB4RAPVh6mRttbAXUsSF4b3enwEPBAEAAAAAAQ4gOhs7PIN9ZInqejHY5sfdUDwAG+8+BpWOdXSAjWjKeKUBDwQAAAAAAAEDCE+TNXcAAAAAAQQWABQLE1LKzQPPaqG388jWOIZxs0peEQA=", 0);
34 [ + - ]: 1 : CheckTimeLock("cHNidP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEBAfsEAgAAAAABDiAPdY2/vU2nwWyKMwnDyB4RAPVh6mRttbAXUsSF4b3enwEPBAEAAAABEgQQJwAAAAEOIDobOzyDfWSJ6nox2ObH3VA8ABvvPgaVjnV0gI1oynilAQ8EAAAAAAABAwhPkzV3AAAAAAEEFgAUCxNSys0Dz2qht/PI1jiGcbNKXhEA", 10000);
35 [ + - ]: 1 : CheckTimeLock("cHNidP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEBAfsEAgAAAAABDiAPdY2/vU2nwWyKMwnDyB4RAPVh6mRttbAXUsSF4b3enwEPBAEAAAABEgQQJwAAAAEOIDobOzyDfWSJ6nox2ObH3VA8ABvvPgaVjnV0gI1oynilAQ8EAAAAAAESBCgjAAAAAQMIT5M1dwAAAAABBBYAFAsTUsrNA89qobfzyNY4hnGzSl4RAA==", 10000);
36 [ + - ]: 1 : CheckTimeLock("cHNidP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEBAfsEAgAAAAABDiAPdY2/vU2nwWyKMwnDyB4RAPVh6mRttbAXUsSF4b3enwEPBAEAAAABEgQQJwAAAAEOIDobOzyDfWSJ6nox2ObH3VA8ABvvPgaVjnV0gI1oynilAQ8EAAAAAAERBIyNxGIBEgQoIwAAAAEDCE+TNXcAAAAAAQQWABQLE1LKzQPPaqG388jWOIZxs0peEQA=", 10000);
37 [ + - ]: 1 : CheckTimeLock("cHNidP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEBAfsEAgAAAAABDiAPdY2/vU2nwWyKMwnDyB4RAPVh6mRttbAXUsSF4b3enwEPBAEAAAABEQSLjcRiARIEECcAAAABDiA6Gzs8g31kiep6Mdjmx91QPAAb7z4GlY51dICNaMp4pQEPBAAAAAABEQSMjcRiARIEKCMAAAABAwhPkzV3AAAAAAEEFgAUCxNSys0Dz2qht/PI1jiGcbNKXhEA", 10000);
38 [ + - ]: 1 : CheckTimeLock("cHNidP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEBAfsEAgAAAAABDiAPdY2/vU2nwWyKMwnDyB4RAPVh6mRttbAXUsSF4b3enwEPBAEAAAABEQSLjcRiAAEOIDobOzyDfWSJ6nox2ObH3VA8ABvvPgaVjnV0gI1oynilAQ8EAAAAAAERBIyNxGIBEgQoIwAAAAEDCE+TNXcAAAAAAQQWABQLE1LKzQPPaqG388jWOIZxs0peEQA=", 1657048460);
39 [ + - ]: 1 : CheckTimeLock("cHNidP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEBAfsEAgAAAAABDiAPdY2/vU2nwWyKMwnDyB4RAPVh6mRttbAXUsSF4b3enwEPBAEAAAABEQSLjcRiARIEECcAAAABDiA6Gzs8g31kiep6Mdjmx91QPAAb7z4GlY51dICNaMp4pQEPBAAAAAABEQSMjcRiAAEDCE+TNXcAAAAAAQQWABQLE1LKzQPPaqG388jWOIZxs0peEQA=", 1657048460);
40 [ + - ]: 1 : CheckTimeLock("cHNidP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEBAfsEAgAAAAABDiAPdY2/vU2nwWyKMwnDyB4RAPVh6mRttbAXUsSF4b3enwEPBAEAAAAAAQ4gOhs7PIN9ZInqejHY5sfdUDwAG+8+BpWOdXSAjWjKeKUBDwQAAAAAAREEjI3EYgABAwhPkzV3AAAAAAEEFgAUCxNSys0Dz2qht/PI1jiGcbNKXhEA", 1657048460);
41 [ + - ]: 1 : CheckTimeLock("cHNidP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEBAfsEAgAAAAABDiAPdY2/vU2nwWyKMwnDyB4RAPVh6mRttbAXUsSF4b3enwEPBAEAAAABEgQQJwAAAAEOIDobOzyDfWSJ6nox2ObH3VA8ABvvPgaVjnV0gI1oynilAQ8EAAAAAAERBIyNxGIAAQMIT5M1dwAAAAABBBYAFAsTUsrNA89qobfzyNY4hnGzSl4RAA==", std::nullopt);
42 : 1 : }
43 : :
44 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(psbt2_addinput)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
45 : : {
46 : 1 : FastRandomContext rng(/*fDeterministic=*/true);
47 : :
48 [ + - ]: 1 : CMutableTransaction mtx;
49 [ + - ]: 1 : PartiallySignedTransaction psbt(mtx, /*version=*/2);
50 [ - + ]: 1 : psbt.m_tx_modifiable.emplace();
51 [ + - ]: 1 : psbt.m_tx_modifiable->set(0, true);
52 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.inputs.size(), 0);
+ - ]
53 : :
54 : : // Same PSBT version is required
55 : 1 : uint256 txid;
56 : 1 : rng.fillrand(MakeWritableByteSpan(txid));
57 : 1 : PSBTInput psbtin_v0(/*psbt_version=*/0, Txid::FromUint256(txid), /*prev_out=*/0);
58 [ + - + - : 2 : BOOST_CHECK(!psbt.AddInput(psbtin_v0));
+ - + - ]
59 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.inputs.size(), 0);
+ - ]
60 : 1 : rng.fillrand(MakeWritableByteSpan(txid));
61 : 1 : PSBTInput psbtin(/*psbt_version=*/2, Txid::FromUint256(txid), /*prev_out=*/0);
62 [ + - + - : 2 : BOOST_CHECK(psbt.AddInput(psbtin));
+ - + - ]
63 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.inputs.size(), 1);
+ - ]
64 : :
65 : : // Duplicates are not allowed
66 [ + - + - : 2 : BOOST_CHECK(!psbt.AddInput(psbtin));
+ - + - ]
67 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.inputs.size(), 1);
+ - ]
68 : :
69 : : // Input with a unique txid is allowed
70 : 1 : rng.fillrand(MakeWritableByteSpan(txid));
71 : 1 : PSBTInput psbtin2(/*psbt_version=*/2, Txid::FromUint256(txid), /*prev_out=*/0);
72 [ + - + - : 2 : BOOST_CHECK(psbt.AddInput(psbtin2));
+ - + - ]
73 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.inputs.size(), 2);
+ - ]
74 : :
75 : : // Disabling inputs modifiable flag prevents adding new inputs
76 : 1 : psbt.m_tx_modifiable->set(0, false);
77 : 1 : rng.fillrand(MakeWritableByteSpan(txid));
78 : 1 : PSBTInput psbtin3(/*psbt_version=*/2, Txid::FromUint256(txid), /*prev_out=*/0);
79 [ + - + - : 2 : BOOST_CHECK(!psbt.AddInput(psbtin3));
+ - + - ]
80 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.inputs.size(), 2);
+ - ]
81 : 1 : psbt.m_tx_modifiable->set(0, true);
82 : :
83 : : // Make sure that timelock compatibility checks are working
84 : : // No previous required timelocks, new input with both height and time timelocks is allowed
85 : 1 : rng.fillrand(MakeWritableByteSpan(txid));
86 : 1 : PSBTInput psbtin4(/*psbt_version=*/2, Txid::FromUint256(txid), /*prev_out=*/0);
87 : 1 : psbtin4.time_locktime = LOCKTIME_THRESHOLD;
88 [ - + ]: 1 : psbtin4.height_locktime = 100;
89 [ + - + - : 2 : BOOST_CHECK(psbt.AddInput(psbtin4));
+ - + - ]
90 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.inputs.size(), 3);
+ - ]
91 : :
92 : : // Input with only a time timelock is allowed
93 : 1 : rng.fillrand(MakeWritableByteSpan(txid));
94 : 1 : PSBTInput psbtin5(/*psbt_version=*/2, Txid::FromUint256(txid), /*prev_out=*/0);
95 : 1 : psbtin5.time_locktime = LOCKTIME_THRESHOLD + 1;
96 [ + - + - : 2 : BOOST_CHECK(psbt.AddInput(psbtin5));
+ - + - ]
97 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.inputs.size(), 4);
+ - ]
98 : :
99 : : // Input with only a height timelock is not allowed because of previous
100 : 1 : rng.fillrand(MakeWritableByteSpan(txid));
101 : 1 : PSBTInput psbtin6(/*psbt_version=*/2, Txid::FromUint256(txid), /*prev_out=*/0);
102 [ - + ]: 1 : psbtin6.height_locktime = 100;
103 [ + - + - : 2 : BOOST_CHECK(!psbt.AddInput(psbtin6));
+ - + - ]
104 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.inputs.size(), 4);
+ - ]
105 : :
106 : : // Adding an input that already has a signature is allowed
107 : 1 : rng.fillrand(MakeWritableByteSpan(txid));
108 : 1 : PSBTInput psbtin7(/*psbt_version=*/2, Txid::FromUint256(txid), /*prev_out=*/0);
109 [ + - ]: 1 : psbtin7.final_script_sig << OP_1;
110 [ + - + - : 2 : BOOST_CHECK(psbt.AddInput(psbtin7));
+ - + - ]
111 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.inputs.size(), 5);
+ - ]
112 : :
113 : : // Same thing, but with other things that have signatures
114 : 1 : psbtin7.final_script_sig.clear();
115 [ + - ]: 1 : psbtin7.final_script_witness.stack.emplace_back();
116 [ + - + - : 2 : BOOST_CHECK(!psbt.AddInput(psbtin7));
+ - + - ]
117 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.inputs.size(), 5);
+ - ]
118 : 1 : psbtin7.final_script_witness.SetNull();
119 [ + - ]: 1 : psbtin7.partial_sigs.emplace();
120 [ + - + - : 2 : BOOST_CHECK(!psbt.AddInput(psbtin7));
+ - + - ]
121 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.inputs.size(), 5);
+ - ]
122 : 1 : psbtin7.partial_sigs.clear();
123 [ + - ]: 1 : psbtin7.m_tap_key_sig.push_back(0);
124 [ + - + - : 2 : BOOST_CHECK(!psbt.AddInput(psbtin7));
+ - + - ]
125 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.inputs.size(), 5);
+ - ]
126 [ + - ]: 1 : psbtin7.m_tap_key_sig.clear();
127 [ + - ]: 1 : psbtin7.m_tap_script_sigs.emplace();
128 [ + - + - : 2 : BOOST_CHECK(!psbt.AddInput(psbtin7));
+ - + - ]
129 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.inputs.size(), 5);
+ - ]
130 : 1 : psbtin7.m_tap_script_sigs.clear();
131 [ + - ]: 1 : psbtin7.m_musig2_partial_sigs.emplace();
132 [ + - + - : 2 : BOOST_CHECK(!psbt.AddInput(psbtin7));
+ - + - ]
133 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.inputs.size(), 5);
+ - ]
134 : :
135 : : // Adding an input that changes the timelock is no longer allowed
136 : 1 : rng.fillrand(MakeWritableByteSpan(txid));
137 : 1 : PSBTInput psbtin8(/*psbt_version=*/2, Txid::FromUint256(txid), /*prev_out=*/0);
138 : 1 : psbtin8.time_locktime = LOCKTIME_THRESHOLD + 2;
139 [ + - + - : 2 : BOOST_CHECK(!psbt.AddInput(psbtin8));
+ - + - ]
140 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.inputs.size(), 5);
+ - ]
141 : 2 : }
142 : :
143 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(psbt2_addoutput)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
144 : : {
145 : 1 : CMutableTransaction mtx;
146 [ + - ]: 1 : PartiallySignedTransaction psbt(mtx, /*version=*/2);
147 [ - + ]: 1 : psbt.m_tx_modifiable.emplace();
148 [ + - ]: 1 : psbt.m_tx_modifiable->set(1, true);
149 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.outputs.size(), 0);
+ - ]
150 : :
151 : : // Same PSBT version is required
152 : 1 : PSBTOutput psbtout_v0(/*psbt_version=*/0, /*amount=*/1, CScript());
153 [ + - + - : 2 : BOOST_CHECK(!psbt.AddOutput(psbtout_v0));
+ - + - ]
154 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.outputs.size(), 0);
+ - ]
155 : 1 : PSBTOutput psbtout(/*psbt_version=*/2, /*amount=*/1, CScript());
156 [ + - + - : 2 : BOOST_CHECK(psbt.AddOutput(psbtout));
+ - + - ]
157 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.outputs.size(), 1);
+ - ]
158 : :
159 : : // Disabling outputs modifiable flag prevents adding new outputs
160 : 1 : psbt.m_tx_modifiable->set(1, false);
161 : 1 : PSBTOutput psbtout2(/*psbt_version=*/2, /*amount=*/1, CScript());
162 [ + - + - : 2 : BOOST_CHECK(!psbt.AddOutput(psbtout2));
+ - + - ]
163 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.outputs.size(), 1);
+ - ]
164 : 1 : psbt.m_tx_modifiable->set(1, true);
165 : 1 : PSBTOutput psbtout3(/*psbt_version=*/2, /*amount=*/1, CScript());
166 [ + - + - : 2 : BOOST_CHECK(psbt.AddOutput(psbtout3));
+ - + - ]
167 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.outputs.size(), 2);
+ - ]
168 : 2 : }
169 : :
170 : : BOOST_AUTO_TEST_SUITE_END()
|