Skip to content

Commit ed03bfc

Browse files
committed
Merge #726: Support descriptors with checksums in initpegoutwallet
5af17a4 Update initpegoutwallet help to describe derivation paths properly. (Gregory Sanders) 55c4c6c Fix other bug in initpegoutwallet descriptor parsing (Steven Roose) 28dac17 Temp disable pegout descriptors that are not pkh() (Steven Roose) fdba8c4 Support descriptors with checksums in initpegoutwallet (Steven Roose) Pull request description: Non-pkh descriptor types will be re-enabled once entire liquid network functionary set is updated to use elements daemons. Tree-SHA512: 41203f767c4879251eb958f938a8cc88b8f5d03ffa16bb598645f5c1bd5b45d7e6468cadcb3c5c12abd62c73913834718b9ad48a24f721537d1e8a0a3cf7e6fc
2 parents 280c33f + 5af17a4 commit ed03bfc

File tree

3 files changed

+20
-10
lines changed

3 files changed

+20
-10
lines changed

src/script/descriptor.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -464,13 +464,6 @@ class DescriptorImpl : public Descriptor
464464
}
465465
};
466466

467-
//TODO(stevenroose) remove if unused
468-
CScript P2PKHGetScript(const CPubKey& pubkey) { return GetScriptForDestination(PKHash(pubkey)); }
469-
CScript P2PKGetScript(const CPubKey& pubkey) { return GetScriptForRawPubKey(pubkey); }
470-
CScript P2WPKHGetScript(const CPubKey& pubkey) { return GetScriptForDestination(WitnessV0KeyHash(pubkey.GetID())); }
471-
CScript ConvertP2SH(const CScript& script) { return GetScriptForDestination(ScriptHash(script)); }
472-
CScript ConvertP2WSH(const CScript& script) { return GetScriptForDestination(WitnessV0ScriptHash(script)); }
473-
474467
/** Construct a vector with one element, which is moved into it. */
475468
template<typename T>
476469
std::vector<T> Singleton(T elem)

src/wallet/rpcwallet.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4915,7 +4915,7 @@ UniValue initpegoutwallet(const JSONRPCRequest& request)
49154915
"\nThis call is for Liquid network initialization on the Liquid wallet. The wallet generates a new Liquid pegout authorization key (PAK) and stores it in the Liquid wallet. It then combines this with the `bitcoin_descriptor` to finally create a PAK entry for the network. This allows the user to send Liquid coins directly to a secure offline Bitcoin wallet at the derived path from the bitcoin_descriptor using the `sendtomainchain` command. Losing the Liquid PAK or offline Bitcoin root key will result in the inability to pegout funds, so immediate backup upon initialization is required.\n" +
49164916
HelpRequiringPassphrase(pwallet),
49174917
{
4918-
{"bitcoin_descriptor", RPCArg::Type::STR, RPCArg::Optional::NO, "The Bitcoin descriptor that includes a single extended pubkey. Must be one of the following: pkh(<xpub>), sh(wpkh(<xpub>)), or wpkh(<xpub>). This is used as the root for the Bitcoin destination wallet. The derivation path from the xpub will be `0/k`, reflecting the external chain of the wallet. DEPRECATED: If a plain xpub is given, pkh(<xpub>) is assumed. See link for more details on script descriptors: https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md"},
4918+
{"bitcoin_descriptor", RPCArg::Type::STR, RPCArg::Optional::NO, "The Bitcoin descriptor that includes a single extended pubkey. Must be one of the following: pkh(<xpub>), sh(wpkh(<xpub>)), or wpkh(<xpub>). This is used as the destination chain for the Bitcoin destination wallet. The derivation path from the xpub is given by the descriptor, typically `0/k`, reflecting the external chain of the wallet. DEPRECATED: If a plain xpub is given, pkh(<xpub>) is assumed, with the `0/k` derivation from that xpub. See link for more details on script descriptors: https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md"},
49194919
{"bip32_counter", RPCArg::Type::NUM , /* default */ "0", "The `k` in `0/k` to be set as the next address to derive from the `bitcoin_descriptor`. This will be stored in the wallet and incremented on each successful `sendtomainchain` invocation."},
49204920
{"liquid_pak", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED_NAMED_ARG, "The Liquid wallet pubkey in hex to be used as the Liquid PAK for pegout authorization. The private key must be in the wallet if argument is given. If this argument is not provided one will be generated and stored in the wallet automatically and returned."}
49214921
},
@@ -4982,19 +4982,32 @@ UniValue initpegoutwallet(const JSONRPCRequest& request)
49824982
}
49834983

