mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-15 22:32:37 -03:00
5c2e2afe99
458a345b05
Add support for SIGHASH_DEFAULT in RPCs, and make it default (Pieter Wuille)c0f0c8eccb
tests: check spending of P2TR (Pieter Wuille)a2380127e9
Basic Taproot signing logic in script/sign.cpp (Pieter Wuille)49487bc3b6
Make GetInputUTXO safer: verify non-witness UTXO match (Pieter Wuille)fd3f6890f3
Construct and use PrecomputedTransactionData in PSBT signing (Pieter Wuille)5cb6502ac5
Construct and use PrecomputedTransactionData in SignTransaction (Pieter Wuille)5d2e22437b
Don't nuke witness data when signing fails (Pieter Wuille)ce9353164b
Permit full precomputation in PrecomputedTransactionData (Pieter Wuille)e841fb503d
Add precomputed txdata support to MutableTransactionSignatureCreator (Pieter Wuille)a91d532338
Add CKey::SignSchnorr function for BIP 340/341 signing (Pieter Wuille)e77a2839b5
Use HandleMissingData also in CheckSchnorrSignature (Pieter Wuille)dbb0ce9fbf
Add TaprootSpendData data structure, equivalent to script map for P2[W]SH (Pieter Wuille) Pull request description: Builds on top of #22051, adding signing support after derivation support. Nothing is changed in descriptor features. Signing works for key path and script path spending, through the normal sending functions, and PSBT-based RPCs. However, PSBT usability is rather low as no extensions have been defined to convey Taproot-specific information, so all script information must be known to the signing wallet. ACKs for top commit: achow101: re-ACK458a345b05
fjahr: Code review ACK458a345b05
Sjors: ACK458a345b05
Tree-SHA512: 30ed212cf7754763a4a81624ebc084c51727b8322711ac0b390369213c1a891d367ed8b123882ac08c99595320c11ec57ee42304ff22a69afdc3d1a0d55cc711
84 lines
3.1 KiB
C++
84 lines
3.1 KiB
C++
// Copyright (c) 2020 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 <chainparams.h>
|
|
#include <external_signer.h>
|
|
#include <wallet/external_signer_scriptpubkeyman.h>
|
|
|
|
#include <iostream>
|
|
#include <memory>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
bool ExternalSignerScriptPubKeyMan::SetupDescriptor(std::unique_ptr<Descriptor> desc)
|
|
{
|
|
LOCK(cs_desc_man);
|
|
assert(m_storage.IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));
|
|
assert(m_storage.IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER));
|
|
|
|
int64_t creation_time = GetTime();
|
|
|
|
// Make the descriptor
|
|
WalletDescriptor w_desc(std::move(desc), creation_time, 0, 0, 0);
|
|
m_wallet_descriptor = w_desc;
|
|
|
|
// Store the descriptor
|
|
WalletBatch batch(m_storage.GetDatabase());
|
|
if (!batch.WriteDescriptor(GetID(), m_wallet_descriptor)) {
|
|
throw std::runtime_error(std::string(__func__) + ": writing descriptor failed");
|
|
}
|
|
|
|
// TopUp
|
|
TopUp();
|
|
|
|
m_storage.UnsetBlankWalletFlag(batch);
|
|
return true;
|
|
}
|
|
|
|
ExternalSigner ExternalSignerScriptPubKeyMan::GetExternalSigner() {
|
|
const std::string command = gArgs.GetArg("-signer", "");
|
|
if (command == "") throw std::runtime_error(std::string(__func__) + ": restart bitcoind with -signer=<cmd>");
|
|
std::vector<ExternalSigner> signers;
|
|
ExternalSigner::Enumerate(command, signers, Params().NetworkIDString());
|
|
if (signers.empty()) throw std::runtime_error(std::string(__func__) + ": No external signers found");
|
|
// TODO: add fingerprint argument in case of multiple signers
|
|
return signers[0];
|
|
}
|
|
|
|
bool ExternalSignerScriptPubKeyMan::DisplayAddress(const CScript scriptPubKey, const ExternalSigner &signer) const
|
|
{
|
|
// TODO: avoid the need to infer a descriptor from inside a descriptor wallet
|
|
auto provider = GetSolvingProvider(scriptPubKey);
|
|
auto descriptor = InferDescriptor(scriptPubKey, *provider);
|
|
|
|
signer.DisplayAddress(descriptor->ToString());
|
|
// TODO inspect result
|
|
return true;
|
|
}
|
|
|
|
// If sign is true, transaction must previously have been filled
|
|
TransactionError ExternalSignerScriptPubKeyMan::FillPSBT(PartiallySignedTransaction& psbt, const PrecomputedTransactionData& txdata, int sighash_type, bool sign, bool bip32derivs, int* n_signed) const
|
|
{
|
|
if (!sign) {
|
|
return DescriptorScriptPubKeyMan::FillPSBT(psbt, txdata, sighash_type, false, bip32derivs, n_signed);
|
|
}
|
|
|
|
// Already complete if every input is now signed
|
|
bool complete = true;
|
|
for (const auto& input : psbt.inputs) {
|
|
// TODO: for multisig wallets, we should only care if all _our_ inputs are signed
|
|
complete &= PSBTInputSigned(input);
|
|
}
|
|
if (complete) return TransactionError::OK;
|
|
|
|
std::string strFailReason;
|
|
if(!GetExternalSigner().SignTransaction(psbt, strFailReason)) {
|
|
tfm::format(std::cerr, "Failed to sign: %s\n", strFailReason);
|
|
return TransactionError::EXTERNAL_SIGNER_FAILED;
|
|
}
|
|
FinalizePSBT(psbt); // This won't work in a multisig setup
|
|
return TransactionError::OK;
|
|
}
|