aboutsummaryrefslogtreecommitdiff
path: root/src/wallet
diff options
context:
space:
mode:
authorAndrew Chow <achow101-github@achow101.com>2020-02-11 17:10:25 -0500
committerAndrew Chow <achow101-github@achow101.com>2020-04-23 13:59:48 -0400
commitbde7c9fa38775a81d53ac0484fa9c98076a0c7d1 (patch)
treeb17856967ae018b7c09bdcf83165db02b1898da7 /src/wallet
parentd50c8ddd4190f20bf0debd410348b73408ec3143 (diff)
Implement SignTransaction in DescriptorScriptPubKeyMan
Diffstat (limited to 'src/wallet')
-rw-r--r--src/wallet/scriptpubkeyman.cpp11
-rw-r--r--src/wallet/wallet.cpp41
2 files changed, 22 insertions, 30 deletions
diff --git a/src/wallet/scriptpubkeyman.cpp b/src/wallet/scriptpubkeyman.cpp
index 67063ad23c..1eb9dc4d7a 100644
--- a/src/wallet/scriptpubkeyman.cpp
+++ b/src/wallet/scriptpubkeyman.cpp
@@ -1943,7 +1943,16 @@ bool DescriptorScriptPubKeyMan::CanProvide(const CScript& script, SignatureData&
bool DescriptorScriptPubKeyMan::SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, std::string>& input_errors) const
{
- return false;
+ std::unique_ptr<FlatSigningProvider> keys = MakeUnique<FlatSigningProvider>();
+ for (const auto& coin_pair : coins) {
+ std::unique_ptr<FlatSigningProvider> coin_keys = GetSigningProvider(coin_pair.second.out.scriptPubKey, true);
+ if (!coin_keys) {
+ continue;
+ }
+ *keys = Merge(*keys, *coin_keys);
+ }
+
+ return ::SignTransaction(tx, keys.get(), coins, sighash, input_errors);
}
SigningResult DescriptorScriptPubKeyMan::SignMessage(const std::string& message, const PKHash& pkhash, std::string& str_sig) const
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 8f42d1d75f..062162bdf7 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -2428,11 +2428,17 @@ bool CWallet::SignTransaction(CMutableTransaction& tx) const
bool CWallet::SignTransaction(CMutableTransaction& tx, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, std::string>& input_errors) const
{
- // Sign the tx with ScriptPubKeyMans
- // Because each ScriptPubKeyMan can sign more than one input, we need to keep track of each ScriptPubKeyMan that has signed this transaction.
- // Each iteration, we may sign more txins than the txin that is specified in that iteration.
- // We assume that each input is signed by only one ScriptPubKeyMan.
- std::set<uint256> visited_spk_mans;
+ // Try to sign with all ScriptPubKeyMans
+ for (ScriptPubKeyMan* spk_man : GetAllScriptPubKeyMans()) {
+ // spk_man->SignTransaction will return true if the transaction is complete,
+ // so we can exit early and return true if that happens
+ if (spk_man->SignTransaction(tx, coins, sighash, input_errors)) {
+ return true;
+ }
+ }
+
+ // At this point, one input was not fully signed otherwise we would have exited already
+ // Find that input and figure out what went wrong.
for (unsigned int i = 0; i < tx.vin.size(); i++) {
// Get the prevout
CTxIn& txin = tx.vin[i];
@@ -2444,33 +2450,10 @@ bool CWallet::SignTransaction(CMutableTransaction& tx, const std::map<COutPoint,
// Check if this input is complete
SignatureData sigdata = DataFromTransaction(tx, i, coin->second.out);
- if (sigdata.complete) {
- continue;
- }
-
- // Input needs to be signed, find the right ScriptPubKeyMan
- std::set<ScriptPubKeyMan*> spk_mans = GetScriptPubKeyMans(coin->second.out.scriptPubKey, sigdata);
- if (spk_mans.size() == 0) {
+ if (!sigdata.complete) {
input_errors[i] = "Unable to sign input, missing keys";
continue;
}
-
- for (auto& spk_man : spk_mans) {
- // If we've already been signed by this spk_man, skip it
- if (visited_spk_mans.count(spk_man->GetID()) > 0) {
- continue;
- }
-
- // Sign the tx.
- // spk_man->SignTransaction will return true if the transaction is complete,
- // so we can exit early and return true if that happens.
- if (spk_man->SignTransaction(tx, coins, sighash, input_errors)) {
- return true;
- }
-
- // Add this spk_man to visited_spk_mans so we can skip it later
- visited_spk_mans.insert(spk_man->GetID());
- }
}
return false;
}