Skip to content

Commit

Permalink
jadepy: new api calls and tests for miniscript descriptor wallets
Browse files Browse the repository at this point in the history
  • Loading branch information
JamieDriver committed Oct 19, 2023
1 parent 8da3df8 commit 78816c8
Show file tree
Hide file tree
Showing 8 changed files with 465 additions and 34 deletions.
51 changes: 50 additions & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,55 @@ ota_complete reply
* A 'true' response implies the firmware upload completed successfully, and the next restart will attempt to boot the new firmware.

.. _register_descriptor_request:

register_descriptor request
---------------------------

Jade can store up to 16 user-defined miniscript descriptor wallet configurations, which need to be confirmed on the hw.

.. code-block:: cbor
{
"id": "186282",
"method": "register_descriptor"
"params": {
"network": "mainnet",
"descriptor_name": "inheritance",
"descriptor": "wsh(or_d(pk(@0/<0;1>/*),and_v(v:multi(2,@1/<0;1>/*,@2/<0;1>/*),older(4320))))",
"datavalues": [
{
"key": "@0",
"value": "[1bf12fe0/48'/1'/0'/2']tpubDEHXLZfMAAM5duEnX6SSnZjGYbrxqXvRJmMxw8MFwr3gu4LC4DSxR9KVEfVDVcZxre4XL5tGcwVRrHwQ9euTMnSq6P6BqREemaqrFsC96Fy",
},
{
"key": "@1",
"value": "[eda3d606/48'/1'/0'/2']tpubDEAmqvQkhqP6SbfbSPu3AeRR9kfHLFXYvNDiWashLy7V2zicg1YLg654AqfomsC6kFwTs4MpcnqwxN2AnYAqi5JZeuVDBn3rfZZLTaAuS8Y",
},
{
"key": "@2",
"value": "[e1640396/48'/1'/0'/2']tpubDFgDvZifofePphQiVjLfkov8YTDg3UPuHRvt6LzbySYMZQhN19p6zvR7NTEXi1ZJAMNostHMTnz2sfXXYcJFQqtyCnNuUfgYqsahxTLGJq2",
}
]
}
}
* 'descriptor_name' is a string, and must be less than 16 characters long. Using an existing name will overwrite the corresponding descriptor registration record.
* 'descriptor' is the descriptor string. It must be a 'wallet policy' miniscript expression with the keys presented in the accompanying datavalues map.
* 'datavalues' is the map of signers' keys, which must include an entry for the Jade signer.

.. _register_descriptor_reply:

register_descriptor reply
-------------------------

.. code-block:: cbor
{
"id": "186282",
"result": true
}
.. _register_multisig_request:

register_multisig request
Expand Down Expand Up @@ -630,7 +679,7 @@ or:
}
}
* 'multisig_name' is a string, and must be less than 16 characters long. Using an existing name will overwrite the corresponding registration record.
* 'multisig_name' is a string, and must be less than 16 characters long. Using an existing name will overwrite the corresponding multisig registration record.
* 'variant' indicates the script type used, and must be one of: 'sh(multi(k))', 'wsh(multi(k))' or 'sh(wsh(multi(k)))'
* 'master_blinding_key' should be set for multisigs to be used on a Liquid network if the Jade is to provide confidential addresses, blinding keys, blinding nonces, asset blinding factors or output commitments. Otherwise it can be omitted.
* 'fingerprint' is the 4-byte wallet origin fingerprint - at least one signer must reference the Jade signer's root xpub fingerprint.
Expand Down
40 changes: 39 additions & 1 deletion jadepy/jade.py
Original file line number Diff line number Diff line change
Expand Up @@ -901,8 +901,32 @@ def register_multisig_file(self, multisig_file):
params = {'multisig_file': multisig_file}
return self._jadeRpc('register_multisig', params)

