0
0
Fork 0
mirror of https://github.com/bitcoin/bitcoin.git synced 2025-02-05 10:17:30 -05:00
bitcoin-bitcoin-core/src/wallet/external_signer_scriptpubkeyman.cpp
Sjors Provoost b54b2e7b1a
Move external signer out of wallet module
This commit moves the ExternalSigner class and RPC methods out of the wallet module.

The enumeratesigners RPC can be used without a wallet since #21417.
With additional modifications external signers could be used without a wallet in general, e.g. via signrawtransaction.

The signerdisplayaddress RPC is ranamed to walletdisplayaddress because it requires wallet context.
A future displayaddress RPC call without wallet context could take a descriptor argument.

This commit fixes a rpc_help.py failure when configured with --disable-wallet.
2021-04-08 17:56:00 +02:00

81 lines
3 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>
#ifdef ENABLE_EXTERNAL_SIGNER
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, int sighash_type, bool sign, bool bip32derivs, int* n_signed) const
{
if (!sign) {
return DescriptorScriptPubKeyMan::FillPSBT(psbt, 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;
}
#endif