Skip to content

Commit afb7ac2

Browse files
committed
Optionally pass BIP388 policy to signtx
1 parent c4fe550 commit afb7ac2

File tree

4 files changed

+42
-5
lines changed

4 files changed

+42
-5
lines changed

hwilib/_cli.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ def signmessage_handler(args: argparse.Namespace, client: HardwareWalletClient)
9292
return signmessage(client, message=args.message, path=args.path)
9393

9494
def signtx_handler(args: argparse.Namespace, client: HardwareWalletClient) -> Dict[str, Union[bool, str]]:
95-
return signtx(client, psbt=args.psbt)
95+
return signtx(client, psbt=args.psbt, policy_name=args.policy_name, descriptor_template=args.policy_desc, keys_info=args.key, hmac=args.hmac)
9696

9797
def wipe_device_handler(args: argparse.Namespace, client: HardwareWalletClient) -> Dict[str, bool]:
9898
return wipe_device(client)
@@ -165,6 +165,11 @@ def get_parser() -> HWIArgumentParser:
165165

166166
signtx_parser = subparsers.add_parser('signtx', help='Sign a PSBT')
167167
signtx_parser.add_argument('psbt', help='The Partially Signed Bitcoin Transaction to sign')
168+
signtx_policy_group = signtx_parser.add_argument_group("BIP388 policy")
169+
signtx_policy_group.add_argument('--policy-name', help='Registered policy name')
170+
signtx_policy_group.add_argument('--policy-desc', help='Registered policy descriptor template')
171+
signtx_policy_group.add_argument('--key', help='Registered policy key information', action='append')
172+
signtx_policy_group.add_argument('--hmac', help='Registered policy hmac, obtained via register command')
168173
signtx_parser.set_defaults(func=signtx_handler)
169174

170175
getxpub_parser = subparsers.add_parser('getxpub', help='Get an extended public key')

hwilib/commands.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,12 @@ def getmasterxpub(client: HardwareWalletClient, addrtype: AddressType = AddressT
183183
"""
184184
return {"xpub": client.get_master_xpub(addrtype, account).to_string()}
185185

186-
def signtx(client: HardwareWalletClient, psbt: str) -> Dict[str, Union[bool, str]]:
186+
def signtx(client: HardwareWalletClient,
187+
psbt: str,
188+
policy_name: str,
189+
descriptor_template: str,
190+
keys_info: List[str],
191+
hmac: str) -> Dict[str, Union[bool, str]]:
187192
"""
188193
Sign a Partially Signed Bitcoin Transaction (PSBT) with the client.
189194
@@ -195,7 +200,7 @@ def signtx(client: HardwareWalletClient, psbt: str) -> Dict[str, Union[bool, str
195200
# Deserialize the transaction
196201
tx = PSBT()
197202
tx.deserialize(psbt)
198-
result = client.sign_tx(tx).serialize()
203+
result = client.sign_tx(tx, policy_name, descriptor_template, keys_info, hmac).serialize()
199204
return {"psbt": result, "signed": result != psbt}
200205

201206
def getxpub(client: HardwareWalletClient, path: str, expert: bool = False) -> Dict[str, Any]:

hwilib/devices/ledger.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,12 @@ def get_pubkey_at_path(self, path: str) -> ExtendedKey:
185185
return ExtendedKey.deserialize(xpub_str)
186186

187187
@ledger_exception
188-
def sign_tx(self, tx: PSBT) -> PSBT:
188+
def sign_tx(self,
189+
tx: PSBT,
190+
policy_name: str,
191+
descriptor_template: str,
192+
keys_info: List[str],
193+
hmac: str) -> PSBT:
189194
"""
190195
Sign a transaction with a Ledger device. Not all transactions can be signed by a Ledger.
191196
@@ -198,6 +203,8 @@ def sign_tx(self, tx: PSBT) -> PSBT:
198203
For application versions 2.1.x and above:
199204
200205
- Only keys derived with standard BIP 44, 49, 84, and 86 derivation paths are supported for single signature addresses.
206+
207+
BIP388 policy arguments are optional, but if one is provided, all must be.
201208
"""
202209
master_fp = self.get_master_fingerprint()
203210

@@ -264,6 +271,22 @@ def legacy_sign_tx() -> PSBT:
264271
else:
265272
continue
266273

274+
policy_args = [policy_name, descriptor_template, keys_info, hmac]
275+
if policy_args != [None] * len(policy_args):
276+
if any(arg is None for arg in policy_args):
277+
raise BadArgumentError("Either all BIP388 policy arguments must be used or none")
278+
policy = WalletPolicy(name=policy_name, descriptor_template=descriptor_template, keys_info=keys_info)
279+
if policy.id not in wallets:
280+
wallets[policy.id] = (
281+
signing_priority[script_addrtype],
282+
script_addrtype,
283+
policy,
284+
bytes.fromhex(hmac),
285+
)
286+
continue
287+
288+
# No BIP388 policy provided, construct on the fly
289+
267290
# Check if P2WSH
268291
if is_p2wsh(scriptcode):
269292
if len(psbt_in.witness_script) == 0:

hwilib/hwwclient.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,11 @@ def get_pubkey_at_path(self, bip32_path: str) -> ExtendedKey:
7979
raise NotImplementedError("The HardwareWalletClient base class "
8080
"does not implement this method")
8181

82-
def sign_tx(self, psbt: PSBT) -> PSBT:
82+
def sign_tx(self, psbt: PSBT,
83+
policy_name=None,
84+
descriptor_template=None,
85+
keys_info=None,
86+
hmac=None) -> PSBT:
8387
"""
8488
Sign a partially signed bitcoin transaction (PSBT).
8589

0 commit comments

Comments
 (0)