Merge #17371: Refactor: Require scriptPubKey to get wallet SigningProvider

d0dab897af Refactor: Require scriptPubKey to get wallet SigningProvider (Andrew Chow)
4b0c718f8f Accumulate result UniValue in SignTransaction (Andrew Chow)

Pull request description:

  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

ACKs for top commit:
  instagibbs:
    utACK d0dab897af
  ryanofsky:
    Code review ACK d0dab897af. Thanks for the SignTransaction update. No other changes since last review
  Sjors:
    Code review ACK d0dab897af
  promag:
    Code review ACK d0dab897af.
  meshcollider:
    Code review ACK d0dab897af

Tree-SHA512: c3f52df20fd9d6b3b5aa65562cf5f7dce7b7f44c148b0f988f8b578fce2a28e9b7bf010f5f04bb5bf60f5272b2899f1dbbfb8aee81579c21c9cba559d1d2bb70
This commit is contained in:
Samuel Dobson
2019-11-23 08:33:38 +13:00
11 changed files with 137 additions and 57 deletions

View File

@@ -560,7 +560,11 @@ static UniValue signmessage(const JSONRPCRequest& request)
throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
}
const SigningProvider* provider = pwallet->GetSigningProvider();
CScript script_pub_key = GetScriptForDestination(*pkhash);
const SigningProvider* provider = pwallet->GetSigningProvider(script_pub_key);
if (!provider) {
throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available");
}
CKey key;
CKeyID keyID(*pkhash);
@@ -2940,34 +2944,36 @@ static UniValue listunspent(const JSONRPCRequest& request)
entry.pushKV("label", i->second.name);
}
const SigningProvider* provider = pwallet->GetSigningProvider();
if (scriptPubKey.IsPayToScriptHash()) {
const CScriptID& hash = CScriptID(boost::get<ScriptHash>(address));
CScript redeemScript;
if (provider->GetCScript(hash, redeemScript)) {
entry.pushKV("redeemScript", HexStr(redeemScript.begin(), redeemScript.end()));
// Now check if the redeemScript is actually a P2WSH script
CTxDestination witness_destination;
if (redeemScript.IsPayToWitnessScriptHash()) {
bool extracted = ExtractDestination(redeemScript, witness_destination);
CHECK_NONFATAL(extracted);
// Also return the witness script
const WitnessV0ScriptHash& whash = boost::get<WitnessV0ScriptHash>(witness_destination);
CScriptID id;
CRIPEMD160().Write(whash.begin(), whash.size()).Finalize(id.begin());
CScript witnessScript;
if (provider->GetCScript(id, witnessScript)) {
entry.pushKV("witnessScript", HexStr(witnessScript.begin(), witnessScript.end()));
const SigningProvider* provider = pwallet->GetSigningProvider(scriptPubKey);
if (provider) {
if (scriptPubKey.IsPayToScriptHash()) {
const CScriptID& hash = CScriptID(boost::get<ScriptHash>(address));
CScript redeemScript;
if (provider->GetCScript(hash, redeemScript)) {
entry.pushKV("redeemScript", HexStr(redeemScript.begin(), redeemScript.end()));
// Now check if the redeemScript is actually a P2WSH script
CTxDestination witness_destination;
if (redeemScript.IsPayToWitnessScriptHash()) {
bool extracted = ExtractDestination(redeemScript, witness_destination);
CHECK_NONFATAL(extracted);
// Also return the witness script
const WitnessV0ScriptHash& whash = boost::get<WitnessV0ScriptHash>(witness_destination);
CScriptID id;
CRIPEMD160().Write(whash.begin(), whash.size()).Finalize(id.begin());
CScript witnessScript;
if (provider->GetCScript(id, witnessScript)) {
entry.pushKV("witnessScript", HexStr(witnessScript.begin(), witnessScript.end()));
}
}
}
}
} else if (scriptPubKey.IsPayToWitnessScriptHash()) {
const WitnessV0ScriptHash& whash = boost::get<WitnessV0ScriptHash>(address);
CScriptID id;
CRIPEMD160().Write(whash.begin(), whash.size()).Finalize(id.begin());
CScript witnessScript;
if (provider->GetCScript(id, witnessScript)) {
entry.pushKV("witnessScript", HexStr(witnessScript.begin(), witnessScript.end()));
} else if (scriptPubKey.IsPayToWitnessScriptHash()) {
const WitnessV0ScriptHash& whash = boost::get<WitnessV0ScriptHash>(address);
CScriptID id;
CRIPEMD160().Write(whash.begin(), whash.size()).Finalize(id.begin());
CScript witnessScript;
if (provider->GetCScript(id, witnessScript)) {
entry.pushKV("witnessScript", HexStr(witnessScript.begin(), witnessScript.end()));
}
}
}
}
@@ -2978,8 +2984,11 @@ static UniValue listunspent(const JSONRPCRequest& request)
entry.pushKV("spendable", out.fSpendable);
entry.pushKV("solvable", out.fSolvable);
if (out.fSolvable) {
auto descriptor = InferDescriptor(scriptPubKey, *pwallet->GetLegacyScriptPubKeyMan());
entry.pushKV("desc", descriptor->ToString());
const SigningProvider* provider = pwallet->GetSigningProvider(scriptPubKey);
if (provider) {
auto descriptor = InferDescriptor(scriptPubKey, *provider);
entry.pushKV("desc", descriptor->ToString());
}
}
if (avoid_reuse) entry.pushKV("reused", reused);
entry.pushKV("safe", out.fSafe);
@@ -3288,7 +3297,23 @@ UniValue signrawtransactionwithwallet(const JSONRPCRequest& request)
// Parse the prevtxs array
ParsePrevouts(request.params[1], nullptr, coins);
return SignTransaction(mtx, &*pwallet->GetLegacyScriptPubKeyMan(), coins, request.params[2]);
std::set<const SigningProvider*> providers;
for (const std::pair<COutPoint, Coin> coin_pair : coins) {
const SigningProvider* provider = pwallet->GetSigningProvider(coin_pair.second.out.scriptPubKey);
if (provider) {
providers.insert(std::move(provider));
}
}
if (providers.size() == 0) {
// When there are no available providers, use DUMMY_SIGNING_PROVIDER so we can check if the tx is complete
providers.insert(&DUMMY_SIGNING_PROVIDER);
}
UniValue result(UniValue::VOBJ);
for (const SigningProvider* provider : providers) {
SignTransaction(mtx, provider, coins, request.params[2], result);
}
return result;
}
static UniValue bumpfee(const JSONRPCRequest& request)
@@ -3653,9 +3678,10 @@ static UniValue DescribeWalletAddress(CWallet* pwallet, const CTxDestination& de
{
UniValue ret(UniValue::VOBJ);
UniValue detail = DescribeAddress(dest);
CScript script = GetScriptForDestination(dest);
const SigningProvider* provider = nullptr;
if (pwallet) {
provider = pwallet->GetSigningProvider();
provider = pwallet->GetSigningProvider(script);
}
ret.pushKVs(detail);
ret.pushKVs(boost::apply_visitor(DescribeWalletAddressVisitor(provider), dest));
@@ -3747,11 +3773,11 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
CScript scriptPubKey = GetScriptForDestination(dest);
ret.pushKV("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end()));
const SigningProvider* provider = pwallet->GetSigningProvider();
const SigningProvider* provider = pwallet->GetSigningProvider(scriptPubKey);
isminetype mine = pwallet->IsMine(dest);
ret.pushKV("ismine", bool(mine & ISMINE_SPENDABLE));
bool solvable = IsSolvable(*provider, scriptPubKey);
bool solvable = provider && IsSolvable(*provider, scriptPubKey);
ret.pushKV("solvable", solvable);
if (solvable) {
ret.pushKV("desc", InferDescriptor(scriptPubKey, *provider)->ToString());
@@ -3764,7 +3790,7 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
}
ret.pushKV("ischange", pwallet->IsChange(scriptPubKey));
ScriptPubKeyMan* spk_man = pwallet->GetScriptPubKeyMan();
ScriptPubKeyMan* spk_man = pwallet->GetScriptPubKeyMan(scriptPubKey);
if (spk_man) {
if (const CKeyMetadata* meta = spk_man->GetMetadata(dest)) {
ret.pushKV("timestamp", meta->nCreateTime);