RPC/Wallet: Convert descriptorprocesspsbt to use options parameter

This commit is contained in:
Luke Dashjr 2023-12-28 21:39:53 +00:00
parent 390e177215
commit a22be508da
3 changed files with 59 additions and 13 deletions

View File

@ -171,6 +171,9 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "walletprocesspsbt", 3, "bip32derivs" },
{ "walletprocesspsbt", 4, "finalize" },
{ "descriptorprocesspsbt", 1, "descriptors"},
{ "descriptorprocesspsbt", 2, "options" },
{ "descriptorprocesspsbt", 2, "bip32derivs" },
{ "descriptorprocesspsbt", 2, "finalize" },
{ "descriptorprocesspsbt", 3, "bip32derivs" },
{ "descriptorprocesspsbt", 4, "finalize" },
{ "createpsbt", 0, "inputs" },

View File

@ -1937,6 +1937,8 @@ RPCHelpMan descriptorprocesspsbt()
{"range", RPCArg::Type::RANGE, RPCArg::Default{1000}, "Up to what index HD chains should be explored (either end or [begin,end])"},
}},
}},
{"options|sighashtype", {RPCArg::Type::OBJ_NAMED_PARAMS, RPCArg::Type::STR}, RPCArg::Optional::OMITTED, "",
{
{"sighashtype", RPCArg::Type::STR, RPCArg::Default{"DEFAULT for Taproot, ALL otherwise"}, "The signature hash type to sign with if not specified by the PSBT. Must be one of\n"
" \"DEFAULT\"\n"
" \"ALL\"\n"
@ -1944,9 +1946,14 @@ RPCHelpMan descriptorprocesspsbt()
" \"SINGLE\"\n"
" \"ALL|ANYONECANPAY\"\n"
" \"NONE|ANYONECANPAY\"\n"
" \"SINGLE|ANYONECANPAY\""},
{"bip32derivs", RPCArg::Type::BOOL, RPCArg::Default{true}, "Include BIP 32 derivation paths for public keys if we know them"},
{"finalize", RPCArg::Type::BOOL, RPCArg::Default{true}, "Also finalize inputs if possible"},
" \"SINGLE|ANYONECANPAY\"",
RPCArgOptions{.also_positional = true}},
{"bip32derivs", RPCArg::Type::BOOL, RPCArg::Default{true}, "Include BIP 32 derivation paths for public keys if we know them", RPCArgOptions{.also_positional = true}},
{"finalize", RPCArg::Type::BOOL, RPCArg::Default{true}, "Also finalize inputs if possible", RPCArgOptions{.also_positional = true}},
},
RPCArgOptions{.oneline_description="options"}},
{"bip32derivs", RPCArg::Type::BOOL, RPCArg::Default{true}, "for backwards compatibility", RPCArgOptions{.hidden=true}},
{"finalize", RPCArg::Type::BOOL, RPCArg::Default{true}, "for backwards compatibility", RPCArgOptions{.hidden=true}},
},
RPCResult{
RPCResult::Type::OBJ, "", "",
@ -1970,9 +1977,39 @@ RPCHelpMan descriptorprocesspsbt()
EvalDescriptorStringOrObject(descs[i], provider, /*expand_priv=*/true);
}
int sighash_type = ParseSighashString(request.params[2]);
bool bip32derivs = request.params[3].isNull() ? true : request.params[3].get_bool();
bool finalize = request.params[4].isNull() ? true : request.params[4].get_bool();
// Get options
bool bip32derivs = true;
bool finalize = true;
int sighash_type = ParseSighashString(NullUniValue); // Use ParseSighashString default
if (request.params[2].isStr() || request.params[2].isNull()) {
// Old style positional parameters
sighash_type = ParseSighashString(request.params[2]);
bip32derivs = request.params[3].isNull() ? true : request.params[3].get_bool();
finalize = request.params[4].isNull() ? true : request.params[4].get_bool();
} else {
// New style options are in an object
UniValue options = request.params[2];
RPCTypeCheckObj(options,
{
{"bip32derivs", UniValueType(UniValue::VBOOL)},
{"finalize", UniValueType(UniValue::VBOOL)},
{"sighashtype", UniValueType(UniValue::VSTR)},
},
true, true);
if (options.exists("bip32derivs")) {
bip32derivs = options["bip32derivs"].get_bool();
}
if (options.exists("finalize")) {
finalize = options["finalize"].get_bool();
}
if (options.exists("sighashtype")) {
sighash_type = ParseSighashString(options["sighashtype"]);
}
if (request.params.size() > 3) {
// Same behaviour as too many args passed normally
throw std::runtime_error(self.ToString());
}
}
const PartiallySignedTransaction& psbtx = ProcessPSBT(
request.params[0].get_str(),

View File

@ -1027,11 +1027,14 @@ class PSBTTest(BitcoinTestFramework):
# are still added to the psbt
alt_descriptor = descsum_create(f"wpkh({get_generate_key().privkey})")
alt_psbt = self.nodes[2].descriptorprocesspsbt(psbt=psbt, descriptors=[alt_descriptor], sighashtype="ALL")["psbt"]
assert_equal(alt_psbt, self.nodes[2].descriptorprocesspsbt(psbt=psbt, descriptors=[alt_descriptor], options={'sighashtype': "ALL"})["psbt"])
decoded = self.nodes[2].decodepsbt(alt_psbt)
test_psbt_input_keys(decoded['inputs'][0], ['witness_utxo', 'non_witness_utxo'])
# Test that the psbt is not finalized and does not have bip32_derivs unless specified
processed_psbt = self.nodes[2].descriptorprocesspsbt(psbt=psbt, descriptors=[descriptor], sighashtype="ALL", bip32derivs=True, finalize=False)
assert_equal(processed_psbt, self.nodes[2].descriptorprocesspsbt(psbt=psbt, descriptors=[descriptor], options={'sighashtype': "ALL", 'bip32derivs': True, 'finalize': False}))
assert_equal(processed_psbt, self.nodes[2].descriptorprocesspsbt(psbt, [descriptor], "ALL", True, False))
decoded = self.nodes[2].decodepsbt(processed_psbt['psbt'])
test_psbt_input_keys(decoded['inputs'][0], ['witness_utxo', 'non_witness_utxo', 'partial_signatures', 'bip32_derivs'])
@ -1039,6 +1042,7 @@ class PSBTTest(BitcoinTestFramework):
assert "hex" not in processed_psbt
processed_psbt = self.nodes[2].descriptorprocesspsbt(psbt=psbt, descriptors=[descriptor], sighashtype="ALL", bip32derivs=False, finalize=True)
assert_equal(processed_psbt, self.nodes[2].descriptorprocesspsbt(psbt, [descriptor], {'sighashtype': "ALL", 'bip32derivs': False, 'finalize': True}))
decoded = self.nodes[2].decodepsbt(processed_psbt['psbt'])
test_psbt_input_keys(decoded['inputs'][0], ['witness_utxo', 'non_witness_utxo', 'final_scriptwitness'])
@ -1050,6 +1054,8 @@ class PSBTTest(BitcoinTestFramework):
self.log.info("Test descriptorprocesspsbt raises if an invalid sighashtype is passed")
assert_raises_rpc_error(-8, "'all' is not a valid sighash parameter.", self.nodes[2].descriptorprocesspsbt, psbt, [descriptor], sighashtype="all")
assert_raises_rpc_error(-8, "'all' is not a valid sighash parameter.", self.nodes[2].descriptorprocesspsbt, psbt, [descriptor], "all")
assert_raises_rpc_error(-8, "'all' is not a valid sighash parameter.", self.nodes[2].descriptorprocesspsbt, psbt, [descriptor], {'sighashtype': "all"})
if __name__ == '__main__':