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 <addresstype.h>
6 : : #include <key.h>
7 : : #include <psbt.h>
8 : : #include <script/descriptor.h>
9 : : #include <script/script.h>
10 : : #include <script/signingprovider.h>
11 : : #include <script/solver.h>
12 : : #include <test/util/setup_common.h>
13 : : #include <util/strencodings.h>
14 : : #include <util/string.h>
15 : :
16 : : #include <boost/test/unit_test.hpp>
17 : :
18 : : #include <string>
19 : : #include <vector>
20 : :
21 : : BOOST_FIXTURE_TEST_SUITE(psbt_tests, BasicTestingSetup)
22 : :
23 : 2 : static PSBTProprietary MakeProprietary(uint64_t subtype, uint8_t key_data, uint8_t value)
24 : : {
25 [ + - + - ]: 2 : return PSBTProprietary{
26 : : .subtype = subtype,
27 : : .identifier = {'p', 's', 'b', 't'},
28 : : .key = {key_data},
29 : : .value = {value},
30 : 2 : };
31 : : }
32 : :
33 : 10 : void CheckTimeLock(const std::string& base64_psbt, std::optional<uint32_t> timelock)
34 : : {
35 : 10 : util::Result<PartiallySignedTransaction> psbt = DecodeBase64PSBT(base64_psbt);
36 [ + - + - ]: 20 : BOOST_CHECK(psbt);
37 : :
38 [ + - ]: 10 : std::optional<uint32_t> computed_timelock = psbt->ComputeTimeLock();
39 [ + - ]: 10 : std::optional<CMutableTransaction> tx = psbt->GetUnsignedTx();
40 [ + + ]: 10 : if (timelock) {
41 [ + - + - : 18 : BOOST_CHECK(computed_timelock);
+ - ]
42 [ + - + - ]: 9 : BOOST_CHECK_EQUAL(*computed_timelock, *timelock);
43 [ + - + - : 18 : BOOST_CHECK(tx);
+ - ]
44 [ + - + - ]: 9 : BOOST_CHECK_EQUAL(tx->nLockTime, *timelock);
45 : : } else {
46 [ + - + - : 2 : BOOST_CHECK(!computed_timelock);
+ - ]
47 [ + - + - : 11 : BOOST_CHECK(!tx);
+ + ]
48 : : }
49 : 10 : }
50 : :
51 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(psbt2_timelock_test)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
52 : : {
53 [ + - ]: 1 : CheckTimeLock("cHNidP8BAgQCAAAAAQQBAQEFAQIB+wQCAAAAAAEOIAsK2SFBnByHGXNdctxzn56p4GONH+TB7vD5lECEgV/IAQ8EAAAAAAABAwgACK8vAAAAAAEEFgAUxDD2TEdW2jENvRoIVXLvKZkmJywAAQMIi73rCwAAAAABBBYAFE3Rk6yWSlasG54cyoRU/i9HT4UTAA==", 0);
54 [ + - ]: 1 : CheckTimeLock("cHNidP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEBAfsEAgAAAAABDiAPdY2/vU2nwWyKMwnDyB4RAPVh6mRttbAXUsSF4b3enwEPBAEAAAAAAQ4gOhs7PIN9ZInqejHY5sfdUDwAG+8+BpWOdXSAjWjKeKUBDwQAAAAAAAEDCE+TNXcAAAAAAQQWABQLE1LKzQPPaqG388jWOIZxs0peEQA=", 0);
55 [ + - ]: 1 : CheckTimeLock("cHNidP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEBAfsEAgAAAAABDiAPdY2/vU2nwWyKMwnDyB4RAPVh6mRttbAXUsSF4b3enwEPBAEAAAABEgQQJwAAAAEOIDobOzyDfWSJ6nox2ObH3VA8ABvvPgaVjnV0gI1oynilAQ8EAAAAAAABAwhPkzV3AAAAAAEEFgAUCxNSys0Dz2qht/PI1jiGcbNKXhEA", 10000);
56 [ + - ]: 1 : CheckTimeLock("cHNidP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEBAfsEAgAAAAABDiAPdY2/vU2nwWyKMwnDyB4RAPVh6mRttbAXUsSF4b3enwEPBAEAAAABEgQQJwAAAAEOIDobOzyDfWSJ6nox2ObH3VA8ABvvPgaVjnV0gI1oynilAQ8EAAAAAAESBCgjAAAAAQMIT5M1dwAAAAABBBYAFAsTUsrNA89qobfzyNY4hnGzSl4RAA==", 10000);
57 [ + - ]: 1 : CheckTimeLock("cHNidP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEBAfsEAgAAAAABDiAPdY2/vU2nwWyKMwnDyB4RAPVh6mRttbAXUsSF4b3enwEPBAEAAAABEgQQJwAAAAEOIDobOzyDfWSJ6nox2ObH3VA8ABvvPgaVjnV0gI1oynilAQ8EAAAAAAERBIyNxGIBEgQoIwAAAAEDCE+TNXcAAAAAAQQWABQLE1LKzQPPaqG388jWOIZxs0peEQA=", 10000);
58 [ + - ]: 1 : CheckTimeLock("cHNidP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEBAfsEAgAAAAABDiAPdY2/vU2nwWyKMwnDyB4RAPVh6mRttbAXUsSF4b3enwEPBAEAAAABEQSLjcRiARIEECcAAAABDiA6Gzs8g31kiep6Mdjmx91QPAAb7z4GlY51dICNaMp4pQEPBAAAAAABEQSMjcRiARIEKCMAAAABAwhPkzV3AAAAAAEEFgAUCxNSys0Dz2qht/PI1jiGcbNKXhEA", 10000);
59 [ + - ]: 1 : CheckTimeLock("cHNidP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEBAfsEAgAAAAABDiAPdY2/vU2nwWyKMwnDyB4RAPVh6mRttbAXUsSF4b3enwEPBAEAAAABEQSLjcRiAAEOIDobOzyDfWSJ6nox2ObH3VA8ABvvPgaVjnV0gI1oynilAQ8EAAAAAAERBIyNxGIBEgQoIwAAAAEDCE+TNXcAAAAAAQQWABQLE1LKzQPPaqG388jWOIZxs0peEQA=", 1657048460);
60 [ + - ]: 1 : CheckTimeLock("cHNidP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEBAfsEAgAAAAABDiAPdY2/vU2nwWyKMwnDyB4RAPVh6mRttbAXUsSF4b3enwEPBAEAAAABEQSLjcRiARIEECcAAAABDiA6Gzs8g31kiep6Mdjmx91QPAAb7z4GlY51dICNaMp4pQEPBAAAAAABEQSMjcRiAAEDCE+TNXcAAAAAAQQWABQLE1LKzQPPaqG388jWOIZxs0peEQA=", 1657048460);
61 [ + - ]: 1 : CheckTimeLock("cHNidP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEBAfsEAgAAAAABDiAPdY2/vU2nwWyKMwnDyB4RAPVh6mRttbAXUsSF4b3enwEPBAEAAAAAAQ4gOhs7PIN9ZInqejHY5sfdUDwAG+8+BpWOdXSAjWjKeKUBDwQAAAAAAREEjI3EYgABAwhPkzV3AAAAAAEEFgAUCxNSys0Dz2qht/PI1jiGcbNKXhEA", 1657048460);
62 [ + - ]: 1 : CheckTimeLock("cHNidP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEBAfsEAgAAAAABDiAPdY2/vU2nwWyKMwnDyB4RAPVh6mRttbAXUsSF4b3enwEPBAEAAAABEgQQJwAAAAEOIDobOzyDfWSJ6nox2ObH3VA8ABvvPgaVjnV0gI1oynilAQ8EAAAAAAERBIyNxGIAAQMIT5M1dwAAAAABBBYAFAsTUsrNA89qobfzyNY4hnGzSl4RAA==", std::nullopt);
63 : 1 : }
64 : :
65 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(psbt2_addinput)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
66 : : {
67 : 1 : FastRandomContext rng(/*fDeterministic=*/true);
68 : :
69 [ + - ]: 1 : CMutableTransaction mtx;
70 [ + - ]: 1 : PartiallySignedTransaction psbt(mtx, /*version=*/2);
71 [ - + ]: 1 : psbt.m_tx_modifiable.emplace();
72 [ + - ]: 1 : psbt.m_tx_modifiable->set(0, true);
73 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.inputs.size(), 0);
+ - ]
74 : :
75 : : // Same PSBT version is required
76 : 1 : uint256 txid;
77 : 1 : rng.fillrand(MakeWritableByteSpan(txid));
78 : 1 : PSBTInput psbtin_v0(/*psbt_version=*/0, Txid::FromUint256(txid), /*prev_out=*/0);
79 [ + - + - : 2 : BOOST_CHECK(!psbt.AddInput(psbtin_v0));
+ - + - ]
80 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.inputs.size(), 0);
+ - ]
81 : 1 : rng.fillrand(MakeWritableByteSpan(txid));
82 : 1 : PSBTInput psbtin(/*psbt_version=*/2, Txid::FromUint256(txid), /*prev_out=*/0);
83 [ + - + - : 2 : BOOST_CHECK(psbt.AddInput(psbtin));
+ - + - +
- ]
84 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.inputs.size(), 1);
+ - ]
85 : :
86 : : // Duplicates are not allowed
87 [ + - + - : 2 : BOOST_CHECK(!psbt.AddInput(psbtin));
+ - + - ]
88 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.inputs.size(), 1);
+ - ]
89 : :
90 : : // Input with a unique txid is allowed
91 : 1 : rng.fillrand(MakeWritableByteSpan(txid));
92 : 1 : PSBTInput psbtin2(/*psbt_version=*/2, Txid::FromUint256(txid), /*prev_out=*/0);
93 [ + - + - : 2 : BOOST_CHECK(psbt.AddInput(psbtin2));
+ - + - ]
94 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.inputs.size(), 2);
+ - ]
95 : :
96 : : // Disabling inputs modifiable flag prevents adding new inputs
97 : 1 : psbt.m_tx_modifiable->set(0, false);
98 : 1 : rng.fillrand(MakeWritableByteSpan(txid));
99 : 1 : PSBTInput psbtin3(/*psbt_version=*/2, Txid::FromUint256(txid), /*prev_out=*/0);
100 [ + - + - : 2 : BOOST_CHECK(!psbt.AddInput(psbtin3));
+ - + - ]
101 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.inputs.size(), 2);
+ - ]
102 : 1 : psbt.m_tx_modifiable->set(0, true);
103 : :
104 : : // Make sure that timelock compatibility checks are working
105 : : // No previous required timelocks, new input with both height and time timelocks is allowed
106 : 1 : rng.fillrand(MakeWritableByteSpan(txid));
107 : 1 : PSBTInput psbtin4(/*psbt_version=*/2, Txid::FromUint256(txid), /*prev_out=*/0);
108 : 1 : psbtin4.time_locktime = LOCKTIME_THRESHOLD;
109 [ - + ]: 1 : psbtin4.height_locktime = 100;
110 [ + - + - : 2 : BOOST_CHECK(psbt.AddInput(psbtin4));
+ - + - ]
111 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.inputs.size(), 3);
+ - ]
112 : :
113 : : // Input with only a time timelock is allowed
114 : 1 : rng.fillrand(MakeWritableByteSpan(txid));
115 : 1 : PSBTInput psbtin5(/*psbt_version=*/2, Txid::FromUint256(txid), /*prev_out=*/0);
116 : 1 : psbtin5.time_locktime = LOCKTIME_THRESHOLD + 1;
117 [ + - + - : 2 : BOOST_CHECK(psbt.AddInput(psbtin5));
+ - + - ]
118 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.inputs.size(), 4);
+ - ]
119 : :
120 : : // Input with only a height timelock is not allowed because of previous
121 : 1 : rng.fillrand(MakeWritableByteSpan(txid));
122 : 1 : PSBTInput psbtin6(/*psbt_version=*/2, Txid::FromUint256(txid), /*prev_out=*/0);
123 [ - + ]: 1 : psbtin6.height_locktime = 100;
124 [ + - + - : 2 : BOOST_CHECK(!psbt.AddInput(psbtin6));
+ - + - ]
125 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.inputs.size(), 4);
+ - ]
126 : :
127 : : // Adding an input that already has a signature is allowed
128 : 1 : rng.fillrand(MakeWritableByteSpan(txid));
129 : 1 : PSBTInput psbtin7(/*psbt_version=*/2, Txid::FromUint256(txid), /*prev_out=*/0);
130 [ + - ]: 1 : psbtin7.final_script_sig << OP_1;
131 [ + - + - : 2 : BOOST_CHECK(psbt.AddInput(psbtin7));
+ - + - ]
132 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.inputs.size(), 5);
+ - ]
133 : :
134 : : // Same thing, but with other things that have signatures
135 : 1 : psbtin7.final_script_sig.clear();
136 [ + - ]: 1 : psbtin7.final_script_witness.stack.emplace_back();
137 [ + - + - : 2 : BOOST_CHECK(!psbt.AddInput(psbtin7));
+ - + - ]
138 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.inputs.size(), 5);
+ - ]
139 : 1 : psbtin7.final_script_witness.SetNull();
140 [ + - ]: 1 : psbtin7.partial_sigs.emplace();
141 [ + - + - : 2 : BOOST_CHECK(!psbt.AddInput(psbtin7));
+ - + - ]
142 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.inputs.size(), 5);
+ - ]
143 : 1 : psbtin7.partial_sigs.clear();
144 [ + - ]: 1 : psbtin7.m_tap_key_sig.push_back(0);
145 [ + - + - : 2 : BOOST_CHECK(!psbt.AddInput(psbtin7));
+ - + - ]
146 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.inputs.size(), 5);
+ - ]
147 [ + - ]: 1 : psbtin7.m_tap_key_sig.clear();
148 [ + - ]: 1 : psbtin7.m_tap_script_sigs.emplace();
149 [ + - + - : 2 : BOOST_CHECK(!psbt.AddInput(psbtin7));
+ - + - ]
150 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.inputs.size(), 5);
+ - ]
151 : 1 : psbtin7.m_tap_script_sigs.clear();
152 [ + - ]: 1 : psbtin7.m_musig2_partial_sigs.emplace();
153 [ + - + - : 2 : BOOST_CHECK(!psbt.AddInput(psbtin7));
+ - + - ]
154 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.inputs.size(), 5);
+ - ]
155 : :
156 : : // Adding an input that changes the timelock is no longer allowed
157 : 1 : rng.fillrand(MakeWritableByteSpan(txid));
158 : 1 : PSBTInput psbtin8(/*psbt_version=*/2, Txid::FromUint256(txid), /*prev_out=*/0);
159 : 1 : psbtin8.time_locktime = LOCKTIME_THRESHOLD + 2;
160 [ + - + - : 2 : BOOST_CHECK(!psbt.AddInput(psbtin8));
+ - + - ]
161 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.inputs.size(), 5);
+ - ]
162 : 2 : }
163 : :
164 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(psbt2_addoutput)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
165 : : {
166 : 1 : CMutableTransaction mtx;
167 [ + - ]: 1 : PartiallySignedTransaction psbt(mtx, /*version=*/2);
168 [ - + ]: 1 : psbt.m_tx_modifiable.emplace();
169 [ + - ]: 1 : psbt.m_tx_modifiable->set(1, true);
170 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.outputs.size(), 0);
+ - ]
171 : :
172 : : // Same PSBT version is required
173 : 1 : PSBTOutput psbtout_v0(/*psbt_version=*/0, /*amount=*/1, CScript());
174 [ + - + - : 2 : BOOST_CHECK(!psbt.AddOutput(psbtout_v0));
+ - + - ]
175 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.outputs.size(), 0);
+ - ]
176 : 1 : PSBTOutput psbtout(/*psbt_version=*/2, /*amount=*/1, CScript());
177 [ + - + - : 2 : BOOST_CHECK(psbt.AddOutput(psbtout));
+ - + - ]
178 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.outputs.size(), 1);
+ - ]
179 : :
180 : : // Disabling outputs modifiable flag prevents adding new outputs
181 : 1 : psbt.m_tx_modifiable->set(1, false);
182 : 1 : PSBTOutput psbtout2(/*psbt_version=*/2, /*amount=*/1, CScript());
183 [ + - + - : 2 : BOOST_CHECK(!psbt.AddOutput(psbtout2));
+ - + - ]
184 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.outputs.size(), 1);
+ - ]
185 : 1 : psbt.m_tx_modifiable->set(1, true);
186 : 1 : PSBTOutput psbtout3(/*psbt_version=*/2, /*amount=*/1, CScript());
187 [ + - + - : 2 : BOOST_CHECK(psbt.AddOutput(psbtout3));
+ - + - ]
188 [ + - - + : 1 : BOOST_CHECK_EQUAL(psbt.outputs.size(), 2);
+ - ]
189 : 2 : }
190 : :
191 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(merge_proprietary_fields)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
192 : : {
193 : 1 : CMutableTransaction tx;
194 [ + - ]: 1 : tx.vin.emplace_back(COutPoint{});
195 [ + - ]: 1 : tx.vout.emplace_back(0, CScript{});
196 : :
197 [ + - ]: 1 : PartiallySignedTransaction left(tx);
198 [ + - ]: 1 : PartiallySignedTransaction right(tx);
199 : :
200 [ + - ]: 1 : const auto left_prop = MakeProprietary(/*subtype=*/1, /*key_data=*/0x01, /*value=*/0xaa);
201 [ + - ]: 1 : const auto right_prop = MakeProprietary(/*subtype=*/2, /*key_data=*/0x02, /*value=*/0xbb);
202 : :
203 [ + - ]: 1 : left.m_proprietary.insert(left_prop);
204 [ + - ]: 1 : left.inputs[0].m_proprietary.insert(left_prop);
205 [ + - ]: 1 : left.outputs[0].m_proprietary.insert(left_prop);
206 : :
207 [ + - ]: 1 : right.m_proprietary.insert(right_prop);
208 [ + - ]: 1 : right.inputs[0].m_proprietary.insert(right_prop);
209 [ + - ]: 1 : right.outputs[0].m_proprietary.insert(right_prop);
210 : :
211 [ + - + - : 2 : BOOST_REQUIRE(left.Merge(right));
+ - + - ]
212 : :
213 [ + - + - ]: 1 : BOOST_REQUIRE_EQUAL(left.m_proprietary.size(), 2U);
214 [ + - + - ]: 1 : BOOST_REQUIRE_EQUAL(left.inputs[0].m_proprietary.size(), 2U);
215 [ + - + - ]: 1 : BOOST_REQUIRE_EQUAL(left.outputs[0].m_proprietary.size(), 2U);
216 : :
217 : 1 : const auto global_it = left.m_proprietary.find(right_prop);
218 [ + - + - : 2 : BOOST_REQUIRE(global_it != left.m_proprietary.end());
+ - ]
219 [ + - + - ]: 2 : BOOST_CHECK(global_it->value == right_prop.value);
220 : :
221 : 1 : const auto input_it = left.inputs[0].m_proprietary.find(right_prop);
222 [ + - + - : 2 : BOOST_REQUIRE(input_it != left.inputs[0].m_proprietary.end());
+ - ]
223 [ + - + - ]: 2 : BOOST_CHECK(input_it->value == right_prop.value);
224 : :
225 : 1 : const auto output_it = left.outputs[0].m_proprietary.find(right_prop);
226 [ + - + - : 2 : BOOST_REQUIRE(output_it != left.outputs[0].m_proprietary.end());
+ - ]
227 [ + - + - ]: 2 : BOOST_CHECK(output_it->value == right_prop.value);
228 : 2 : }
229 : :
230 : 12 : struct PSBTOutputTest {
231 : : CPubKey pubkey;
232 : : FlatSigningProvider provider;
233 : : CScript script_pubkey;
234 : :
235 : 12 : explicit PSBTOutputTest(std::string descriptor)
236 : 12 : {
237 : 12 : CKey key{GenerateRandomKey()};
238 [ + - ]: 12 : pubkey = key.GetPubKey();
239 [ + - + - ]: 12 : provider.keys.emplace(pubkey.GetID(), key);
240 : :
241 [ + - + - : 24 : util::ReplaceAll(descriptor, "<KEY>", HexStr(pubkey));
+ - ]
242 [ - + ]: 12 : std::string error;
243 [ - + + - ]: 12 : auto descriptors{Parse(descriptor, provider, error, /*require_checksum=*/false)};
244 [ + - + - : 24 : BOOST_REQUIRE_MESSAGE(!descriptors.empty(), error);
+ - ]
245 : 12 : std::vector<CScript> output_scripts;
246 [ + - + - : 24 : BOOST_REQUIRE(descriptors[0]->Expand(/*pos=*/0, provider, output_scripts, provider));
+ - + - ]
247 [ + - - + : 12 : BOOST_REQUIRE_EQUAL(output_scripts.size(), 1);
+ - ]
248 : 12 : script_pubkey = output_scripts[0];
249 : 12 : }
250 : :
251 : 12 : PSBTOutput UpdateOutput(bool has_input) const
252 : : {
253 : 12 : CMutableTransaction tx;
254 [ + + + - ]: 12 : if (has_input) tx.vin.emplace_back();
255 [ + - ]: 12 : tx.vout.emplace_back(0, script_pubkey);
256 [ + - ]: 12 : PartiallySignedTransaction psbt{tx};
257 [ + - ]: 12 : UpdatePSBTOutput(provider, psbt, 0);
258 [ + - ]: 12 : return psbt.outputs[0];
259 : 24 : }
260 : : };
261 : :
262 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(update_psbt_output_keypaths)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
263 : : {
264 [ + + ]: 3 : for (bool has_input : {false, true}) {
265 [ + + ]: 6 : for (const auto& descriptor : {"pkh(<KEY>)", "wpkh(<KEY>)"}) {
266 [ + - ]: 4 : PSBTOutputTest test{descriptor};
267 [ + - ]: 4 : auto out{test.UpdateOutput(has_input)};
268 [ + - + - : 8 : BOOST_CHECK(out.hd_keypaths.contains(test.pubkey));
+ - ]
269 [ + - - + : 8 : BOOST_CHECK(out.redeem_script.empty());
+ - + - ]
270 [ + - - + : 8 : BOOST_CHECK(out.witness_script.empty());
+ - ]
271 : 8 : }
272 : : }
273 : 1 : }
274 : :
275 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(update_psbt_output_redeem_script)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
276 : : {
277 [ + + ]: 3 : for (bool has_input : {false, true}) {
278 [ + - ]: 2 : PSBTOutputTest test{"sh(wpkh(<KEY>))"};
279 [ + - ]: 2 : auto out{test.UpdateOutput(has_input)};
280 [ + - + - : 4 : BOOST_CHECK(out.redeem_script == GetScriptForDestination(WitnessV0KeyHash{test.pubkey}));
+ - + - +
- ]
281 [ + - + - ]: 4 : BOOST_CHECK(out.hd_keypaths.contains(test.pubkey));
282 : 4 : }
283 : 1 : }
284 : :
285 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(update_psbt_output_witness_script)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
286 : : {
287 [ + + ]: 3 : for (bool has_input : {false, true}) {
288 [ + - ]: 2 : PSBTOutputTest test{"wsh(pk(<KEY>))"};
289 [ + - ]: 2 : auto out{test.UpdateOutput(has_input)};
290 [ + - + - : 4 : BOOST_CHECK(out.witness_script == GetScriptForRawPubKey(test.pubkey));
+ - + - ]
291 [ + - + - ]: 4 : BOOST_CHECK(out.hd_keypaths.contains(test.pubkey));
292 : 4 : }
293 : 1 : }
294 : :
295 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(update_psbt_output_miniscript_timelock)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
296 : : {
297 [ + + ]: 3 : for (bool has_input : {false, true}) {
298 [ + - ]: 2 : PSBTOutputTest test{"wsh(and_v(v:pk(<KEY>),older(144)))"};
299 [ + - ]: 2 : auto out{test.UpdateOutput(has_input)};
300 [ + - + - : 4 : BOOST_CHECK(GetScriptForDestination(WitnessV0ScriptHash{out.witness_script}) == test.script_pubkey);
+ - + - +
- ]
301 [ + - + - ]: 4 : BOOST_CHECK(out.hd_keypaths.contains(test.pubkey));
302 : 4 : }
303 : 1 : }
304 : :
305 [ + - + - : 7 : BOOST_AUTO_TEST_CASE(update_psbt_output_taproot)
+ - + - -
+ + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- + - + -
+ - + - +
- + - - +
+ - + - +
- + - + -
+ - - + +
- ]
306 : : {
307 [ + + ]: 3 : for (bool has_input : {false, true}) {
308 [ + - ]: 2 : PSBTOutputTest test{"rawtr(<KEY>)"};
309 [ + - ]: 2 : auto out{test.UpdateOutput(has_input)};
310 [ + - + - : 4 : BOOST_CHECK(out.m_tap_bip32_paths.contains(XOnlyPubKey{test.pubkey}));
+ - ]
311 [ + - + - ]: 4 : BOOST_CHECK(out.hd_keypaths.empty());
312 : 4 : }
313 : 1 : }
314 : :
315 : : BOOST_AUTO_TEST_SUITE_END()
|