mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-09-11 21:20:39 +02:00
test: characterize PSBT output metadata
Document the scripts and key origins collected for common output descriptors before changing zero-input handling. Use a valid input for ECDSA-backed outputs because their zero-input paths currently abort.
This commit is contained in:
@@ -2,10 +2,21 @@
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or https://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <addresstype.h>
|
||||
#include <key.h>
|
||||
#include <psbt.h>
|
||||
#include <script/descriptor.h>
|
||||
#include <script/script.h>
|
||||
#include <script/signingprovider.h>
|
||||
#include <script/solver.h>
|
||||
#include <test/util/setup_common.h>
|
||||
#include <util/strencodings.h>
|
||||
#include <util/string.h>
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <test/util/setup_common.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(psbt_tests, BasicTestingSetup)
|
||||
|
||||
@@ -216,4 +227,79 @@ BOOST_AUTO_TEST_CASE(merge_proprietary_fields)
|
||||
BOOST_CHECK(output_it->value == right_prop.value);
|
||||
}
|
||||
|
||||
struct PSBTOutputTest {
|
||||
CPubKey pubkey;
|
||||
FlatSigningProvider provider;
|
||||
CScript script_pubkey;
|
||||
|
||||
explicit PSBTOutputTest(std::string descriptor)
|
||||
{
|
||||
CKey key{GenerateRandomKey()};
|
||||
pubkey = key.GetPubKey();
|
||||
provider.keys.emplace(pubkey.GetID(), key);
|
||||
|
||||
util::ReplaceAll(descriptor, "<KEY>", HexStr(pubkey));
|
||||
std::string error;
|
||||
auto descriptors{Parse(descriptor, provider, error, /*require_checksum=*/false)};
|
||||
BOOST_REQUIRE_MESSAGE(!descriptors.empty(), error);
|
||||
std::vector<CScript> output_scripts;
|
||||
BOOST_REQUIRE(descriptors[0]->Expand(/*pos=*/0, provider, output_scripts, provider));
|
||||
BOOST_REQUIRE_EQUAL(output_scripts.size(), 1);
|
||||
script_pubkey = output_scripts[0];
|
||||
}
|
||||
|
||||
PSBTOutput UpdateOutput(bool has_input) const
|
||||
{
|
||||
CMutableTransaction tx;
|
||||
if (has_input) tx.vin.emplace_back();
|
||||
tx.vout.emplace_back(0, script_pubkey);
|
||||
PartiallySignedTransaction psbt{tx};
|
||||
UpdatePSBTOutput(provider, psbt, 0);
|
||||
return psbt.outputs[0];
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_AUTO_TEST_CASE(update_psbt_output_keypaths)
|
||||
{
|
||||
for (bool has_input : {true}) { // TODO: Zero-input updates abort during ECDSA sighash creation.
|
||||
for (const auto& descriptor : {"pkh(<KEY>)", "wpkh(<KEY>)"}) {
|
||||
PSBTOutputTest test{descriptor};
|
||||
auto out{test.UpdateOutput(has_input)};
|
||||
BOOST_CHECK(out.hd_keypaths.contains(test.pubkey));
|
||||
BOOST_CHECK(out.redeem_script.empty());
|
||||
BOOST_CHECK(out.witness_script.empty());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(update_psbt_output_redeem_script)
|
||||
{
|
||||
for (bool has_input : {true}) { // TODO: Zero-input updates abort during ECDSA sighash creation.
|
||||
PSBTOutputTest test{"sh(wpkh(<KEY>))"};
|
||||
auto out{test.UpdateOutput(has_input)};
|
||||
BOOST_CHECK(out.redeem_script == GetScriptForDestination(WitnessV0KeyHash{test.pubkey}));
|
||||
BOOST_CHECK(out.hd_keypaths.contains(test.pubkey));
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(update_psbt_output_witness_script)
|
||||
{
|
||||
for (bool has_input : {true}) { // TODO: Zero-input updates abort during ECDSA sighash creation.
|
||||
PSBTOutputTest test{"wsh(pk(<KEY>))"};
|
||||
auto out{test.UpdateOutput(has_input)};
|
||||
BOOST_CHECK(out.witness_script == GetScriptForRawPubKey(test.pubkey));
|
||||
BOOST_CHECK(out.hd_keypaths.contains(test.pubkey));
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(update_psbt_output_taproot)
|
||||
{
|
||||
for (bool has_input : {false, true}) {
|
||||
PSBTOutputTest test{"rawtr(<KEY>)"};
|
||||
auto out{test.UpdateOutput(has_input)};
|
||||
BOOST_CHECK(out.m_tap_bip32_paths.contains(XOnlyPubKey{test.pubkey}));
|
||||
BOOST_CHECK(out.hd_keypaths.empty());
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
@@ -1424,6 +1424,14 @@ class PSBTTest(BitcoinTestFramework):
|
||||
utxo = self.create_outpoints(self.nodes[0], outputs=[{address: 1}])[0]
|
||||
self.sync_all()
|
||||
|
||||
self.log.info("Test descriptorprocesspsbt updates PSBT outputs")
|
||||
for has_input in [True]: # TODO: Zero-input updates abort during ECDSA sighash creation.
|
||||
output_psbt = self.nodes[2].createpsbt([utxo] if has_input else [], {address: 1})
|
||||
processed = self.nodes[2].descriptorprocesspsbt(psbt=output_psbt, descriptors=[descriptor], finalize=False)
|
||||
decoded = self.nodes[2].decodepsbt(processed["psbt"])
|
||||
assert_equal(len(decoded["inputs"]), int(has_input))
|
||||
assert_equal(len(decoded["outputs"][0]["bip32_derivs"]), 1)
|
||||
|
||||
psbt = self.nodes[2].createpsbt([utxo], {self.nodes[0].getnewaddress(): 0.99999})
|
||||
decoded = self.nodes[2].decodepsbt(psbt)
|
||||
test_psbt_input_keys(decoded['inputs'][0], [])
|
||||
|
||||
Reference in New Issue
Block a user