bitcoin/src/psbt.cpp
Andrew Chow d810fde8ea
psbt: Change m_tap_tree to store just the tuples
Instead of having an entire TaprootBuilder which may or may not be
complete, and could potentially have future changes that interact oddly
with taproot tree tuples, have m_tap_tree be just the tuples.

When needed in other a TaprootBuilder for actual use, the tuples will be
added to a a TaprootBuilder that, in the future, can take in whatever
other data is needed as well.

Github-Pull: #25858
Rebased-From: 0577d423adda8e719d7611d03355680c8fbacab8
2022-10-13 23:45:06 +08:00

491 lines
18 KiB
C++

// Copyright (c) 2009-2021 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <psbt.h>
#include <util/check.h>
#include <util/strencodings.h>
PartiallySignedTransaction::PartiallySignedTransaction(const CMutableTransaction& tx) : tx(tx)
{
inputs.resize(tx.vin.size());
outputs.resize(tx.vout.size());
}
bool PartiallySignedTransaction::IsNull() const
{
return !tx && inputs.empty() && outputs.empty() && unknown.empty();
}
bool PartiallySignedTransaction::Merge(const PartiallySignedTransaction& psbt)
{
// Prohibited to merge two PSBTs over different transactions
if (tx->GetHash() != psbt.tx->GetHash()) {
return false;
}
for (unsigned int i = 0; i < inputs.size(); ++i) {
inputs[i].Merge(psbt.inputs[i]);
}
for (unsigned int i = 0; i < outputs.size(); ++i) {
outputs[i].Merge(psbt.outputs[i]);
}
for (auto& xpub_pair : psbt.m_xpubs) {
if (m_xpubs.count(xpub_pair.first) == 0) {
m_xpubs[xpub_pair.first] = xpub_pair.second;
} else {
m_xpubs[xpub_pair.first].insert(xpub_pair.second.begin(), xpub_pair.second.end());
}
}
unknown.insert(psbt.unknown.begin(), psbt.unknown.end());
return true;
}
bool PartiallySignedTransaction::AddInput(const CTxIn& txin, PSBTInput& psbtin)
{
if (std::find(tx->vin.begin(), tx->vin.end(), txin) != tx->vin.end()) {
return false;
}
tx->vin.push_back(txin);
psbtin.partial_sigs.clear();
psbtin.final_script_sig.clear();
psbtin.final_script_witness.SetNull();
inputs.push_back(psbtin);
return true;
}
bool PartiallySignedTransaction::AddOutput(const CTxOut& txout, const PSBTOutput& psbtout)
{
tx->vout.push_back(txout);
outputs.push_back(psbtout);
return true;
}
bool PartiallySignedTransaction::GetInputUTXO(CTxOut& utxo, int input_index) const
{
const PSBTInput& input = inputs[input_index];
uint32_t prevout_index = tx->vin[input_index].prevout.n;
if (input.non_witness_utxo) {
if (prevout_index >= input.non_witness_utxo->vout.size()) {
return false;
}
if (input.non_witness_utxo->GetHash() != tx->vin[input_index].prevout.hash) {
return false;
}
utxo = input.non_witness_utxo->vout[prevout_index];
} else if (!input.witness_utxo.IsNull()) {
utxo = input.witness_utxo;
} else {
return false;
}
return true;
}
bool PSBTInput::IsNull() const
{
return !non_witness_utxo && witness_utxo.IsNull() && partial_sigs.empty() && unknown.empty() && hd_keypaths.empty() && redeem_script.empty() && witness_script.empty();
}
void PSBTInput::FillSignatureData(SignatureData& sigdata) const
{
if (!final_script_sig.empty()) {
sigdata.scriptSig = final_script_sig;
sigdata.complete = true;
}
if (!final_script_witness.IsNull()) {
sigdata.scriptWitness = final_script_witness;
sigdata.complete = true;
}
if (sigdata.complete) {
return;
}
sigdata.signatures.insert(partial_sigs.begin(), partial_sigs.end());
if (!redeem_script.empty()) {
sigdata.redeem_script = redeem_script;
}
if (!witness_script.empty()) {
sigdata.witness_script = witness_script;
}
for (const auto& key_pair : hd_keypaths) {
sigdata.misc_pubkeys.emplace(key_pair.first.GetID(), key_pair);
}
if (!m_tap_key_sig.empty()) {
sigdata.taproot_key_path_sig = m_tap_key_sig;
}
for (const auto& [pubkey_leaf, sig] : m_tap_script_sigs) {
sigdata.taproot_script_sigs.emplace(pubkey_leaf, sig);
}
if (!m_tap_internal_key.IsNull()) {
sigdata.tr_spenddata.internal_key = m_tap_internal_key;
}
if (!m_tap_merkle_root.IsNull()) {
sigdata.tr_spenddata.merkle_root = m_tap_merkle_root;
}
for (const auto& [leaf_script, control_block] : m_tap_scripts) {
sigdata.tr_spenddata.scripts.emplace(leaf_script, control_block);
}
for (const auto& [pubkey, leaf_origin] : m_tap_bip32_paths) {
sigdata.taproot_misc_pubkeys.emplace(pubkey, leaf_origin);
}
}
void PSBTInput::FromSignatureData(const SignatureData& sigdata)
{
if (sigdata.complete) {
partial_sigs.clear();
hd_keypaths.clear();
redeem_script.clear();
witness_script.clear();
if (!sigdata.scriptSig.empty()) {
final_script_sig = sigdata.scriptSig;
}
if (!sigdata.scriptWitness.IsNull()) {
final_script_witness = sigdata.scriptWitness;
}
return;
}
partial_sigs.insert(sigdata.signatures.begin(), sigdata.signatures.end());
if (redeem_script.empty() && !sigdata.redeem_script.empty()) {
redeem_script = sigdata.redeem_script;
}
if (witness_script.empty() && !sigdata.witness_script.empty()) {
witness_script = sigdata.witness_script;
}
for (const auto& entry : sigdata.misc_pubkeys) {
hd_keypaths.emplace(entry.second);
}
if (!sigdata.taproot_key_path_sig.empty()) {
m_tap_key_sig = sigdata.taproot_key_path_sig;
}
for (const auto& [pubkey_leaf, sig] : sigdata.taproot_script_sigs) {
m_tap_script_sigs.emplace(pubkey_leaf, sig);
}
if (!sigdata.tr_spenddata.internal_key.IsNull()) {
m_tap_internal_key = sigdata.tr_spenddata.internal_key;
}
if (!sigdata.tr_spenddata.merkle_root.IsNull()) {
m_tap_merkle_root = sigdata.tr_spenddata.merkle_root;
}
for (const auto& [leaf_script, control_block] : sigdata.tr_spenddata.scripts) {
m_tap_scripts.emplace(leaf_script, control_block);
}
for (const auto& [pubkey, leaf_origin] : sigdata.taproot_misc_pubkeys) {
m_tap_bip32_paths.emplace(pubkey, leaf_origin);
}
}
void PSBTInput::Merge(const PSBTInput& input)
{
if (!non_witness_utxo && input.non_witness_utxo) non_witness_utxo = input.non_witness_utxo;
if (witness_utxo.IsNull() && !input.witness_utxo.IsNull()) {
witness_utxo = input.witness_utxo;
}
partial_sigs.insert(input.partial_sigs.begin(), input.partial_sigs.end());
ripemd160_preimages.insert(input.ripemd160_preimages.begin(), input.ripemd160_preimages.end());
sha256_preimages.insert(input.sha256_preimages.begin(), input.sha256_preimages.end());
hash160_preimages.insert(input.hash160_preimages.begin(), input.hash160_preimages.end());
hash256_preimages.insert(input.hash256_preimages.begin(), input.hash256_preimages.end());
hd_keypaths.insert(input.hd_keypaths.begin(), input.hd_keypaths.end());
unknown.insert(input.unknown.begin(), input.unknown.end());
m_tap_script_sigs.insert(input.m_tap_script_sigs.begin(), input.m_tap_script_sigs.end());
m_tap_scripts.insert(input.m_tap_scripts.begin(), input.m_tap_scripts.end());
m_tap_bip32_paths.insert(input.m_tap_bip32_paths.begin(), input.m_tap_bip32_paths.end());
if (redeem_script.empty() && !input.redeem_script.empty()) redeem_script = input.redeem_script;
if (witness_script.empty() && !input.witness_script.empty()) witness_script = input.witness_script;
if (final_script_sig.empty() && !input.final_script_sig.empty()) final_script_sig = input.final_script_sig;
if (final_script_witness.IsNull() && !input.final_script_witness.IsNull()) final_script_witness = input.final_script_witness;
if (m_tap_key_sig.empty() && !input.m_tap_key_sig.empty()) m_tap_key_sig = input.m_tap_key_sig;
if (m_tap_internal_key.IsNull() && !input.m_tap_internal_key.IsNull()) m_tap_internal_key = input.m_tap_internal_key;
if (m_tap_merkle_root.IsNull() && !input.m_tap_merkle_root.IsNull()) m_tap_merkle_root = input.m_tap_merkle_root;
}
void PSBTOutput::FillSignatureData(SignatureData& sigdata) const
{
if (!redeem_script.empty()) {
sigdata.redeem_script = redeem_script;
}
if (!witness_script.empty()) {
sigdata.witness_script = witness_script;
}
for (const auto& key_pair : hd_keypaths) {
sigdata.misc_pubkeys.emplace(key_pair.first.GetID(), key_pair);
}
if (!m_tap_tree.empty() && m_tap_internal_key.IsFullyValid()) {
TaprootBuilder builder;
for (const auto& [depth, leaf_ver, script] : m_tap_tree) {
builder.Add((int)depth, script, (int)leaf_ver, /*track=*/true);
}
assert(builder.IsComplete());
builder.Finalize(m_tap_internal_key);
TaprootSpendData spenddata = builder.GetSpendData();
sigdata.tr_spenddata.internal_key = m_tap_internal_key;
sigdata.tr_spenddata.Merge(spenddata);
}
for (const auto& [pubkey, leaf_origin] : m_tap_bip32_paths) {
sigdata.taproot_misc_pubkeys.emplace(pubkey, leaf_origin);
}
}
void PSBTOutput::FromSignatureData(const SignatureData& sigdata)
{
if (redeem_script.empty() && !sigdata.redeem_script.empty()) {
redeem_script = sigdata.redeem_script;
}
if (witness_script.empty() && !sigdata.witness_script.empty()) {
witness_script = sigdata.witness_script;
}
for (const auto& entry : sigdata.misc_pubkeys) {
hd_keypaths.emplace(entry.second);
}
if (!sigdata.tr_spenddata.internal_key.IsNull()) {
m_tap_internal_key = sigdata.tr_spenddata.internal_key;
}
if (sigdata.tr_builder.has_value()) {
m_tap_tree = sigdata.tr_builder->GetTreeTuples();
}
for (const auto& [pubkey, leaf_origin] : sigdata.taproot_misc_pubkeys) {
m_tap_bip32_paths.emplace(pubkey, leaf_origin);
}
}
bool PSBTOutput::IsNull() const
{
return redeem_script.empty() && witness_script.empty() && hd_keypaths.empty() && unknown.empty();
}
void PSBTOutput::Merge(const PSBTOutput& output)
{
hd_keypaths.insert(output.hd_keypaths.begin(), output.hd_keypaths.end());
unknown.insert(output.unknown.begin(), output.unknown.end());
m_tap_bip32_paths.insert(output.m_tap_bip32_paths.begin(), output.m_tap_bip32_paths.end());
if (redeem_script.empty() && !output.redeem_script.empty()) redeem_script = output.redeem_script;
if (witness_script.empty() && !output.witness_script.empty()) witness_script = output.witness_script;
if (m_tap_internal_key.IsNull() && !output.m_tap_internal_key.IsNull()) m_tap_internal_key = output.m_tap_internal_key;
if (m_tap_tree.empty() && !output.m_tap_tree.empty()) m_tap_tree = output.m_tap_tree;
}
bool PSBTInputSigned(const PSBTInput& input)
{
return !input.final_script_sig.empty() || !input.final_script_witness.IsNull();
}
size_t CountPSBTUnsignedInputs(const PartiallySignedTransaction& psbt) {
size_t count = 0;
for (const auto& input : psbt.inputs) {
if (!PSBTInputSigned(input)) {
count++;
}
}
return count;
}
void UpdatePSBTOutput(const SigningProvider& provider, PartiallySignedTransaction& psbt, int index)
{
CMutableTransaction& tx = *Assert(psbt.tx);
const CTxOut& out = tx.vout.at(index);
PSBTOutput& psbt_out = psbt.outputs.at(index);
// Fill a SignatureData with output info
SignatureData sigdata;
psbt_out.FillSignatureData(sigdata);
// Construct a would-be spend of this output, to update sigdata with.
// Note that ProduceSignature is used to fill in metadata (not actual signatures),
// so provider does not need to provide any private keys (it can be a HidingSigningProvider).
MutableTransactionSignatureCreator creator(tx, /*input_idx=*/0, out.nValue, SIGHASH_ALL);
ProduceSignature(provider, creator, out.scriptPubKey, sigdata);
// Put redeem_script, witness_script, key paths, into PSBTOutput.
psbt_out.FromSignatureData(sigdata);
}
PrecomputedTransactionData PrecomputePSBTData(const PartiallySignedTransaction& psbt)
{
const CMutableTransaction& tx = *psbt.tx;
bool have_all_spent_outputs = true;
std::vector<CTxOut> utxos(tx.vin.size());
for (size_t idx = 0; idx < tx.vin.size(); ++idx) {
if (!psbt.GetInputUTXO(utxos[idx], idx)) have_all_spent_outputs = false;
}
PrecomputedTransactionData txdata;
if (have_all_spent_outputs) {
txdata.Init(tx, std::move(utxos), true);
} else {
txdata.Init(tx, {}, true);
}
return txdata;
}
bool SignPSBTInput(const SigningProvider& provider, PartiallySignedTransaction& psbt, int index, const PrecomputedTransactionData* txdata, int sighash, SignatureData* out_sigdata, bool finalize)
{
PSBTInput& input = psbt.inputs.at(index);
const CMutableTransaction& tx = *psbt.tx;
if (PSBTInputSigned(input)) {
return true;
}
// Fill SignatureData with input info
SignatureData sigdata;
input.FillSignatureData(sigdata);
// Get UTXO
bool require_witness_sig = false;
CTxOut utxo;
if (input.non_witness_utxo) {
// If we're taking our information from a non-witness UTXO, verify that it matches the prevout.
COutPoint prevout = tx.vin[index].prevout;
if (prevout.n >= input.non_witness_utxo->vout.size()) {
return false;
}
if (input.non_witness_utxo->GetHash() != prevout.hash) {
return false;
}
utxo = input.non_witness_utxo->vout[prevout.n];
} else if (!input.witness_utxo.IsNull()) {
utxo = input.witness_utxo;
// When we're taking our information from a witness UTXO, we can't verify it is actually data from
// the output being spent. This is safe in case a witness signature is produced (which includes this
// information directly in the hash), but not for non-witness signatures. Remember that we require
// a witness signature in this situation.
require_witness_sig = true;
} else {
return false;
}
sigdata.witness = false;
bool sig_complete;
if (txdata == nullptr) {
sig_complete = ProduceSignature(provider, DUMMY_SIGNATURE_CREATOR, utxo.scriptPubKey, sigdata);
} else {
MutableTransactionSignatureCreator creator(tx, index, utxo.nValue, txdata, sighash);
sig_complete = ProduceSignature(provider, creator, utxo.scriptPubKey, sigdata);
}
// Verify that a witness signature was produced in case one was required.
if (require_witness_sig && !sigdata.witness) return false;
// If we are not finalizing, set sigdata.complete to false to not set the scriptWitness
if (!finalize && sigdata.complete) sigdata.complete = false;
input.FromSignatureData(sigdata);
// If we have a witness signature, put a witness UTXO.
if (sigdata.witness) {
input.witness_utxo = utxo;
// We can remove the non_witness_utxo if and only if there are no non-segwit or segwit v0
// inputs in this transaction. Since this requires inspecting the entire transaction, this
// is something for the caller to deal with (i.e. FillPSBT).
}
// Fill in the missing info
if (out_sigdata) {
out_sigdata->missing_pubkeys = sigdata.missing_pubkeys;
out_sigdata->missing_sigs = sigdata.missing_sigs;
out_sigdata->missing_redeem_script = sigdata.missing_redeem_script;
out_sigdata->missing_witness_script = sigdata.missing_witness_script;
}
return sig_complete;
}
bool FinalizePSBT(PartiallySignedTransaction& psbtx)
{
// Finalize input signatures -- in case we have partial signatures that add up to a complete
// signature, but have not combined them yet (e.g. because the combiner that created this
// PartiallySignedTransaction did not understand them), this will combine them into a final
// script.
bool complete = true;
const PrecomputedTransactionData txdata = PrecomputePSBTData(psbtx);
for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
complete &= SignPSBTInput(DUMMY_SIGNING_PROVIDER, psbtx, i, &txdata, SIGHASH_ALL, nullptr, true);
}
return complete;
}
bool FinalizeAndExtractPSBT(PartiallySignedTransaction& psbtx, CMutableTransaction& result)
{
// It's not safe to extract a PSBT that isn't finalized, and there's no easy way to check
// whether a PSBT is finalized without finalizing it, so we just do this.
if (!FinalizePSBT(psbtx)) {
return false;
}
result = *psbtx.tx;
for (unsigned int i = 0; i < result.vin.size(); ++i) {
result.vin[i].scriptSig = psbtx.inputs[i].final_script_sig;
result.vin[i].scriptWitness = psbtx.inputs[i].final_script_witness;
}
return true;
}
TransactionError CombinePSBTs(PartiallySignedTransaction& out, const std::vector<PartiallySignedTransaction>& psbtxs)
{
out = psbtxs[0]; // Copy the first one
// Merge
for (auto it = std::next(psbtxs.begin()); it != psbtxs.end(); ++it) {
if (!out.Merge(*it)) {
return TransactionError::PSBT_MISMATCH;
}
}
return TransactionError::OK;
}
std::string PSBTRoleName(PSBTRole role) {
switch (role) {
case PSBTRole::CREATOR: return "creator";
case PSBTRole::UPDATER: return "updater";
case PSBTRole::SIGNER: return "signer";
case PSBTRole::FINALIZER: return "finalizer";
case PSBTRole::EXTRACTOR: return "extractor";
// no default case, so the compiler can warn about missing cases
}
assert(false);
}
bool DecodeBase64PSBT(PartiallySignedTransaction& psbt, const std::string& base64_tx, std::string& error)
{
auto tx_data = DecodeBase64(base64_tx);
if (!tx_data) {
error = "invalid base64";
return false;
}
return DecodeRawPSBT(psbt, MakeByteSpan(*tx_data), error);
}
bool DecodeRawPSBT(PartiallySignedTransaction& psbt, Span<const std::byte> tx_data, std::string& error)
{
CDataStream ss_data(tx_data, SER_NETWORK, PROTOCOL_VERSION);
try {
ss_data >> psbt;
if (!ss_data.empty()) {
error = "extra data after PSBT";
return false;
}
} catch (const std::exception& e) {
error = e.what();
return false;
}
return true;
}
uint32_t PartiallySignedTransaction::GetVersion() const
{
if (m_version != std::nullopt) {
return *m_version;
}
return 0;
}