Branch data Line data Source code
# 1 : : // Copyright (c) 2020-2021 The Bitcoin Core developers
# 2 : : // Distributed under the MIT software license, see the accompanying
# 3 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
# 4 : :
# 5 : : #include <chainparams.h>
# 6 : : #include <external_signer.h>
# 7 : : #include <wallet/external_signer_scriptpubkeyman.h>
# 8 : :
# 9 : : #include <iostream>
# 10 : : #include <memory>
# 11 : : #include <stdexcept>
# 12 : : #include <string>
# 13 : : #include <utility>
# 14 : : #include <vector>
# 15 : :
# 16 : : namespace wallet {
# 17 : : bool ExternalSignerScriptPubKeyMan::SetupDescriptor(std::unique_ptr<Descriptor> desc)
# 18 : 6 : {
# 19 : 6 : LOCK(cs_desc_man);
# 20 : 6 : assert(m_storage.IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));
# 21 : 0 : assert(m_storage.IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER));
# 22 : :
# 23 : 0 : int64_t creation_time = GetTime();
# 24 : :
# 25 : : // Make the descriptor
# 26 : 6 : WalletDescriptor w_desc(std::move(desc), creation_time, 0, 0, 0);
# 27 : 6 : m_wallet_descriptor = w_desc;
# 28 : :
# 29 : : // Store the descriptor
# 30 : 6 : WalletBatch batch(m_storage.GetDatabase());
# 31 [ - + ]: 6 : if (!batch.WriteDescriptor(GetID(), m_wallet_descriptor)) {
# 32 : 0 : throw std::runtime_error(std::string(__func__) + ": writing descriptor failed");
# 33 : 0 : }
# 34 : :
# 35 : : // TopUp
# 36 : 6 : TopUp();
# 37 : :
# 38 : 6 : m_storage.UnsetBlankWalletFlag(batch);
# 39 : 6 : return true;
# 40 : 6 : }
# 41 : :
# 42 : 6 : ExternalSigner ExternalSignerScriptPubKeyMan::GetExternalSigner() {
# 43 : 6 : const std::string command = gArgs.GetArg("-signer", "");
# 44 [ - + ]: 6 : if (command == "") throw std::runtime_error(std::string(__func__) + ": restart bitcoind with -signer=<cmd>");
# 45 : 6 : std::vector<ExternalSigner> signers;
# 46 : 6 : ExternalSigner::Enumerate(command, signers, Params().NetworkIDString());
# 47 [ - + ]: 6 : if (signers.empty()) throw std::runtime_error(std::string(__func__) + ": No external signers found");
# 48 : : // TODO: add fingerprint argument in case of multiple signers
# 49 : 6 : return signers[0];
# 50 : 6 : }
# 51 : :
# 52 : : bool ExternalSignerScriptPubKeyMan::DisplayAddress(const CScript scriptPubKey, const ExternalSigner &signer) const
# 53 : 1 : {
# 54 : : // TODO: avoid the need to infer a descriptor from inside a descriptor wallet
# 55 : 1 : auto provider = GetSolvingProvider(scriptPubKey);
# 56 : 1 : auto descriptor = InferDescriptor(scriptPubKey, *provider);
# 57 : :
# 58 : 1 : signer.DisplayAddress(descriptor->ToString());
# 59 : : // TODO inspect result
# 60 : 1 : return true;
# 61 : 1 : }
# 62 : :
# 63 : : // If sign is true, transaction must previously have been filled
# 64 : : TransactionError ExternalSignerScriptPubKeyMan::FillPSBT(PartiallySignedTransaction& psbt, const PrecomputedTransactionData& txdata, int sighash_type, bool sign, bool bip32derivs, int* n_signed, bool finalize) const
# 65 : 24 : {
# 66 [ + + ]: 24 : if (!sign) {
# 67 : 12 : return DescriptorScriptPubKeyMan::FillPSBT(psbt, txdata, sighash_type, false, bip32derivs, n_signed, finalize);
# 68 : 12 : }
# 69 : :
# 70 : : // Already complete if every input is now signed
# 71 : 12 : bool complete = true;
# 72 [ + + ]: 12 : for (const auto& input : psbt.inputs) {
# 73 : : // TODO: for multisig wallets, we should only care if all _our_ inputs are signed
# 74 : 12 : complete &= PSBTInputSigned(input);
# 75 : 12 : }
# 76 [ + + ]: 12 : if (complete) return TransactionError::OK;
# 77 : :
# 78 : 2 : std::string strFailReason;
# 79 [ - + ]: 2 : if(!GetExternalSigner().SignTransaction(psbt, strFailReason)) {
# 80 : 0 : tfm::format(std::cerr, "Failed to sign: %s\n", strFailReason);
# 81 : 0 : return TransactionError::EXTERNAL_SIGNER_FAILED;
# 82 : 0 : }
# 83 [ + - ]: 2 : if (finalize) FinalizePSBT(psbt); // This won't work in a multisig setup
# 84 : 2 : return TransactionError::OK;
# 85 : 2 : }
# 86 : : } // namespace wallet
|