1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-17 05:03:07 +00:00

python/trezorctl: support multisig addresses in get-address

This commit is contained in:
matejcik 2020-07-28 11:20:18 +02:00
parent cea634158a
commit 95f33a77c7
2 changed files with 86 additions and 3 deletions

View File

@ -12,6 +12,7 @@ _At the moment, the project does **not** adhere to [Semantic Versioning](https:/
### Added
- `trezorctl set unsafe-prompts` controls the new "unsafe prompts" feature. [#1126]
- `trezorctl btc get-address` can create multisig addresses.
### Changed

View File

@ -18,6 +18,7 @@ import base64
import json
import click
import construct as c
from .. import btc, messages, protobuf, tools
from . import ChoiceType, with_client
@ -37,6 +38,34 @@ OUTPUT_SCRIPTS = {
DEFAULT_COIN = "Bitcoin"
XpubStruct = c.Struct(
"version" / c.Int32ub,
"depth" / c.Int8ub,
"fingerprint" / c.Int32ub,
"child_num" / c.Int32ub,
"chain_code" / c.Bytes(32),
"key" / c.Bytes(33),
c.Terminated,
)
def xpub_deserialize(xpubstr):
xpub_bytes = tools.b58check_decode(xpubstr)
data = XpubStruct.parse(xpub_bytes)
node = messages.HDNodeType(
depth=data.depth,
fingerprint=data.fingerprint,
child_num=data.child_num,
chain_code=data.chain_code,
)
if data.key[0] == 0:
node.private_key = data.key[1:]
else:
node.public_key = data.key
return data.version, node
@click.group(name="btc")
def cli():
"""Bitcoin and Bitcoin-like coins commands."""
@ -52,13 +81,66 @@ def cli():
@click.option("-n", "--address", required=True, help="BIP-32 path")
@click.option("-t", "--script-type", type=ChoiceType(INPUT_SCRIPTS), default="address")
@click.option("-d", "--show-display", is_flag=True)
@click.option("-x", "--multisig-xpub", multiple=True, help="XPUBs of multisig owners")
@click.option("-m", "--multisig-threshold", type=int, help="Number of signatures")
@click.option(
"-N",
"--multisig-suffix-length",
help="BIP-32 suffix length for multisig",
type=int,
default=2,
)
@with_client
def get_address(client, coin, address, script_type, show_display):
"""Get address for specified path."""
def get_address(
client,
coin,
address,
script_type,
show_display,
multisig_xpub,
multisig_threshold,
multisig_suffix_length,
):
"""Get address for specified path.
To obtain a multisig address, provide XPUBs of all signers (including your own) in
the intended order. All XPUBs should be on the same level. By default, it is assumed
that the XPUBs are on the account level, and the last two components of --address
should be derived from all of them.
For BIP-45 multisig:
$ trezorctl btc get-public-node -n m/45h/0
xpub0101
$ trezorctl btc get-address -n m/45h/0/0/7 -m 3 -x xpub0101 -x xpub0202 -x xpub0303
This assumes that the other signers also created xpubs at address "m/45h/i".
For all the signers, the final keys will be derived with the "/0/7" suffix.
You can specify a different suffix length by using the -N option. For example, to
use final xpubs, specify '-N 0'.
"""
coin = coin or DEFAULT_COIN
address_n = tools.parse_path(address)
if multisig_xpub:
if multisig_threshold is None:
raise click.ClickException("Please specify signature threshold")
multisig_suffix = address_n[-multisig_suffix_length:]
nodes = [xpub_deserialize(x)[1] for x in multisig_xpub]
multisig = messages.MultisigRedeemScriptType(
nodes=nodes, address_n=multisig_suffix, m=multisig_threshold
)
if script_type == messages.InputScriptType.SPENDADDRESS:
script_type = messages.InputScriptType.SPENDMULTISIG
return btc.get_address(
client, coin, address_n, show_display, script_type=script_type
client,
coin,
address_n,
show_display,
script_type=script_type,
multisig=multisig,
)