def register_descriptor(self, network, descriptor_name, descriptor_script, datavalues=None):
"""
RPC call to register a new descriptor wallet, which must contain the hw signer.
A registration name is provided - if it already exists that record is overwritten.
Parameters
----------
network : string
Network to which the multisig should apply - eg. 'mainnet', 'liquid', 'testnet', etc.
descriptor_name : string
Name to use to identify this descriptor wallet registration record.
If a registration record exists with the name given, that record is overwritten.
Returns
-------
bool
True on success, implying the descriptor wallet can now be used.
"""
params = {'network': network, 'descriptor_name': descriptor_name,
'descriptor': descriptor_script, 'datavalues': datavalues}
return self._jadeRpc('register_descriptor', params)

def get_receive_address(self, *args, recovery_xpub=None, csv_blocks=0,
variant=None, multisig_name=None, confidential=None):
variant=None, multisig_name=None, descriptor_name=None,
confidential=None):
"""
RPC call to generate, show, and return an address for the given path.
The call has three forms.
Expand Down Expand Up @@ -948,6 +972,16 @@ def get_receive_address(self, *args, recovery_xpub=None, csv_blocks=0,
multisig_name : str
The name of the registered multisig wallet record used to generate the address.
4. Descriptor wallet addresses
branch : int
Multi-path derivation branch, usually 0.
pointer : int
Path index to descriptor
descriptor_name : str
The name of the registered descriptor wallet record used to generate the address.
Returns
-------
str
Expand All @@ -958,6 +992,10 @@ def get_receive_address(self, *args, recovery_xpub=None, csv_blocks=0,
assert len(args) == 2
keys = ['network', 'paths', 'multisig_name']
args += (multisig_name,)
elif descriptor_name is not None:
assert len(args) == 3
keys = ['network', 'branch', 'pointer', 'descriptor_name']
args += (descriptor_name,)
elif variant is not None:
assert len(args) == 2
keys = ['network', 'path', 'variant']
Expand Down
24 changes: 24 additions & 0 deletions test_data/descriptor_ss_anchorwatch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"input": {
"network": "testnet",
"descriptor_name": "testanchorwatch",
"descriptor": "wsh(or_d(pk(@0/<0;1>/*),and_v(v:multi(2,@1/<0;1>/*,@2/<0;1>/*),older(4320))))",
"datavalues": {
"@0": "[1273da33/48'/1'/0'/2']tpubDEAjmvwVDj4aTdNLyLdoVGdEuRf8ZMsZEun6Aa2uMHa3DFNSzXQFt8DY62gi37RuaPTcpoNFage2h6dPHABssCnWcp2j6srQTpWbGEKHgU1",
"@1": "[e3ebcc79/48'/1'/0'/2']tpubDDvj9CrVJ9kWXSL2kjtA8v53rZvTmL3HmWPvgD3hiTnD5KZuMkxSUsgGraZ9vavB5JSA3F9s5E4cXuCte5rvBs5N4DjfxYssQk1L82Bq4FE",
"@2": "[e1640396/48'/1'/0'/2']tpubDFgDvZifofePphQiVjLfkov8YTDg3UPuHRvt6LzbySYMZQhN19p6zvR7NTEXi1ZJAMNostHMTnz2sfXXYcJFQqtyCnNuUfgYqsahxTLGJq2"
}
},
"address_tests": [
{
"branch": 0,
"pointer": 0,
"expected_address": "tb1qc8vql2ljkkmtc9kqj6v45qde0e8jgusva6d8ex5zpzpv75k6vw8sswsajw"
},
{
"branch": 0,
"pointer": 1,
"expected_address": "tb1qtyjtmq0ya577qkyhq6v8ue7hjsmmde6j80fndm0f5gl8kfjx7nysn6w6fq"
}
]
}
34 changes: 34 additions & 0 deletions test_data/descriptor_ss_liana.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"input": {
"network": "testnet",
"descriptor_name": "testliana",
"descriptor": "wsh(or_d(multi(2,@0/<0;1>/*,@1/<0;1>/*),and_v(v:pkh(@2/<0;1>/*),older(100))))",
"datavalues": {
"@0": "[1273da33/48'/1'/0'/2']tpubDEAjmvwVDj4aTdNLyLdoVGdEuRf8ZMsZEun6Aa2uMHa3DFNSzXQFt8DY62gi37RuaPTcpoNFage2h6dPHABssCnWcp2j6srQTpWbGEKHgU1",
"@1": "[e3ebcc79/48'/1'/0'/2']tpubDDvj9CrVJ9kWXSL2kjtA8v53rZvTmL3HmWPvgD3hiTnD5KZuMkxSUsgGraZ9vavB5JSA3F9s5E4cXuCte5rvBs5N4DjfxYssQk1L82Bq4FE",
"@2": "[7897b5b3/48'/1'/1'/2']tpubDFf2ES1oUSZRgiCFT4mvBQ4jC2xTfRzVwfa6KewXZthgtL83UquqirWXzo1EKi4et3bx2wQz9QFKLDeu6vXoKpgQnJHyV8DomjCjJRT3d57"
}
},
"address_tests": [
{
"branch": 0,
"pointer": 0,
"expected_address": "tb1qrgvtrz6fgs5zqt3tjr00zvj0mmncxtqya8ekyd0cdw8k4f76csgq8uwec9"
},
{
"branch": 0,
"pointer": 1,
"expected_address": "tb1q3f0s843r2gzzfvdvun53rs7ykjm6uxtvw97j4avugqcd933tpzhsyhuc4x"
},
{
"branch": 1,
"pointer": 0,
"expected_address": "tb1qav54lcan22y7apd2xagt3q4dtkvn2z5eruyxugj99ahcw6cwf8eqr4z3m7"
},
{
"branch": 1,
"pointer": 1,
"expected_address": "tb1q4mrwkmvsrgpqwr6hnhc425zsjevf86vcl7x42x9dvem2a46l695styrjnu"
}
]
}
59 changes: 59 additions & 0 deletions test_data/descriptor_ss_multisig_sh_wsh_unsorted_match.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
{
"input": {
"network": "testnet",
"descriptor_name": "sh_wsh_unsorted",
"descriptor": "sh(wsh(multi(1,@0/**,@1/**)))",
"datavalues": {
"@0": "[1273da33/48'/1'/0'/1']tpubDEAjmvwVDj4aPk3kXMnajWYnp7RX27uU6D1TFmJvKykmtVwttXBekZ6UEu4xYcZX7hQsuKbECnsC6P6LKCw45uCp2fh2KEwNWcRh1229T57",
"@1": "[e3ebcc79/48'/1'/0'/1']tpubDDvj9CrVJ9kWVUsayi3QZQQBsneoyvXUV313SDztDE8ziAchxZfnGx9GwQv5nWGeVZtpfgev3eh94mK3oG1tpHGZpm3pTMPJ4EQnFK7t877"
},
"multisig_equivalent": {
"descriptor": {
"variant": "sh(wsh(multi(k)))",
"sorted": false,
"threshold": 1,
"signers": [
{
"fingerprint": "1273da33",
"derivation": [
2147483696,
2147483649,
2147483648,
2147483649
],
"xpub": "tpubDEAjmvwVDj4aPk3kXMnajWYnp7RX27uU6D1TFmJvKykmtVwttXBekZ6UEu4xYcZX7hQsuKbECnsC6P6LKCw45uCp2fh2KEwNWcRh1229T57",
"path": []
},
{
"fingerprint": "e3ebcc79",
"derivation": [
2147483696,
2147483649,
2147483648,
2147483649
],
"xpub": "tpubDDvj9CrVJ9kWVUsayi3QZQQBsneoyvXUV313SDztDE8ziAchxZfnGx9GwQv5nWGeVZtpfgev3eh94mK3oG1tpHGZpm3pTMPJ4EQnFK7t877",
"path": []
}
]
}
}
},
"address_tests": [
{
"branch": 0,
"pointer": 0,
"expected_address": "2NGBcvqkhMAZvpUwcE7bo9PirFB9sGceLCU"
},
{
"branch": 0,
"pointer": 32,
"expected_address": "2MtGMmcVsXkEtGQfgv3MKCD7eExTCHjPGMp"
},
{
"branch": 0,
"pointer": 658,
"expected_address": "2NAmfNinCqTWmNHBqHe3WXsZNYJJcqPnZVo"
}
]
}
59 changes: 59 additions & 0 deletions test_data/descriptor_ss_multisig_wsh_sorted_match.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
{
"input": {
"network": "testnet",
"descriptor_name": "wsh_sorted",
"descriptor": "wsh(sortedmulti(2,@0/**,@1/**))",
"datavalues": {
"@0": "[1273da33/48'/1'/0'/2']tpubDEAjmvwVDj4aTdNLyLdoVGdEuRf8ZMsZEun6Aa2uMHa3DFNSzXQFt8DY62gi37RuaPTcpoNFage2h6dPHABssCnWcp2j6srQTpWbGEKHgU1",
"@1": "[e3ebcc79/48'/1'/0'/2']tpubDDvj9CrVJ9kWXSL2kjtA8v53rZvTmL3HmWPvgD3hiTnD5KZuMkxSUsgGraZ9vavB5JSA3F9s5E4cXuCte5rvBs5N4DjfxYssQk1L82Bq4FE"
},
"multisig_equivalent": {
"descriptor": {
"variant": "wsh(multi(k))",
"sorted": true,
"threshold": 2,
"signers": [
{
"fingerprint": "1273da33",
"derivation": [
2147483696,
2147483649,
2147483648,
2147483650
],
"xpub": "tpubDEAjmvwVDj4aTdNLyLdoVGdEuRf8ZMsZEun6Aa2uMHa3DFNSzXQFt8DY62gi37RuaPTcpoNFage2h6dPHABssCnWcp2j6srQTpWbGEKHgU1",
"path": []
},
{
"fingerprint": "e3ebcc79",
"derivation": [
2147483696,
2147483649,
2147483648,
2147483650
],
"xpub": "tpubDDvj9CrVJ9kWXSL2kjtA8v53rZvTmL3HmWPvgD3hiTnD5KZuMkxSUsgGraZ9vavB5JSA3F9s5E4cXuCte5rvBs5N4DjfxYssQk1L82Bq4FE",
"path": []
}
]
}
}
},
"address_tests": [
{
"branch": 0,
"pointer": 0,
"expected_address": "tb1qe5f847vum9jvad5tnu2ghwv6470asy5tmewetjth0cxhpm3t28xq3ykdlc"
},
{
"branch": 0,
"pointer": 27,
"expected_address": "tb1qwd6qm0rt7p7nch9wnym6td6vs0kk4qzxppfw0ujftcmr60v7tfpqmccswj"
},
{
"branch": 0,
"pointer": 736,
"expected_address": "tb1qkluc3eyaukn3r24a5za2aqh44grc4qxfnzuwn2wp3ulx6j3f27esk3u9yh"
}
]
}
23 changes: 23 additions & 0 deletions test_data/descriptor_ss_p2sh_example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"input": {
"network": "testnet",
"descriptor_name": "p2sh_p2wsh_ms",
"descriptor": "sh(wsh(or_d(thresh(1,pk(@0/<0;1>/*)),and_v(v:thresh(1,pk(@1/<0;1>/*)),older(30)))))",
"datavalues": {
"@0": "[1273da33/48'/1'/0'/2']tpubDEAjmvwVDj4aTdNLyLdoVGdEuRf8ZMsZEun6Aa2uMHa3DFNSzXQFt8DY62gi37RuaPTcpoNFage2h6dPHABssCnWcp2j6srQTpWbGEKHgU1",
"@1": "[e3ebcc79/48'/1'/0'/2']tpubDDvj9CrVJ9kWXSL2kjtA8v53rZvTmL3HmWPvgD3hiTnD5KZuMkxSUsgGraZ9vavB5JSA3F9s5E4cXuCte5rvBs5N4DjfxYssQk1L82Bq4FE"
}
},
"address_tests": [
{
"branch": 0,
"pointer": 0,
"expected_address": "2NAxP4LFDiHkjkWsExDn18sMzk3GfDYCZPB"
},
{
"branch": 0,
"pointer": 1,
"expected_address": "2MwfaaqyQARv5zLbwa4yq23WiX535tsBnqo"
}
]
}
Loading

0 comments on commit 78816c8

Please sign in to comment.