49844984
FlatSigningProvider provider;
4985-
auto desc = Parse(bitcoin_desc, provider);
4985+
auto desc = Parse(bitcoin_desc, provider, false); // don't require checksum
49864986
if (!desc) {
49874987
throw JSONRPCError(RPC_INVALID_PARAMETER, "bitcoin_descriptor is not a valid descriptor string.");
49884988
} else if (!desc->IsRange()) {
49894989
throw JSONRPCError(RPC_INVALID_PARAMETER, "bitcoin_descriptor must be a ranged descriptor.");
49904990
}
49914991

4992+
// For our manual pattern matching, we don't want the checksum part.
4993+
auto checksum_char = bitcoin_desc.find('#');
4994+
if (checksum_char != std::string::npos) {
4995+
bitcoin_desc = bitcoin_desc.substr(0, checksum_char);
4996+
}
4997+
49924998
// Three acceptable descriptors:
4999+
bool is_liquid = Params().NetworkIDString() == "liquidv1";
49935000
if (bitcoin_desc.substr(0, 8) == "sh(wpkh("
49945001
&& bitcoin_desc.substr(bitcoin_desc.size()-2, 2) == "))") {
5002+
if(is_liquid) {
5003+
throw JSONRPCError(RPC_INVALID_PARAMETER, "bitcoin_descriptor is not supported by Liquid; try pkh(<xpub>) or <xpub>.");
5004+
}
49955005
xpub_str = bitcoin_desc.substr(8, bitcoin_desc.size()-2);
49965006
} else if (bitcoin_desc.substr(0, 5) == "wpkh("
49975007
&& bitcoin_desc.substr(bitcoin_desc.size()-1, 1) == ")") {
5008+
if(is_liquid) {
5009+
throw JSONRPCError(RPC_INVALID_PARAMETER, "bitcoin_descriptor is not supported by Liquid; try pkh(<xpub>) or <xpub>.");
5010+
}
49985011
xpub_str = bitcoin_desc.substr(5, bitcoin_desc.size()-1);
49995012
} else if (bitcoin_desc.substr(0, 4) == "pkh("
50005013
&& bitcoin_desc.substr(bitcoin_desc.size()-1, 1) == ")") {
@@ -5005,7 +5018,7 @@ UniValue initpegoutwallet(const JSONRPCRequest& request)
50055018

50065019
// Strip off leading key origin
50075020
if (xpub_str.find("]") != std::string::npos) {
5008-
xpub_str = xpub_str.substr(xpub_str.find("]"), std::string::npos);
5021+
xpub_str = xpub_str.substr(xpub_str.find("]")+1, std::string::npos);
50095022
}
50105023

50115024
// Strip off following range

test/functional/feature_pak.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ def run_test(self):
6363

6464
assert_raises_rpc_error(-8, "bip32_counter must be between 0 and 1,000,000,000, inclusive.", self.nodes[1].initpegoutwallet, xpub, 1000000001)
6565

66+
# Make sure we can also prepend the key origin to the xpub.
67+
self.nodes[1].initpegoutwallet("pkh([deadbeef/44h/0h/0h]"+xpub+"/0/*)")
6668
new_init = self.nodes[1].initpegoutwallet(xpub, 2)
6769
assert_equal(self.nodes[1].getwalletpakinfo()["bip32_counter"], "2")
6870
assert_equal(new_init["address_lookahead"][0], init_results[1]["address_lookahead"][2])
@@ -167,6 +169,8 @@ def run_test(self):
167169

168170
# Peg out with each new type, check that destination script matches
169171
wpkh_desc = "wpkh("+xpub+"/0/*)"
172+
# add a valid checksum
173+
wpkh_desc = self.nodes[1].getdescriptorinfo(wpkh_desc)["descriptor"]
170174
wpkh_info = self.nodes[1].initpegoutwallet(wpkh_desc)
171175
wpkh_pak_info = self.nodes[1].getwalletpakinfo()
172176

0 commit comments

Comments
 (0)