diff --git a/src/interfaces/wallet.cpp b/src/interfaces/wallet.cpp --- a/src/interfaces/wallet.cpp +++ b/src/interfaces/wallet.cpp @@ -129,7 +129,7 @@ } bool getPubKey(const CScript &script, const CKeyID &address, CPubKey &pub_key) override { - const SigningProvider *provider = + std::unique_ptr provider = m_wallet->GetSigningProvider(script); if (provider) { return provider->GetPubKey(address, pub_key); @@ -138,7 +138,7 @@ } bool getPrivKey(const CScript &script, const CKeyID &address, CKey &key) override { - const SigningProvider *provider = + std::unique_ptr provider = m_wallet->GetSigningProvider(script); if (provider) { return provider->GetKey(address, key); diff --git a/src/wallet/psbtwallet.cpp b/src/wallet/psbtwallet.cpp --- a/src/wallet/psbtwallet.cpp +++ b/src/wallet/psbtwallet.cpp @@ -54,27 +54,28 @@ } SignatureData sigdata; input.FillSignatureData(sigdata); - const SigningProvider *provider = + std::unique_ptr provider = pwallet->GetSigningProvider(script, sigdata); if (!provider) { complete = false; continue; } - complete &= - SignPSBTInput(HidingSigningProvider(provider, !sign, !bip32derivs), - psbtx, i, sighash_type); + complete &= SignPSBTInput( + HidingSigningProvider(provider.get(), !sign, !bip32derivs), psbtx, + i, sighash_type); } // Fill in the bip32 keypaths and redeemscripts for the outputs so that // hardware wallets can identify change for (size_t i = 0; i < psbtx.tx->vout.size(); ++i) { const CTxOut &out = psbtx.tx->vout.at(i); - const SigningProvider *provider = + std::unique_ptr provider = pwallet->GetSigningProvider(out.scriptPubKey); if (provider) { UpdatePSBTOutput( - HidingSigningProvider(provider, true, !bip32derivs), psbtx, i); + HidingSigningProvider(provider.get(), true, !bip32derivs), + psbtx, i); } } diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -628,7 +628,7 @@ } CScript script_pub_key = GetScriptForDestination(*pkhash); - const SigningProvider *provider = + std::unique_ptr provider = pwallet->GetSigningProvider(script_pub_key); if (!provider) { throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available"); @@ -3545,7 +3545,7 @@ entry.pushKV("label", address_book_entry->GetLabel()); } - const SigningProvider *provider = + std::unique_ptr provider = pwallet->GetSigningProvider(scriptPubKey); if (provider) { if (scriptPubKey.IsPayToScriptHash()) { @@ -3568,7 +3568,7 @@ entry.pushKV("spendable", out.fSpendable); entry.pushKV("solvable", out.fSolvable); if (out.fSolvable) { - const SigningProvider *provider = + std::unique_ptr provider = pwallet->GetSigningProvider(scriptPubKey); if (provider) { auto descriptor = InferDescriptor(scriptPubKey, *provider); @@ -3927,23 +3927,23 @@ // Parse the prevtxs array ParsePrevouts(request.params[1], nullptr, coins); - std::set providers; + std::set> providers; for (const std::pair coin_pair : coins) { - const SigningProvider *provider = pwallet->GetSigningProvider( + std::unique_ptr provider = pwallet->GetSigningProvider( coin_pair.second.GetTxOut().scriptPubKey); if (provider) { providers.insert(std::move(provider)); } } if (providers.size() == 0) { - // When there are no available providers, use DUMMY_SIGNING_PROVIDER so + // When there are no available providers, use a dummy SigningProvider so // we can check if the tx is complete - providers.insert(&DUMMY_SIGNING_PROVIDER); + providers.insert(std::make_shared()); } UniValue result(UniValue::VOBJ); - for (const SigningProvider *provider : providers) { - SignTransaction(mtx, provider, coins, request.params[2], result); + for (std::shared_ptr provider : providers) { + SignTransaction(mtx, provider.get(), coins, request.params[2], result); } return result; } @@ -4134,13 +4134,13 @@ UniValue ret(UniValue::VOBJ); UniValue detail = DescribeAddress(dest); CScript script = GetScriptForDestination(dest); - const SigningProvider *provider = nullptr; + std::unique_ptr provider = nullptr; if (pwallet) { provider = pwallet->GetSigningProvider(script); } ret.pushKVs(detail); - ret.pushKVs( - boost::apply_visitor(DescribeWalletAddressVisitor(provider), dest)); + ret.pushKVs(boost::apply_visitor( + DescribeWalletAddressVisitor(provider.get()), dest)); return ret; } @@ -4279,7 +4279,8 @@ ret.pushKV("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end())); - const SigningProvider *provider = pwallet->GetSigningProvider(scriptPubKey); + std::unique_ptr provider = + pwallet->GetSigningProvider(scriptPubKey); isminetype mine = pwallet->IsMine(dest); ret.pushKV("ismine", bool(mine & ISMINE_SPENDABLE)); diff --git a/src/wallet/scriptpubkeyman.h b/src/wallet/scriptpubkeyman.h --- a/src/wallet/scriptpubkeyman.h +++ b/src/wallet/scriptpubkeyman.h @@ -239,7 +239,7 @@ return nullptr; } - virtual const SigningProvider * + virtual std::unique_ptr GetSigningProvider(const CScript &script) const { return nullptr; } @@ -413,7 +413,7 @@ bool CanGetAddresses(bool internal = false) override; - const SigningProvider * + std::unique_ptr GetSigningProvider(const CScript &script) const override; bool CanProvide(const CScript &script, SignatureData &sigdata) override; @@ -537,4 +537,34 @@ std::set GetKeys() const override; }; +/** Wraps a LegacyScriptPubKeyMan so that it can be returned in a new unique_ptr + */ +class LegacySigningProvider : public SigningProvider { +private: + const LegacyScriptPubKeyMan &m_spk_man; + +public: + LegacySigningProvider(const LegacyScriptPubKeyMan &spk_man) + : m_spk_man(spk_man) {} + + bool GetCScript(const CScriptID &scriptid, CScript &script) const override { + return m_spk_man.GetCScript(scriptid, script); + } + bool HaveCScript(const CScriptID &scriptid) const override { + return m_spk_man.HaveCScript(scriptid); + } + bool GetPubKey(const CKeyID &address, CPubKey &pubkey) const override { + return m_spk_man.GetPubKey(address, pubkey); + } + bool GetKey(const CKeyID &address, CKey &key) const override { + return m_spk_man.GetKey(address, key); + } + bool HaveKey(const CKeyID &address) const override { + return m_spk_man.HaveKey(address); + } + bool GetKeyOrigin(const CKeyID &keyid, KeyOriginInfo &info) const override { + return m_spk_man.GetKeyOrigin(keyid, info); + } +}; + #endif // BITCOIN_WALLET_SCRIPTPUBKEYMAN_H diff --git a/src/wallet/scriptpubkeyman.cpp b/src/wallet/scriptpubkeyman.cpp --- a/src/wallet/scriptpubkeyman.cpp +++ b/src/wallet/scriptpubkeyman.cpp @@ -427,9 +427,9 @@ return nTimeFirstKey; } -const SigningProvider * +std::unique_ptr LegacyScriptPubKeyMan::GetSigningProvider(const CScript &script) const { - return this; + return std::make_unique(*this); } bool LegacyScriptPubKeyMan::CanProvide(const CScript &script, diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1429,9 +1429,10 @@ ScriptPubKeyMan *GetScriptPubKeyMan(const uint256 &id) const; //! Get the SigningProvider for a script - const SigningProvider *GetSigningProvider(const CScript &script) const; - const SigningProvider *GetSigningProvider(const CScript &script, - SignatureData &sigdata) const; + std::unique_ptr + GetSigningProvider(const CScript &script) const; + std::unique_ptr + GetSigningProvider(const CScript &script, SignatureData &sigdata) const; //! Get the LegacyScriptPubKeyMan which is used for all types, internal, and //! external. diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1501,7 +1501,8 @@ const CScript &scriptPubKey = txout.scriptPubKey; SignatureData sigdata; - const SigningProvider *provider = GetSigningProvider(scriptPubKey); + std::unique_ptr provider = + GetSigningProvider(scriptPubKey); if (!provider) { // We don't know about this scriptpbuKey; return false; @@ -2400,7 +2401,7 @@ continue; } - const SigningProvider *provider = + std::unique_ptr provider = GetSigningProvider(wtx.tx->vout[i].scriptPubKey); bool solvable = @@ -2732,7 +2733,8 @@ SignatureData sigdata; SigHashType sigHashType = SigHashType().withForkId(); - const SigningProvider *provider = GetSigningProvider(scriptPubKey); + std::unique_ptr provider = + GetSigningProvider(scriptPubKey); if (!provider) { // We don't know about this scriptpbuKey; return false; @@ -3216,7 +3218,7 @@ const CScript &scriptPubKey = coin.txout.scriptPubKey; SignatureData sigdata; - const SigningProvider *provider = + std::unique_ptr provider = GetSigningProvider(scriptPubKey); if (!provider || !ProduceSignature( @@ -4709,13 +4711,13 @@ return nullptr; } -const SigningProvider * +std::unique_ptr CWallet::GetSigningProvider(const CScript &script) const { SignatureData sigdata; return GetSigningProvider(script, sigdata); } -const SigningProvider * +std::unique_ptr CWallet::GetSigningProvider(const CScript &script, SignatureData &sigdata) const { for (const auto &spk_man_pair : m_spk_managers) {