LCOV - code coverage report
Current view: top level - src/wallet - external_signer_scriptpubkeyman.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 38 41 92.7 %
Date: 2026-06-25 07:23:43 Functions: 5 5 100.0 %

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

Generated by: LCOV version 1.16