diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3886,24 +3886,19 @@ // Parse the prevtxs array ParsePrevouts(request.params[1], nullptr, coins); - std::set> providers; - for (const std::pair coin_pair : coins) { - 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 a dummy SigningProvider so - // we can check if the tx is complete - providers.insert(std::make_shared()); + SigHashType nHashType = ParseSighashString(request.params[2]); + if (!nHashType.hasForkId()) { + throw JSONRPCError(RPC_INVALID_PARAMETER, + "Signature must use SIGHASH_FORKID"); } + // Script verification errors + std::map input_errors; + + bool complete = + pwallet->SignTransaction(mtx, coins, nHashType, input_errors); UniValue result(UniValue::VOBJ); - for (std::shared_ptr provider : providers) { - SignTransaction(mtx, provider.get(), coins, request.params[2], result); - } + SignTransactionResultToJSON(mtx, complete, coins, input_errors, result); return result; } diff --git a/src/wallet/scriptpubkeyman.h b/src/wallet/scriptpubkeyman.h --- a/src/wallet/scriptpubkeyman.h +++ b/src/wallet/scriptpubkeyman.h @@ -555,7 +555,8 @@ std::set GetKeys() const override; }; -/** Wraps a LegacyScriptPubKeyMan so that it can be returned in a new unique_ptr +/** + * Wraps a LegacyScriptPubKeyMan so that it can be returned in a new unique_ptr */ class LegacySigningProvider : public SigningProvider { private: diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2757,6 +2757,7 @@ // Input needs to be signed, find the right ScriptPubKeyMan std::set spk_mans = GetScriptPubKeyMans(coin->second.GetTxOut().scriptPubKey, sigdata); + if (spk_mans.size() == 0) { input_errors[i] = "Unable to sign input, missing keys"; continue; @@ -2779,6 +2780,14 @@ visited_spk_mans.insert(spk_man->GetID()); } } + + // When there are no available providers for the remaining inputs, use the + // legacy provider so we can get proper error messages. + auto legacy_spk_man = GetLegacyScriptPubKeyMan(); + if (legacy_spk_man->SignTransaction(tx, coins, sighash, input_errors)) { + return true; + } + return false; } @@ -3243,29 +3252,9 @@ std::numeric_limits::max() - 1)); } - if (sign) { - SigHashType sigHashType = SigHashType().withForkId(); - - int nIn = 0; - for (const auto &coin : selected_coins) { - const CScript &scriptPubKey = coin.txout.scriptPubKey; - SignatureData sigdata; - - std::unique_ptr provider = - GetSigningProvider(scriptPubKey); - if (!provider || - !ProduceSignature( - *provider, - MutableTransactionSignatureCreator( - &txNew, nIn, coin.txout.nValue, sigHashType), - scriptPubKey, sigdata)) { - error = _("Signing transaction failed"); - return false; - } - - UpdateInput(txNew.vin.at(nIn), sigdata); - nIn++; - } + if (sign && !SignTransaction(txNew)) { + error = _("Signing transaction failed"); + return false; } // Return the constructed transaction data.