LCOV - code coverage report
Current view: top level - src/wallet - external_signer_scriptpubkeyman.cpp (source / functions) Coverage Total Hit
Test: test_bitcoin_coverage.info Lines: 0.0 % 56 0
Test Date: 2026-05-29 07:15:13 Functions: 0.0 % 5 0
Branches: 0.0 % 118 0

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) 2020-present 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 <common/args.h>
       7                 :             : #include <common/system.h>
       8                 :             : #include <external_signer.h>
       9                 :             : #include <node/types.h>
      10                 :             : #include <wallet/external_signer_scriptpubkeyman.h>
      11                 :             : 
      12                 :             : #include <iostream>
      13                 :             : #include <key_io.h>
      14                 :             : #include <memory>
      15                 :             : #include <stdexcept>
      16                 :             : #include <string>
      17                 :             : #include <univalue.h>
      18                 :             : #include <utility>
      19                 :             : #include <vector>
      20                 :             : 
      21                 :             : using common::PSBTError;
      22                 :             : 
      23                 :             : namespace wallet {
      24                 :           0 : std::unique_ptr<ExternalSignerScriptPubKeyMan> ExternalSignerScriptPubKeyMan::LoadFromStorage(WalletStorage& storage, WalletDescriptor& descriptor, int64_t keypool_size, const KeyMap& keys, const CryptedKeyMap& ckeys)
      25                 :             : {
      26         [ #  # ]:           0 :     return std::unique_ptr<ExternalSignerScriptPubKeyMan>(new ExternalSignerScriptPubKeyMan(storage, descriptor, keypool_size, keys, ckeys));
      27                 :             : }
      28                 :             : 
      29                 :           0 : std::unique_ptr<ExternalSignerScriptPubKeyMan> ExternalSignerScriptPubKeyMan::CreateNew(WalletStorage& storage, WalletBatch& batch, int64_t keypool_size, std::unique_ptr<Descriptor> desc)
      30                 :             : {
      31         [ #  # ]:           0 :     auto spkm = std::unique_ptr<ExternalSignerScriptPubKeyMan>(new ExternalSignerScriptPubKeyMan(storage, keypool_size));
      32                 :             : 
      33         [ #  # ]:           0 :     LOCK(spkm->cs_desc_man);
      34   [ #  #  #  # ]:           0 :     assert(storage.IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS));
      35   [ #  #  #  # ]:           0 :     assert(storage.IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER));
      36                 :             : 
      37         [ #  # ]:           0 :     int64_t creation_time = GetTime();
      38                 :             : 
      39                 :             :     // Make the descriptor
      40   [ #  #  #  # ]:           0 :     WalletDescriptor w_desc(std::move(desc), creation_time, 0, 0, 0);
      41         [ #  # ]:           0 :     spkm->m_wallet_descriptor = w_desc;
      42                 :             : 
      43                 :             :     // Store the descriptor
      44   [ #  #  #  #  :           0 :     if (!batch.WriteDescriptor(spkm->GetID(), spkm->m_wallet_descriptor)) {
                   #  # ]
      45   [ #  #  #  # ]:           0 :         throw std::runtime_error(std::string(__func__) + ": writing descriptor failed");
      46                 :             :     }
      47                 :             : 
      48                 :             :     // TopUp
      49         [ #  # ]:           0 :     spkm->TopUpWithDB(batch);
      50                 :             : 
      51         [ #  # ]:           0 :     storage.UnsetBlankWalletFlag(batch);
      52                 :           0 :     return spkm;
      53         [ #  # ]:           0 : }
      54                 :             : 
      55                 :           0 :  util::Result<ExternalSigner> ExternalSignerScriptPubKeyMan::GetExternalSigner() {
      56   [ #  #  #  # ]:           0 :     const std::string command = gArgs.GetArg("-signer", "");
      57   [ #  #  #  #  :           0 :     if (command == "") return util::Error{Untranslated("restart bitcoind with -signer=<cmd>")};
                   #  # ]
      58                 :           0 :     std::vector<ExternalSigner> signers;
      59   [ #  #  #  #  :           0 :     ExternalSigner::Enumerate(command, signers, Params().GetChainTypeString());
                   #  # ]
      60   [ #  #  #  #  :           0 :     if (signers.empty()) return util::Error{Untranslated("No external signers found")};
                   #  # ]
      61                 :             :     // TODO: add fingerprint argument instead of failing in case of multiple signers.
      62   [ #  #  #  #  :           0 :     if (signers.size() > 1) return util::Error{Untranslated("More than one external signer found. Please connect only one at a time.")};
             #  #  #  # ]
      63         [ #  # ]:           0 :     return signers[0];
      64                 :           0 : }
      65                 :             : 
      66                 :           0 : util::Result<void> ExternalSignerScriptPubKeyMan::DisplayAddress(const CTxDestination& dest, const ExternalSigner &signer) const
      67                 :             : {
      68                 :             :     // TODO: avoid the need to infer a descriptor from inside a descriptor wallet
      69                 :           0 :     const CScript& scriptPubKey = GetScriptForDestination(dest);
      70         [ #  # ]:           0 :     auto provider = GetSolvingProvider(scriptPubKey);
      71         [ #  # ]:           0 :     auto descriptor = InferDescriptor(scriptPubKey, *provider);
      72                 :             : 
      73   [ #  #  #  # ]:           0 :     const UniValue& result = signer.DisplayAddress(descriptor->ToString());
      74                 :             : 
      75         [ #  # ]:           0 :     const UniValue& error = result.find_value("error");
      76   [ #  #  #  # ]:           0 :     if (error.isStr()) return util::Error{strprintf(_("Signer returned error: %s"), error.getValStr())};
      77                 :             : 
      78         [ #  # ]:           0 :     const UniValue& ret_address = result.find_value("address");
      79   [ #  #  #  # ]:           0 :     if (!ret_address.isStr()) return util::Error{_("Signer did not echo address")};
      80                 :             : 
      81   [ #  #  #  # ]:           0 :     if (ret_address.getValStr() != EncodeDestination(dest)) {
      82         [ #  # ]:           0 :         return util::Error{strprintf(_("Signer echoed unexpected address %s"), ret_address.getValStr())};
      83                 :             :     }
      84                 :             : 
      85                 :           0 :     return util::Result<void>();
      86                 :           0 : }
      87                 :             : 
      88                 :             : // If sign is true, transaction must previously have been filled
      89                 :           0 : std::optional<PSBTError> ExternalSignerScriptPubKeyMan::FillPSBT(PartiallySignedTransaction& psbt, const PrecomputedTransactionData& txdata, const common::PSBTFillOptions& options, int* n_signed) const
      90                 :             : {
      91         [ #  # ]:           0 :     if (!options.sign) {
      92                 :           0 :         return DescriptorScriptPubKeyMan::FillPSBT(psbt, txdata, options, n_signed);
      93                 :             :     }
      94                 :             : 
      95                 :             :     // Already complete if every input is now signed
      96                 :           0 :     bool complete = true;
      97         [ #  # ]:           0 :     for (const auto& input : psbt.inputs) {
      98                 :           0 :         complete &= PSBTInputSigned(input);
      99                 :             :     }
     100         [ #  # ]:           0 :     if (complete) return {};
     101                 :             : 
     102                 :           0 :     auto signer{GetExternalSigner()};
     103         [ #  # ]:           0 :     if (!signer) {
     104   [ #  #  #  # ]:           0 :         LogWarning("%s", util::ErrorString(signer).original);
     105                 :           0 :         return PSBTError::EXTERNAL_SIGNER_NOT_FOUND;
     106                 :             :     }
     107                 :             : 
     108                 :           0 :     std::string failure_reason;
     109   [ #  #  #  # ]:           0 :     if(!signer->SignTransaction(psbt, failure_reason)) {
     110         [ #  # ]:           0 :         LogWarning("Failed to sign: %s\n", failure_reason);
     111                 :           0 :         return PSBTError::EXTERNAL_SIGNER_FAILED;
     112                 :             :     }
     113   [ #  #  #  # ]:           0 :     if (options.finalize) FinalizePSBT(psbt); // This won't work in a multisig setup
     114                 :           0 :     return {};
     115                 :           0 : }
     116                 :             : } // namespace wallet
        

Generated by: LCOV version 2.0-1