Easier to review ignoring whitespace:
git log -p -n1 -w
This commit does not change behavior. It passes new CScript arguments to signing functions, but the arguments aren’t currently used.
Split from #17261
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.
Reviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.
52+ }
53+ SignatureData sigdata;
54+ input.FillSignatureData(sigdata);
55+ const SigningProvider* provider = pwallet->GetSigningProvider(script, sigdata);
56+ if (!provider) {
57+ continue;
complete = false
would seem more consistent with previous behavior which sets complete
to false if it can’t sign one of the inputs.
45+ if (input.non_witness_utxo) {
46+ script = input.non_witness_utxo->vout[txin.prevout.n].scriptPubKey;
47+ } else if (!input.witness_utxo.IsNull()) {
48+ script = input.witness_utxo.scriptPubKey;
49+ } else {
50+ // There's no UTXO so we can just skip this now
complete = false
?
38@@ -39,12 +39,33 @@ TransactionError FillPSBT(const CWallet* pwallet, PartiallySignedTransaction& ps
39 return TransactionError::SIGHASH_MISMATCH;
40 }
41
42- complete &= SignPSBTInput(HidingSigningProvider(pwallet->GetSigningProvider(), !sign, !bip32derivs), psbtx, i, sighash_type);
43+ // Get the scriptPubKey to know which SigningProvider to use
44+ CScript script;
45+ if (input.non_witness_utxo) {
46+ script = input.non_witness_utxo->vout[txin.prevout.n].scriptPubKey;
The signing code will switch to the smaller witness_utxo if this is ok.
). It seems unlikely they’d have different signing providers, but still.
3303+ providers.insert(&DUMMY_SIGNING_PROVIDER);
3304+ }
3305+
3306+ UniValue result;
3307+ for (const SigningProvider* provider : providers) {
3308+ result = SignTransaction(mtx, provider, coins, request.params[2]);
In commit “Refactor: Require scriptPubKey to get wallet SigningProvider” (f7510c144b2262e1ee114eaa740b889c24ec7abb)
According to RPC documentation result has three fields: “hex” “complete” and “errors”. I guess for “hex” and “complete” fields it makes sense to take the last values, but errors field should probably accumulate? In any case, this code is not very future proof in case new fields are added. Would suggest changing SignTransaction to take a UniValue& result
input/output parameter, so it can be responsible for updating the result at each step, and this code isn’t just blindly overwriting previous results.
SignTransaction
to void
and has a result
parameter to accumulate the errors array.
549@@ -550,7 +550,11 @@ static UniValue signmessage(const JSONRPCRequest& request)
550 throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
551 }
552
553- const SigningProvider* provider = pwallet->GetSigningProvider();
554+ CScript script_pub_key = GetScriptForDestination(*pkhash);
In commit “Refactor: Require scriptPubKey to get wallet SigningProvider” (f7510c144b2262e1ee114eaa740b889c24ec7abb)
It would seem more direct to replace *pkhash
with dest
here and call GetScriptForDestination(dest)
pkhash
since signmessage
is supposed to only work on p2pkh addresses.
we still need
pkhash
sincesignmessage
is supposed to only work onp2pkh
addresses
That will change in https://github.com/bitcoin/bitcoin/pull/16440/files#diff-df7d84ff2f53fcb2a0dc15a3a51e55ceR559
3770+ const SigningProvider* provider = pwallet->GetSigningProvider(scriptPubKey);
3771
3772 isminetype mine = pwallet->IsMine(dest);
3773 ret.pushKV("ismine", bool(mine & ISMINE_SPENDABLE));
3774- bool solvable = IsSolvable(*provider, scriptPubKey);
3775+ bool solvable = provider ? IsSolvable(*provider, scriptPubKey) : false;
In commit “Refactor: Require scriptPubKey to get wallet SigningProvider” (f7510c144b2262e1ee114eaa740b889c24ec7abb)
Would be slightly simpler to replace ternary with solvable = provider && IsSolvable(*provider)
SignTransaction will be called multiple times in the future. Pass
it a result UniValue so that it can accumulate the results of multiple
SignTransaction passes.
Easier to review ignoring whitespace:
git log -p -n1 -w
This commit does not change behavior. It passes new CScript arguments to
signing functions, but the arguments aren't currently used.
20@@ -21,9 +21,9 @@ class SigningProvider;
21 * @param keystore Temporary keystore containing signing keys
22 * @param coins Map of unspent outputs
23 * @param hashType The signature hash type
24- * @returns JSON object with details of signed transaction
25+ * @param result JSON object where signed transaction results accumulate
26 */
27-UniValue SignTransaction(CMutableTransaction& mtx, const SigningProvider* keystore, const std::map<COutPoint, Coin>& coins, const UniValue& hashType);
28+void SignTransaction(CMutableTransaction& mtx, const SigningProvider* keystore, const std::map<COutPoint, Coin>& coins, const UniValue& hashType, UniValue& result);
4b0c718f8f48c678cbe4575e9a9cf9e62a30f0da
An overload could be added, like
0UniValue SignTransaction(CMutableTransaction& mtx, const SigningProvider* keystore, const std::map<COutPoint, Coin>& coins, const UniValue& hashType)
1{
2 UniValue result(UniValue::VOBJ);
3 SignTransaction(mtx, &keystore, coins, hashType, result);
4 return result;
5}
But I see that in the next commit this refactor is handy in signrawtransactionwithwallet
RPC.
116@@ -117,8 +117,22 @@ class WalletImpl : public Wallet
117 std::string error;
118 return m_wallet->GetNewDestination(type, label, dest, error);
119 }
120- bool getPubKey(const CKeyID& address, CPubKey& pub_key) override { return m_wallet->GetLegacyScriptPubKeyMan()->GetPubKey(address, pub_key); }
121- bool getPrivKey(const CKeyID& address, CKey& key) override { return m_wallet->GetLegacyScriptPubKeyMan()->GetKey(address, key); }
122+ bool getPubKey(const CScript& script, const CKeyID& address, CPubKey& pub_key) override
address
is a horrible name for this argument
2099@@ -2096,7 +2100,7 @@ void CWallet::AvailableCoins(interfaces::Chain::Lock& locked_chain, std::vector<
2100 continue;
2101 }
2102
2103- const SigningProvider* provider = GetSigningProvider();
2104+ const SigningProvider* provider = GetSigningProvider(wtx.tx->vout[i].scriptPubKey);
3295+ const SigningProvider* provider = pwallet->GetSigningProvider(coin_pair.second.out.scriptPubKey);
3296+ if (provider) {
3297+ providers.insert(std::move(provider));
3298+ }
3299+ }
3300+ if (providers.size() == 0) {
.empty()
121- bool getPrivKey(const CKeyID& address, CKey& key) override { return m_wallet->GetLegacyScriptPubKeyMan()->GetKey(address, key); }
122+ bool getPubKey(const CScript& script, const CKeyID& address, CPubKey& pub_key) override
123+ {
124+ const SigningProvider* provider = m_wallet->GetSigningProvider(script);
125+ if (provider) {
126+ return provider->GetPubKey(address, pub_key);
script
and address
have anything to do with each other. You could end up requesting the wrong SPKM for an address quite easily. Maybe move some of the ExtractDestination stuff inside here instead?
1341@@ -1342,7 +1342,11 @@ bool CWallet::DummySignInput(CTxIn &tx_in, const CTxOut &txout, bool use_max_sig
1342 const CScript& scriptPubKey = txout.scriptPubKey;
1343 SignatureData sigdata;
1344
1345- const SigningProvider* provider = GetSigningProvider();
1346+ const SigningProvider* provider = GetSigningProvider(scriptPubKey);
1347+ if (!provider) {
1348+ // We don't know about this scriptpbuKey;
2976@@ -2971,8 +2977,11 @@ static UniValue listunspent(const JSONRPCRequest& request)
2977 entry.pushKV("spendable", out.fSpendable);
2978 entry.pushKV("solvable", out.fSolvable);
2979 if (out.fSolvable) {
2980- auto descriptor = InferDescriptor(scriptPubKey, *pwallet->GetLegacyScriptPubKeyMan());
2981- entry.pushKV("desc", descriptor->ToString());
2982+ const SigningProvider* provider = pwallet->GetSigningProvider(scriptPubKey);