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