Bitcoin Core 31.99.0
P2P Digital Currency
psbt_tests.cpp
Go to the documentation of this file.
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>
9
11
12static PSBTProprietary MakeProprietary(uint64_t subtype, uint8_t key_data, uint8_t value)
13{
14 return PSBTProprietary{
15 .subtype = subtype,
16 .identifier = {'p', 's', 'b', 't'},
17 .key = {key_data},
18 .value = {value},
19 };
20}
21
22void CheckTimeLock(const std::string& base64_psbt, std::optional<uint32_t> timelock)
23{
25 BOOST_CHECK(psbt);
26
27 std::optional<uint32_t> computed_timelock = psbt->ComputeTimeLock();
28 std::optional<CMutableTransaction> tx = psbt->GetUnsignedTx();
29 if (timelock) {
30 BOOST_CHECK(computed_timelock);
31 BOOST_CHECK_EQUAL(*computed_timelock, *timelock);
32 BOOST_CHECK(tx);
33 BOOST_CHECK_EQUAL(tx->nLockTime, *timelock);
34 } else {
35 BOOST_CHECK(!computed_timelock);
36 BOOST_CHECK(!tx);
37 }
38}
39
40BOOST_AUTO_TEST_CASE(psbt2_timelock_test)
41{
42 CheckTimeLock("cHNidP8BAgQCAAAAAQQBAQEFAQIB+wQCAAAAAAEOIAsK2SFBnByHGXNdctxzn56p4GONH+TB7vD5lECEgV/IAQ8EAAAAAAABAwgACK8vAAAAAAEEFgAUxDD2TEdW2jENvRoIVXLvKZkmJywAAQMIi73rCwAAAAABBBYAFE3Rk6yWSlasG54cyoRU/i9HT4UTAA==", 0);
43 CheckTimeLock("cHNidP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEBAfsEAgAAAAABDiAPdY2/vU2nwWyKMwnDyB4RAPVh6mRttbAXUsSF4b3enwEPBAEAAAAAAQ4gOhs7PIN9ZInqejHY5sfdUDwAG+8+BpWOdXSAjWjKeKUBDwQAAAAAAAEDCE+TNXcAAAAAAQQWABQLE1LKzQPPaqG388jWOIZxs0peEQA=", 0);
44 CheckTimeLock("cHNidP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEBAfsEAgAAAAABDiAPdY2/vU2nwWyKMwnDyB4RAPVh6mRttbAXUsSF4b3enwEPBAEAAAABEgQQJwAAAAEOIDobOzyDfWSJ6nox2ObH3VA8ABvvPgaVjnV0gI1oynilAQ8EAAAAAAABAwhPkzV3AAAAAAEEFgAUCxNSys0Dz2qht/PI1jiGcbNKXhEA", 10000);
45 CheckTimeLock("cHNidP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEBAfsEAgAAAAABDiAPdY2/vU2nwWyKMwnDyB4RAPVh6mRttbAXUsSF4b3enwEPBAEAAAABEgQQJwAAAAEOIDobOzyDfWSJ6nox2ObH3VA8ABvvPgaVjnV0gI1oynilAQ8EAAAAAAESBCgjAAAAAQMIT5M1dwAAAAABBBYAFAsTUsrNA89qobfzyNY4hnGzSl4RAA==", 10000);
46 CheckTimeLock("cHNidP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEBAfsEAgAAAAABDiAPdY2/vU2nwWyKMwnDyB4RAPVh6mRttbAXUsSF4b3enwEPBAEAAAABEgQQJwAAAAEOIDobOzyDfWSJ6nox2ObH3VA8ABvvPgaVjnV0gI1oynilAQ8EAAAAAAERBIyNxGIBEgQoIwAAAAEDCE+TNXcAAAAAAQQWABQLE1LKzQPPaqG388jWOIZxs0peEQA=", 10000);
47 CheckTimeLock("cHNidP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEBAfsEAgAAAAABDiAPdY2/vU2nwWyKMwnDyB4RAPVh6mRttbAXUsSF4b3enwEPBAEAAAABEQSLjcRiARIEECcAAAABDiA6Gzs8g31kiep6Mdjmx91QPAAb7z4GlY51dICNaMp4pQEPBAAAAAABEQSMjcRiARIEKCMAAAABAwhPkzV3AAAAAAEEFgAUCxNSys0Dz2qht/PI1jiGcbNKXhEA", 10000);
48 CheckTimeLock("cHNidP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEBAfsEAgAAAAABDiAPdY2/vU2nwWyKMwnDyB4RAPVh6mRttbAXUsSF4b3enwEPBAEAAAABEQSLjcRiAAEOIDobOzyDfWSJ6nox2ObH3VA8ABvvPgaVjnV0gI1oynilAQ8EAAAAAAERBIyNxGIBEgQoIwAAAAEDCE+TNXcAAAAAAQQWABQLE1LKzQPPaqG388jWOIZxs0peEQA=", 1657048460);
49 CheckTimeLock("cHNidP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEBAfsEAgAAAAABDiAPdY2/vU2nwWyKMwnDyB4RAPVh6mRttbAXUsSF4b3enwEPBAEAAAABEQSLjcRiARIEECcAAAABDiA6Gzs8g31kiep6Mdjmx91QPAAb7z4GlY51dICNaMp4pQEPBAAAAAABEQSMjcRiAAEDCE+TNXcAAAAAAQQWABQLE1LKzQPPaqG388jWOIZxs0peEQA=", 1657048460);
50 CheckTimeLock("cHNidP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEBAfsEAgAAAAABDiAPdY2/vU2nwWyKMwnDyB4RAPVh6mRttbAXUsSF4b3enwEPBAEAAAAAAQ4gOhs7PIN9ZInqejHY5sfdUDwAG+8+BpWOdXSAjWjKeKUBDwQAAAAAAREEjI3EYgABAwhPkzV3AAAAAAEEFgAUCxNSys0Dz2qht/PI1jiGcbNKXhEA", 1657048460);
51 CheckTimeLock("cHNidP8BAgQCAAAAAQMEAAAAAAEEAQIBBQEBAfsEAgAAAAABDiAPdY2/vU2nwWyKMwnDyB4RAPVh6mRttbAXUsSF4b3enwEPBAEAAAABEgQQJwAAAAEOIDobOzyDfWSJ6nox2ObH3VA8ABvvPgaVjnV0gI1oynilAQ8EAAAAAAERBIyNxGIAAQMIT5M1dwAAAAABBBYAFAsTUsrNA89qobfzyNY4hnGzSl4RAA==", std::nullopt);
52}
53
54BOOST_AUTO_TEST_CASE(psbt2_addinput)
55{
56 FastRandomContext rng(/*fDeterministic=*/true);
57
59 PartiallySignedTransaction psbt(mtx, /*version=*/2);
60 psbt.m_tx_modifiable.emplace();
61 psbt.m_tx_modifiable->set(0, true);
62 BOOST_CHECK_EQUAL(psbt.inputs.size(), 0);
63
64 // Same PSBT version is required
65 uint256 txid;
67 PSBTInput psbtin_v0(/*psbt_version=*/0, Txid::FromUint256(txid), /*prev_out=*/0);
68 BOOST_CHECK(!psbt.AddInput(psbtin_v0));
69 BOOST_CHECK_EQUAL(psbt.inputs.size(), 0);
71 PSBTInput psbtin(/*psbt_version=*/2, Txid::FromUint256(txid), /*prev_out=*/0);
72 BOOST_CHECK(psbt.AddInput(psbtin));
73 BOOST_CHECK_EQUAL(psbt.inputs.size(), 1);
74
75 // Duplicates are not allowed
76 BOOST_CHECK(!psbt.AddInput(psbtin));
77 BOOST_CHECK_EQUAL(psbt.inputs.size(), 1);
78
79 // Input with a unique txid is allowed
81 PSBTInput psbtin2(/*psbt_version=*/2, Txid::FromUint256(txid), /*prev_out=*/0);
82 BOOST_CHECK(psbt.AddInput(psbtin2));
83 BOOST_CHECK_EQUAL(psbt.inputs.size(), 2);
84
85 // Disabling inputs modifiable flag prevents adding new inputs
86 psbt.m_tx_modifiable->set(0, false);
88 PSBTInput psbtin3(/*psbt_version=*/2, Txid::FromUint256(txid), /*prev_out=*/0);
89 BOOST_CHECK(!psbt.AddInput(psbtin3));
90 BOOST_CHECK_EQUAL(psbt.inputs.size(), 2);
91 psbt.m_tx_modifiable->set(0, true);
92
93 // Make sure that timelock compatibility checks are working
94 // No previous required timelocks, new input with both height and time timelocks is allowed
96 PSBTInput psbtin4(/*psbt_version=*/2, Txid::FromUint256(txid), /*prev_out=*/0);
98 psbtin4.height_locktime = 100;
99 BOOST_CHECK(psbt.AddInput(psbtin4));
100 BOOST_CHECK_EQUAL(psbt.inputs.size(), 3);
101
102 // Input with only a time timelock is allowed
104 PSBTInput psbtin5(/*psbt_version=*/2, Txid::FromUint256(txid), /*prev_out=*/0);
105 psbtin5.time_locktime = LOCKTIME_THRESHOLD + 1;
106 BOOST_CHECK(psbt.AddInput(psbtin5));
107 BOOST_CHECK_EQUAL(psbt.inputs.size(), 4);
108
109 // Input with only a height timelock is not allowed because of previous
111 PSBTInput psbtin6(/*psbt_version=*/2, Txid::FromUint256(txid), /*prev_out=*/0);
112 psbtin6.height_locktime = 100;
113 BOOST_CHECK(!psbt.AddInput(psbtin6));
114 BOOST_CHECK_EQUAL(psbt.inputs.size(), 4);
115
116 // Adding an input that already has a signature is allowed
118 PSBTInput psbtin7(/*psbt_version=*/2, Txid::FromUint256(txid), /*prev_out=*/0);
119 psbtin7.final_script_sig << OP_1;
120 BOOST_CHECK(psbt.AddInput(psbtin7));
121 BOOST_CHECK_EQUAL(psbt.inputs.size(), 5);
122
123 // Same thing, but with other things that have signatures
124 psbtin7.final_script_sig.clear();
125 psbtin7.final_script_witness.stack.emplace_back();
126 BOOST_CHECK(!psbt.AddInput(psbtin7));
127 BOOST_CHECK_EQUAL(psbt.inputs.size(), 5);
129 psbtin7.partial_sigs.emplace();
130 BOOST_CHECK(!psbt.AddInput(psbtin7));
131 BOOST_CHECK_EQUAL(psbt.inputs.size(), 5);
132 psbtin7.partial_sigs.clear();
133 psbtin7.m_tap_key_sig.push_back(0);
134 BOOST_CHECK(!psbt.AddInput(psbtin7));
135 BOOST_CHECK_EQUAL(psbt.inputs.size(), 5);
136 psbtin7.m_tap_key_sig.clear();
137 psbtin7.m_tap_script_sigs.emplace();
138 BOOST_CHECK(!psbt.AddInput(psbtin7));
139 BOOST_CHECK_EQUAL(psbt.inputs.size(), 5);
140 psbtin7.m_tap_script_sigs.clear();
141 psbtin7.m_musig2_partial_sigs.emplace();
142 BOOST_CHECK(!psbt.AddInput(psbtin7));
143 BOOST_CHECK_EQUAL(psbt.inputs.size(), 5);
144
145 // Adding an input that changes the timelock is no longer allowed
147 PSBTInput psbtin8(/*psbt_version=*/2, Txid::FromUint256(txid), /*prev_out=*/0);
148 psbtin8.time_locktime = LOCKTIME_THRESHOLD + 2;
149 BOOST_CHECK(!psbt.AddInput(psbtin8));
150 BOOST_CHECK_EQUAL(psbt.inputs.size(), 5);
151}
152
153BOOST_AUTO_TEST_CASE(psbt2_addoutput)
154{
156 PartiallySignedTransaction psbt(mtx, /*version=*/2);
157 psbt.m_tx_modifiable.emplace();
158 psbt.m_tx_modifiable->set(1, true);
159 BOOST_CHECK_EQUAL(psbt.outputs.size(), 0);
160
161 // Same PSBT version is required
162 PSBTOutput psbtout_v0(/*psbt_version=*/0, /*amount=*/1, CScript());
163 BOOST_CHECK(!psbt.AddOutput(psbtout_v0));
164 BOOST_CHECK_EQUAL(psbt.outputs.size(), 0);
165 PSBTOutput psbtout(/*psbt_version=*/2, /*amount=*/1, CScript());
166 BOOST_CHECK(psbt.AddOutput(psbtout));
167 BOOST_CHECK_EQUAL(psbt.outputs.size(), 1);
168
169 // Disabling outputs modifiable flag prevents adding new outputs
170 psbt.m_tx_modifiable->set(1, false);
171 PSBTOutput psbtout2(/*psbt_version=*/2, /*amount=*/1, CScript());
172 BOOST_CHECK(!psbt.AddOutput(psbtout2));
173 BOOST_CHECK_EQUAL(psbt.outputs.size(), 1);
174 psbt.m_tx_modifiable->set(1, true);
175 PSBTOutput psbtout3(/*psbt_version=*/2, /*amount=*/1, CScript());
176 BOOST_CHECK(psbt.AddOutput(psbtout3));
177 BOOST_CHECK_EQUAL(psbt.outputs.size(), 2);
178}
179
180BOOST_AUTO_TEST_CASE(merge_proprietary_fields)
181{
183 tx.vin.emplace_back(COutPoint{});
184 tx.vout.emplace_back(0, CScript{});
185
188
189 const auto left_prop = MakeProprietary(/*subtype=*/1, /*key_data=*/0x01, /*value=*/0xaa);
190 const auto right_prop = MakeProprietary(/*subtype=*/2, /*key_data=*/0x02, /*value=*/0xbb);
191
192 left.m_proprietary.insert(left_prop);
193 left.inputs[0].m_proprietary.insert(left_prop);
194 left.outputs[0].m_proprietary.insert(left_prop);
195
196 right.m_proprietary.insert(right_prop);
197 right.inputs[0].m_proprietary.insert(right_prop);
198 right.outputs[0].m_proprietary.insert(right_prop);
199
200 BOOST_REQUIRE(left.Merge(right));
201
202 BOOST_REQUIRE_EQUAL(left.m_proprietary.size(), 2U);
203 BOOST_REQUIRE_EQUAL(left.inputs[0].m_proprietary.size(), 2U);
204 BOOST_REQUIRE_EQUAL(left.outputs[0].m_proprietary.size(), 2U);
205
206 const auto global_it = left.m_proprietary.find(right_prop);
207 BOOST_REQUIRE(global_it != left.m_proprietary.end());
208 BOOST_CHECK(global_it->value == right_prop.value);
209
210 const auto input_it = left.inputs[0].m_proprietary.find(right_prop);
211 BOOST_REQUIRE(input_it != left.inputs[0].m_proprietary.end());
212 BOOST_CHECK(input_it->value == right_prop.value);
213
214 const auto output_it = left.outputs[0].m_proprietary.find(right_prop);
215 BOOST_REQUIRE(output_it != left.outputs[0].m_proprietary.end());
216 BOOST_CHECK(output_it->value == right_prop.value);
217}
218
An outpoint - a combination of a transaction hash and an index n into its vout.
Definition: transaction.h:29
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:406
void clear()
Definition: script.h:569
Fast randomness source.
Definition: random.h:386
void fillrand(std::span< std::byte > output) noexcept
Fill a byte span with random bytes.
Definition: random.cpp:626
A structure for PSBTs which contain per-input information.
Definition: psbt.h:281
std::vector< unsigned char > m_tap_key_sig
Definition: psbt.h:306
CScriptWitness final_script_witness
Definition: psbt.h:291
std::map< CKeyID, SigPair > partial_sigs
Definition: psbt.h:293
std::map< std::pair< XOnlyPubKey, uint256 >, std::vector< unsigned char > > m_tap_script_sigs
Definition: psbt.h:307
std::optional< uint32_t > time_locktime
Definition: psbt.h:302
std::map< std::pair< CPubKey, uint256 >, std::map< CPubKey, uint256 > > m_musig2_partial_sigs
Definition: psbt.h:318
CScript final_script_sig
Definition: psbt.h:290
std::optional< uint32_t > height_locktime
Definition: psbt.h:303
A structure for PSBTs which contains per output information.
Definition: psbt.h:939
A version of CTransaction with the PSBT format.
Definition: psbt.h:1240
std::optional< std::bitset< 8 > > m_tx_modifiable
Definition: psbt.h:1248
bool Merge(const PartiallySignedTransaction &psbt)
Merge psbt into this.
Definition: psbt.cpp:39
std::vector< PSBTInput > inputs
Definition: psbt.h:1249
std::vector< PSBTOutput > outputs
Definition: psbt.h:1250
std::set< PSBTProprietary > m_proprietary
Definition: psbt.h:1252
bool AddOutput(const PSBTOutput &psbtout)
Definition: psbt.cpp:246
bool AddInput(const PSBTInput &psbtin)
Definition: psbt.cpp:163
static transaction_identifier FromUint256(const uint256 &id)
256-bit opaque blob.
Definition: uint256.h:196
BOOST_FIXTURE_TEST_SUITE(cuckoocache_tests, BasicTestingSetup)
Test Suite for CuckooCache.
BOOST_AUTO_TEST_SUITE_END()
#define BOOST_CHECK_EQUAL(v1, v2)
Definition: object.cpp:17
#define BOOST_CHECK(expr)
Definition: object.cpp:16
util::Result< PartiallySignedTransaction > DecodeBase64PSBT(const std::string &base64_tx)
Decode a base64ed PSBT into a PartiallySignedTransaction.
Definition: psbt.cpp:864
BOOST_AUTO_TEST_CASE(psbt2_timelock_test)
Definition: psbt_tests.cpp:40
static PSBTProprietary MakeProprietary(uint64_t subtype, uint8_t key_data, uint8_t value)
Definition: psbt_tests.cpp:12
void CheckTimeLock(const std::string &base64_psbt, std::optional< uint32_t > timelock)
Definition: psbt_tests.cpp:22
static const unsigned int LOCKTIME_THRESHOLD
Definition: script.h:48
@ OP_1
Definition: script.h:84
auto MakeWritableByteSpan(V &&v) noexcept
Definition: span.h:89
Basic testing setup.
Definition: setup_common.h:56
A mutable version of CTransaction.
Definition: transaction.h:358
std::vector< CTxOut > vout
Definition: transaction.h:360
std::vector< CTxIn > vin
Definition: transaction.h:359
std::vector< std::vector< unsigned char > > stack
Definition: script.h:581
void SetNull()
Definition: script.h:588
A structure for PSBT proprietary types.
Definition: psbt.h:100
uint64_t subtype
Definition: psbt.h:101