Skip to content

Commit a953e74

Browse files
committed
Add register command for BIP388 policies
1 parent 9878034 commit a953e74

File tree

4 files changed

+61
-0
lines changed

4 files changed

+61
-0
lines changed

hwilib/_cli.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
getdescriptors,
1313
prompt_pin,
1414
toggle_passphrase,
15+
register,
1516
restore_device,
1617
send_pin,
1718
setup_device,
@@ -59,6 +60,9 @@ def backup_device_handler(args: argparse.Namespace, client: HardwareWalletClient
5960
def displayaddress_handler(args: argparse.Namespace, client: HardwareWalletClient) -> Dict[str, str]:
6061
return displayaddress(client, desc=args.desc, path=args.path, addr_type=args.addr_type)
6162

63+
def register_handler(args: argparse.Namespace, client: HardwareWalletClient) -> Dict[str, str]:
64+
return register(client, name=args.name, descriptor_template=args.desc, keys_info=args.key)
65+
6266
def enumerate_handler(args: argparse.Namespace) -> List[Dict[str, Any]]:
6367
return enumerate(password=args.password, expert=args.expert, chain=args.chain, allow_emulators=args.allow_emulators)
6468

@@ -197,6 +201,12 @@ def get_parser() -> HWIArgumentParser:
197201
displayaddr_parser.add_argument("--addr-type", help="The address type to display", type=AddressType.argparse, choices=list(AddressType), default=AddressType.WIT) # type: ignore
198202
displayaddr_parser.set_defaults(func=displayaddress_handler)
199203

204+
register_parser = subparsers.add_parser('register', help='Register a BIP388 wallet policy')
205+
register_parser.add_argument('--name', help='Name for the policy')
206+
register_parser.add_argument('--desc', help='Descriptor template, e.g. tr(musig(@0,@1)')
207+
register_parser.add_argument('--key', help='Key information, e.g. [00000000/84h/0h/0h]xpub...', action='append')
208+
register_parser.set_defaults(func=register_handler)
209+
200210
setupdev_parser = subparsers.add_parser('setup', help='Setup a device. Passphrase protection uses the password given by -p. Requires interactive mode')
201211
setupdev_parser.add_argument('--label', '-l', help='The name to give to the device', default='')
202212
setupdev_parser.add_argument('--backup_passphrase', '-b', help='The passphrase to use for the backup, if applicable', default='')

hwilib/commands.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,24 @@ def displayaddress(
494494
return {"address": client.display_singlesig_address(pubkey.get_full_derivation_path(0), addr_type)}
495495
raise BadArgumentError("Missing both path and descriptor")
496496

497+
def register(
498+
client: HardwareWalletClient,
499+
name: str,
500+
descriptor_template: str,
501+
keys_info: List[str],
502+
) -> Dict[str, str]:
503+
"""
504+
Register a BIP388 policy on the device for client.
505+
506+
:param name: Name for the policy
507+
:param desc: Descriptor template
508+
:return: A dictionary containing policy HMAC.
509+
Returned as ``{"hmac": <hex string>}``.
510+
:raises: BadArgumentError: if an argument is malformed, missing, or conflicts.
511+
"""
512+
513+
return {"hmac": client.register_bip388_policy(name, descriptor_template, keys_info)}
514+
497515
def setup_device(client: HardwareWalletClient, label: str = "", backup_passphrase: str = "") -> Dict[str, bool]:
498516
"""
499517
Setup a device that has not yet been initialized.

hwilib/devices/ledger.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,26 @@ def format_key_info(pubkey: PubkeyProvider) -> str:
479479

480480
return self.client.get_wallet_address(multisig_wallet, registered_hmac, change, address_index, True)
481481

482+
@ledger_exception
483+
def register_bip388_policy(
484+
self,
485+
name: str,
486+
descriptor_template: str,
487+
keys_info: List[str],
488+
) -> str:
489+
if isinstance(self.client, LegacyClient):
490+
raise BadArgumentError("Registering a BIP388 policy not supported by this version of the Bitcoin App")
491+
492+
wallet_policy = WalletPolicy(
493+
name=name,
494+
descriptor_template=descriptor_template,
495+
keys_info=keys_info
496+
)
497+
498+
_, registered_hmac = self.client.register_wallet(wallet_policy)
499+
500+
return registered_hmac.hex()
501+
482502
def setup_device(self, label: str = "", passphrase: str = "") -> bool:
483503
"""
484504
Ledgers do not support setup via software.

hwilib/hwwclient.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
from typing import (
99
Dict,
10+
List,
1011
Optional,
1112
Union,
1213
)
@@ -135,6 +136,18 @@ def display_multisig_address(
135136
raise NotImplementedError("The HardwareWalletClient base class "
136137
"does not implement this method")
137138

139+
def register_bip388_policy(
140+
self,
141+
name: str,
142+
policy: str,
143+
keys_info: List[str]) -> str:
144+
"""
145+
Register a BIP388 policy.
146+
147+
:return: The policy HMAC
148+
"""
149+
raise NotImplementedError("This device does not support BIP388 policies or it's not yet implemented")
150+
138151
def wipe_device(self) -> bool:
139152
"""
140153
Wipe the device.

0 commit comments

Comments
 (0)