1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-22 22:38:08 +00:00

Merge pull request #105 from trezor/tsusanka/multisig

Multisignature signing
This commit is contained in:
Jan Pochyla 2018-02-26 16:14:13 +01:00 committed by GitHub
commit 6e7a15c088
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
135 changed files with 2391 additions and 588 deletions

View File

@ -74,21 +74,21 @@ STATIC mp_obj_t mod_trezorcrypto_HDNode_make_new(const mp_obj_type_t *type, size
mp_get_buffer_raise(vals[5].u_obj, &public_key, MP_BUFFER_READ);
mp_get_buffer_raise(vals[6].u_obj, &curve_name, MP_BUFFER_READ);
if (NULL == chain_code.buf || 32 != chain_code.len) {
if (32 != chain_code.len) {
mp_raise_ValueError("chain_code is invalid");
}
if (NULL == public_key.buf && NULL == private_key.buf) {
if (0 == public_key.len && 0 == private_key.len) {
mp_raise_ValueError("either public_key or private_key is required");
}
if (NULL != private_key.buf && 32 != private_key.len) {
if (0 != private_key.len && 32 != private_key.len) {
mp_raise_ValueError("private_key is invalid");
}
if (NULL != public_key.buf && 33 != public_key.len) {
if (0 != public_key.len && 33 != public_key.len) {
mp_raise_ValueError("public_key is invalid");
}
const curve_info *curve = NULL;
if (NULL == curve_name.buf) {
if (0 == curve_name.len) {
curve = get_curve_by_name(SECP256K1_NAME);
} else {
curve = get_curve_by_name(curve_name.buf);
@ -103,17 +103,17 @@ STATIC mp_obj_t mod_trezorcrypto_HDNode_make_new(const mp_obj_type_t *type, size
o->fingerprint = fingerprint;
o->hdnode.depth = depth;
o->hdnode.child_num = child_num;
if (NULL != chain_code.buf && 32 == chain_code.len) {
if (32 == chain_code.len) {
memcpy(o->hdnode.chain_code, chain_code.buf, 32);
} else {
memzero(o->hdnode.chain_code, 32);
}
if (NULL != private_key.buf && 32 == private_key.len) {
if (32 == private_key.len) {
memcpy(o->hdnode.private_key, private_key.buf, 32);
} else {
memzero(o->hdnode.private_key, 32);
}
if (NULL != public_key.buf && 33 == public_key.len) {
if (33 == public_key.len) {
memcpy(o->hdnode.public_key, public_key.buf, 33);
} else {
memzero(o->hdnode.public_key, 33);
@ -123,16 +123,27 @@ STATIC mp_obj_t mod_trezorcrypto_HDNode_make_new(const mp_obj_type_t *type, size
return MP_OBJ_FROM_PTR(o);
}
/// def derive(self, index: int) -> None:
/// def derive(self, index: int, public: bool=False) -> None:
/// '''
/// Derive a BIP0032 child node in place.
/// '''
STATIC mp_obj_t mod_trezorcrypto_HDNode_derive(mp_obj_t self, mp_obj_t index) {
mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(self);
uint32_t i = mp_obj_get_int_truncated(index);
STATIC mp_obj_t mod_trezorcrypto_HDNode_derive(size_t n_args, const mp_obj_t *args) {
mp_obj_HDNode_t *o = MP_OBJ_TO_PTR(args[0]);
uint32_t i = mp_obj_get_int_truncated(args[1]);
uint32_t fp = hdnode_fingerprint(&o->hdnode);
bool public = n_args > 2 && args[2] == mp_const_true;
if (!hdnode_private_ckd(&o->hdnode, i)) {
int res;
if (public) {
res = hdnode_public_ckd(&o->hdnode, i);
} else {
if (0 == memcmp(o->hdnode.private_key, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 32)) {
memzero(&o->hdnode, sizeof(o->hdnode));
mp_raise_ValueError("Failed to derive, private key not set");
}
res = hdnode_private_ckd(&o->hdnode, i);
}
if (!res) {
memzero(&o->hdnode, sizeof(o->hdnode));
mp_raise_ValueError("Failed to derive");
}
@ -140,7 +151,7 @@ STATIC mp_obj_t mod_trezorcrypto_HDNode_derive(mp_obj_t self, mp_obj_t index) {
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_HDNode_derive_obj, mod_trezorcrypto_HDNode_derive);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorcrypto_HDNode_derive_obj, 2, 3, mod_trezorcrypto_HDNode_derive);
/// def derive_path(self, path: List[int]) -> None:
/// '''

View File

@ -1,25 +1,45 @@
from typing import *
# extmod/modtrezorconfig/modtrezorconfig.c
def init(self) -> None:
def init() -> None:
'''
Initializes the storage. Must be called before any other method is called from this module!
Initializes the storage. Must be called before any other method is
called from this module!
'''
# extmod/modtrezorconfig/modtrezorconfig.c
def get(app: int, key: int) -> bytes:
def unlock(pin: int, waitcallback: (int, int -> None)) -> bool:
'''
Attempts to unlock the storage with given PIN. Returns True on
success, False on failure.
'''
# extmod/modtrezorconfig/modtrezorconfig.c
def has_pin() -> bool:
'''
Returns True if storage has a configured PIN, False otherwise.
'''
# extmod/modtrezorconfig/modtrezorconfig.c
def change_pin(pin: int, newpin: int, waitcallback: (int, int -> None)) -> bool:
'''
Change PIN. Returns True on success, False on failure.
'''
# extmod/modtrezorconfig/modtrezorconfig.c
def get(app: int, key: int, public: bool=False) -> bytes:
'''
Gets a value of given key for given app (or empty bytes if not set).
'''
# extmod/modtrezorconfig/modtrezorconfig.c
def set(app: int, key: int, value: bytes) -> None:
def set(app: int, key: int, value: bytes, public: bool=False) -> None:
'''
Sets a value of given key for given app.
'''
# extmod/modtrezorconfig/modtrezorconfig.c
def wipe(self) -> None:
def wipe() -> None:
'''
Erases the whole config. Use with caution!
'''

View File

@ -22,7 +22,18 @@ class HDNode:
BIP0032 HD node structure.
'''
def derive(self, index: int) -> None:
def __init__(self,
depth: int,
fingerprint: int,
child_num: int,
chain_code: bytes,
private_key: bytes = None,
public_key: bytes = None,
curve_name: str = None) -> None:
'''
'''
def derive(self, index: int, public: bool=False) -> None:
'''
Derive a BIP0032 child node in place.
'''
@ -82,13 +93,9 @@ class HDNode:
Compute a base58-encoded address string from the HD node.
'''
# extmod/modtrezorcrypto/modtrezorcrypto-bip32.h
class Bip32:
'''
'''
def __init__(self):
def ethereum_pubkeyhash(self) -> bytes:
'''
Compute an Ethereum pubkeyhash (aka address) from the HD node.
'''
def deserialize(self, value: str, version_public: int, version_private: int) -> HDNode:
@ -96,51 +103,69 @@ class Bip32:
Construct a BIP0032 HD node from a base58-serialized value.
'''
def from_seed(self, seed: bytes, curve_name: str) -> HDNode:
def from_seed(seed: bytes, curve_name: str) -> HDNode:
'''
Construct a BIP0032 HD node from a BIP0039 seed value.
'''
# extmod/modtrezorcrypto/modtrezorcrypto-bip39.h
class Bip39:
'''
'''
def __init__(self):
'''
'''
def find_word(self, prefix: str) -> Optional[str]:
def find_word(prefix: str) -> Optional[str]:
'''
Return the first word from the wordlist starting with prefix.
'''
def complete_word(self, prefix: str) -> int:
# extmod/modtrezorcrypto/modtrezorcrypto-bip39.h
def complete_word(prefix: str) -> int:
'''
Return possible 1-letter suffixes for given word prefix.
Result is a bitmask, with 'a' on the lowest bit, 'b' on the second lowest, etc.
'''
def generate(self, strength: int) -> str:
# extmod/modtrezorcrypto/modtrezorcrypto-bip39.h
def generate(strength: int) -> str:
'''
Generate a mnemonic of given strength (128, 160, 192, 224 and 256 bits).
'''
def from_data(self, data: bytes) -> str:
# extmod/modtrezorcrypto/modtrezorcrypto-bip39.h
def from_data(data: bytes) -> str:
'''
Generate a mnemonic from given data (of 16, 20, 24, 28 and 32 bytes).
'''
def check(self, mnemonic: str) -> bool:
# extmod/modtrezorcrypto/modtrezorcrypto-bip39.h
def check(mnemonic: str) -> bool:
'''
Check whether given mnemonic is valid.
'''
def seed(self, mnemonic: str, passphrase: str) -> bytes:
# extmod/modtrezorcrypto/modtrezorcrypto-bip39.h
def seed(mnemonic: str, passphrase: str) -> bytes:
'''
Generate seed from mnemonic and passphrase.
'''
# extmod/modtrezorcrypto/modtrezorcrypto-blake256.h
class Blake256:
'''
Blake256 context.
'''
def __init__(self, data: bytes = None) -> None:
'''
Creates a hash context object.
'''
def update(self, data: bytes) -> None:
'''
Update the hash context with hashed data.
'''
def digest(self) -> bytes:
'''
Returns the digest of hashed data.
'''
# extmod/modtrezorcrypto/modtrezorcrypto-blake2b.h
class Blake2b:
'''
@ -183,116 +208,139 @@ class Blake2s:
Returns the digest of hashed data.
'''
# extmod/modtrezorcrypto/modtrezorcrypto-chacha20poly1305.h
class ChaCha20Poly1305:
'''
ChaCha20Poly1305 context.
'''
def __init__(self, key: bytes, nonce: bytes) -> None:
'''
Initialize the ChaCha20 + Poly1305 context for encryption or decryption
using a 32 byte key and 12 byte nonce as in the RFC 7539 style.
'''
def encrypt(self, data: bytes) -> bytes:
'''
Encrypt data (length of data must be divisible by 64 except for the final value).
'''
def decrypt(self, data: bytes) -> bytes:
'''
Decrypt data (length of data must be divisible by 64 except for the final value).
'''
def auth(self, data: bytes) -> None:
'''
Include authenticated data in the Poly1305 MAC using the RFC 7539
style with 16 byte padding. This must only be called once and prior
to encryption or decryption.
'''
def finish(self) -> bytes:
'''
Compute RFC 7539-style Poly1305 MAC.
'''
# extmod/modtrezorcrypto/modtrezorcrypto-curve25519.h
class Curve25519:
'''
'''
def __init__(self) -> None:
'''
'''
def generate_secret(self) -> bytes:
def generate_secret() -> bytes:
'''
Generate secret key.
'''
def publickey(self, secret_key: bytes) -> bytes:
# extmod/modtrezorcrypto/modtrezorcrypto-curve25519.h
def publickey(secret_key: bytes) -> bytes:
'''
Computes public key from secret key.
'''
def multiply(self, secret_key: bytes, public_key: bytes) -> bytes:
# extmod/modtrezorcrypto/modtrezorcrypto-curve25519.h
def multiply(secret_key: bytes, public_key: bytes) -> bytes:
'''
Multiplies point defined by public_key with scalar defined by secret_key.
Useful for ECDH.
'''
# extmod/modtrezorcrypto/modtrezorcrypto-ed25519.h
class Ed25519:
'''
'''
def __init__(self) -> None:
'''
'''
def generate_secret(self) -> bytes:
def generate_secret() -> bytes:
'''
Generate secret key.
'''
def publickey(self, secret_key: bytes) -> bytes:
# extmod/modtrezorcrypto/modtrezorcrypto-ed25519.h
def publickey(secret_key: bytes) -> bytes:
'''
Computes public key from secret key.
'''
def sign(self, secret_key: bytes, message: bytes) -> bytes:
# extmod/modtrezorcrypto/modtrezorcrypto-ed25519.h
def sign(secret_key: bytes, message: bytes) -> bytes:
'''
Uses secret key to produce the signature of message.
'''
def verify(self, public_key: bytes, signature: bytes, message: bytes) -> bool:
# extmod/modtrezorcrypto/modtrezorcrypto-ed25519.h
def verify(public_key: bytes, signature: bytes, message: bytes) -> bool:
'''
Uses public key to verify the signature of the message.
Returns True on success.
'''
def cosi_combine_publickeys(self, public_keys: List[bytes]) -> bytes:
# extmod/modtrezorcrypto/modtrezorcrypto-ed25519.h
def cosi_combine_publickeys(public_keys: List[bytes]) -> bytes:
'''
Combines a list of public keys used in COSI cosigning scheme.
'''
def cosi_combine_signatures(self, R: bytes, signatures: List[bytes]) -> bytes:
# extmod/modtrezorcrypto/modtrezorcrypto-ed25519.h
def cosi_combine_signatures(R: bytes, signatures: List[bytes]) -> bytes:
'''
Combines a list of signatures used in COSI cosigning scheme.
'''
def cosi_sign(self, secret_key: bytes, message: bytes, nonce: bytes, sigR: bytes, combined_pubkey: bytes) -> bytes:
# extmod/modtrezorcrypto/modtrezorcrypto-ed25519.h
def cosi_sign(secret_key: bytes, message: bytes, nonce: bytes, sigR: bytes, combined_pubkey: bytes) -> bytes:
'''
Produce signature of message using COSI cosigning scheme.
'''
# extmod/modtrezorcrypto/modtrezorcrypto-nist256p1.h
class Nist256p1:
'''
'''
def __init__(self) -> None:
'''
'''
def generate_secret(self) -> bytes:
def generate_secret() -> bytes:
'''
Generate secret key.
'''
def publickey(self, secret_key: bytes, compressed: bool = True) -> bytes:
# extmod/modtrezorcrypto/modtrezorcrypto-nist256p1.h
def publickey(secret_key: bytes, compressed: bool = True) -> bytes:
'''
Computes public key from secret key.
'''
def sign(self, secret_key: bytes, digest: bytes, compressed: bool = True) -> bytes:
# extmod/modtrezorcrypto/modtrezorcrypto-nist256p1.h
def sign(secret_key: bytes, digest: bytes, compressed: bool = True) -> bytes:
'''
Uses secret key to produce the signature of the digest.
'''
def verify(self, public_key: bytes, signature: bytes, digest: bytes) -> bool:
# extmod/modtrezorcrypto/modtrezorcrypto-nist256p1.h
def verify(public_key: bytes, signature: bytes, digest: bytes) -> bool:
'''
Uses public key to verify the signature of the digest.
Returns True on success.
'''
def verify_recover(self, signature: bytes, digest: bytes) -> bytes:
# extmod/modtrezorcrypto/modtrezorcrypto-nist256p1.h
def verify_recover(signature: bytes, digest: bytes) -> bytes:
'''
Uses signature of the digest to verify the digest and recover the public key.
Returns public key on success, None on failure.
'''
def multiply(self, secret_key: bytes, public_key: bytes) -> bytes:
# extmod/modtrezorcrypto/modtrezorcrypto-nist256p1.h
def multiply(secret_key: bytes, public_key: bytes) -> bytes:
'''
Multiplies point defined by public_key with scalar defined by secret_key
Useful for ECDH
Multiplies point defined by public_key with scalar defined by secret_key.
Useful for ECDH.
'''
# extmod/modtrezorcrypto/modtrezorcrypto-pbkdf2.h
@ -317,27 +365,21 @@ class Pbkdf2:
'''
# extmod/modtrezorcrypto/modtrezorcrypto-random.h
class Random:
def uniform(n: int) -> int:
'''
Compute uniform random number from interval 0 ... n - 1.
'''
def __init__(self) -> None:
# extmod/modtrezorcrypto/modtrezorcrypto-random.h
def bytes(len: int) -> bytes:
'''
Generate random bytes sequence of length len.
'''
def uniform(self, n: int) -> int:
# extmod/modtrezorcrypto/modtrezorcrypto-random.h
def shuffle(data: list) -> None:
'''
Compute uniform random number from interval 0 ... n - 1
'''
def bytes(self, len: int) -> bytes:
'''
Generate random bytes sequence of length len
'''
def shuffle(self, data: list) -> None:
'''
Shuffles items of given list (in-place)
Shuffles items of given list (in-place).
'''
# extmod/modtrezorcrypto/modtrezorcrypto-rfc6979.h
@ -378,42 +420,39 @@ class Ripemd160:
'''
# extmod/modtrezorcrypto/modtrezorcrypto-secp256k1.h
class Secp256k1:
'''
'''
def __init__(self) -> None:
'''
'''
def generate_secret(self, ) -> bytes:
def generate_secret() -> bytes:
'''
Generate secret key.
'''
def publickey(self, secret_key: bytes, compressed: bool = True) -> bytes:
# extmod/modtrezorcrypto/modtrezorcrypto-secp256k1.h
def publickey(secret_key: bytes, compressed: bool = True) -> bytes:
'''
Computes public key from secret key.
'''
def sign(self, secret_key: bytes, digest: bytes, compressed: bool = True) -> bytes:
# extmod/modtrezorcrypto/modtrezorcrypto-secp256k1.h
def sign(secret_key: bytes, digest: bytes, compressed: bool = True) -> bytes:
'''
Uses secret key to produce the signature of the digest.
'''
def verify(self, public_key: bytes, signature: bytes, digest: bytes) -> bool:
# extmod/modtrezorcrypto/modtrezorcrypto-secp256k1.h
def verify(public_key: bytes, signature: bytes, digest: bytes) -> bool:
'''
Uses public key to verify the signature of the digest.
Returns True on success.
'''
def verify_recover(self, signature: bytes, digest: bytes) -> bytes:
# extmod/modtrezorcrypto/modtrezorcrypto-secp256k1.h
def verify_recover(signature: bytes, digest: bytes) -> bytes:
'''
Uses signature of the digest to verify the digest and recover the public key.
Returns public key on success, None on failure.
'''
def multiply(self, secret_key: bytes, public_key: bytes) -> bytes:
# extmod/modtrezorcrypto/modtrezorcrypto-secp256k1.h
def multiply(secret_key: bytes, public_key: bytes) -> bytes:
'''
Multiplies point defined by public_key with scalar defined by secret_key.
Useful for ECDH.
@ -523,22 +562,3 @@ class Sha512:
'''
Returns the digest of hashed data.
'''
# extmod/modtrezorcrypto/modtrezorcrypto-ssss.h
class SSSS:
'''
'''
def __init__(self) -> None:
'''
'''
def split(self, m: int, n: int, secret: bytes) -> tuple:
'''
Split secret to (M of N) shares using Shamir's Secret Sharing Scheme.
'''
def combine(self, shares: tuple) -> bytes:
'''
Combine M shares of Shamir's Secret Sharing Scheme into secret.
'''

View File

@ -1,5 +1,87 @@
from typing import *
# extmod/modtrezorio/modtrezorio-flash.h
class FlashOTP:
'''
'''
def __init__(self) -> None:
'''
'''
def FlashOTP.write(self, block: int, offset: int, data: bytes) -> None:
'''
Writes data to OTP flash
'''
def FlashOTP.read(self, block: int, offset: int, data: bytearray) -> None:
'''
Reads data from OTP flash
'''
def FlashOTP.lock(self, block: int) -> None:
'''
Lock OTP flash block
'''
def FlashOTP.is_locked(self, block: int) -> bool:
'''
Is OTP flash block locked?
'''
# extmod/modtrezorio/modtrezorio-hid.h
class HID:
'''
USB HID interface configuration.
'''
def __init__(self,
iface_num: int,
ep_in: int,
ep_out: int,
report_desc: bytes,
subclass: int = 0,
protocol: int = 0,
polling_interval: int = 1,
max_packet_len: int = 64) -> None:
'''
'''
def iface_num(self) -> int:
'''
Returns the configured number of this interface.
'''
def write(self, msg: bytes) -> int:
'''
Sends message using USB HID (device) or UDP (emulator).
'''
# extmod/modtrezorio/modtrezorio-poll.h
def poll(ifaces: Iterable[int], list_ref: List, timeout_us: int) -> bool:
'''
Wait until one of `ifaces` is ready to read or write (using masks
`list_ref`:
`list_ref[0]` - the interface number, including the mask
`list_ref[1]` - for touch event, tuple of (event_type, x_position, y_position)
- for USB read event, received bytes
If timeout occurs, False is returned, True otherwise.
'''
# extmod/modtrezorio/modtrezorio-sbu.h
class SBU:
'''
'''
def __init__(self) -> None:
'''
'''
def set(self, sbu1: bool, sbu2: bool) -> None:
'''
Sets SBU wires to sbu1 and sbu2 values respectively
'''
# extmod/modtrezorio/modtrezorio-sdcard.h
class SDCard:
'''
@ -27,12 +109,94 @@ class SDCard:
def read(self, block_num: int, buf: bytearray) -> bool:
'''
Reads block_num block from the SD card into buf.
Reads blocks starting with block_num from the SD card into buf.
Number of bytes read is length of buf rounded down to multiply of SDCARD_BLOCK_SIZE.
Returns True if in case of success, False otherwise.
'''
def write(self, block_num: int, buf: bytes) -> bool:
'''
Writes block_num block from buf to the SD card.
Writes blocks starting with block_num from buf to the SD card.
Number of bytes written is length of buf rounded down to multiply of SDCARD_BLOCK_SIZE.
Returns True if in case of success, False otherwise.
'''
# extmod/modtrezorio/modtrezorio-usb.h
class USB:
'''
USB device configuration.
'''
def __init__(self,
vendor_id: int,
product_id: int,
release_num: int,
manufacturer: str='',
product: str='',
serial_number: str='',
configuration: str='',
interface: str='') -> None:
'''
'''
def add(self, iface: Union[HID, VCP, WebUSB]) -> None:
'''
Registers passed interface into the USB stack.
'''
def open(self) -> None:
'''
Initializes the USB stack.
'''
def close(self) -> None:
'''
Cleans up the USB stack.
'''
# extmod/modtrezorio/modtrezorio-vcp.h
class VCP:
'''
USB VCP interface configuration.
'''
def __init__(self,
iface_num: int,
data_iface_num: int,
ep_in: int,
ep_out: int,
ep_cmd: int) -> None:
'''
'''
def iface_num(self) -> int:
'''
Returns the configured number of this interface.
'''
# extmod/modtrezorio/modtrezorio-webusb.h
class WebUSB:
'''
USB WebUSB interface configuration.
'''
def __init__(self,
iface_num: int,
ep_in: int,
ep_out: int,
subclass: int = 0,
protocol: int = 0,
polling_interval: int = 1,
max_packet_len: int = 64) -> None:
'''
'''
def iface_num(self) -> int:
'''
Returns the configured number of this interface.
'''
def write(self, msg: bytes) -> int:
'''
Sends message using USB WebUSB (device) or UDP (emulator).
'''

View File

@ -1,83 +0,0 @@
from typing import *
# extmod/modtrezormsg/modtrezormsg.c
class HID:
'''
USB HID interface configuration.
'''
def __init__(self,
iface_num: int,
ep_in: int,
ep_out: int,
report_desc: bytes,
subclass: int = 0,
protocol: int = 0,
polling_interval: int = 1,
max_packet_len: int = 64) -> None:
'''
'''
# extmod/modtrezormsg/modtrezormsg.c
class VCP:
'''
USB VCP interface configuration.
'''
def __init__(self,
iface_num: int,
data_iface_num: int,
ep_in: int,
ep_out: int,
ep_cmd: int) -> None:
'''
'''
# extmod/modtrezormsg/modtrezormsg.c
class USB:
'''
USB device configuration.
'''
def __init__(self,
vendor_id: int,
product_id: int,
release_num: int,
manufacturer_str: str,
product_str: str,
serial_number_str: str,
configuration_str: str = '',
interface_str: str = '') -> None:
'''
'''
# extmod/modtrezormsg/modtrezormsg.c
class Msg:
'''
Interface with USB and touch events.
'''
def __init__(self) -> None:
'''
'''
def init_usb(self, usb_info: USB, usb_ifaces: List[Union[HID, VCP]]) -> None:
'''
Registers passed interfaces and initializes the USB stack.
'''
def deinit_usb(self) -> None:
'''
Cleans up the USB stack
'''
def send(self, iface: int, message: bytes) -> int:
'''
Sends message using USB HID (device) or UDP (emulator).
'''
def select(self, timeout_us: int) -> tuple:
'''
Polls the event queue and returns the event object.
Function returns None if timeout specified in microseconds is reached.
'''

View File

@ -38,10 +38,17 @@ class Display:
The image needs to be in TREZOR Optimized Image Format (TOIF) - full-color mode.
'''
def avatar(self, x: int, y: int, image: bytes, fgcolor: int, bgcolor: int) -> None:
'''
Renders an avatar at position (x,y).
The image needs to be in TREZOR Optimized Image Format (TOIF) - full-color mode.
Image needs to be of exactly AVATAR_IMAGE_SIZE x AVATAR_IMAGE_SIZE pixels size.
'''
def icon(self, x: int, y: int, icon: bytes, fgcolor: int, bgcolor: int) -> None:
'''
Renders an icon at position (x,y), fgcolor is used as foreground color, bgcolor as background.
The image needs to be in TREZOR Optimized Image Format (TOIF) - gray-scale mode.
The icon needs to be in TREZOR Optimized Image Format (TOIF) - gray-scale mode.
'''
def print(self, text: str) -> None:
@ -49,19 +56,19 @@ class Display:
Renders text using 5x8 bitmap font (using special text mode).
'''
def text(self, x: int, y: int, text: str, font: int, fgcolor: int, bgcolor: int) -> None:
def text(self, x: int, y: int, text: str, font: int, fgcolor: int, bgcolor: int, minwidth: int=None) -> None:
'''
Renders left-aligned text at position (x,y) where x is left position and y is baseline.
Font font is used for rendering, fgcolor is used as foreground color, bgcolor as background.
'''
def text_center(self, x: int, y: int, text: str, font: int, fgcolor: int, bgcolor: int) -> None:
def text_center(self, x: int, y: int, text: str, font: int, fgcolor: int, bgcolor: int, minwidth: int=None) -> None:
'''
Renders text centered at position (x,y) where x is text center and y is baseline.
Font font is used for rendering, fgcolor is used as foreground color, bgcolor as background.
'''
def text_right(self, x: int, y: int, text: str, font: int, fgcolor: int, bgcolor: int) -> None:
def text_right(self, x: int, y: int, text: str, font: int, fgcolor: int, bgcolor: int, minwidth: int=None) -> None:
'''
Renders right-aligned text at position (x,y) where x is right position and y is baseline.
Font font is used for rendering, fgcolor is used as foreground color, bgcolor as background.

View File

@ -1,5 +1,14 @@
from typing import *
# extmod/modtrezorutils/modtrezorutils.c
def consteq(sec: bytes, pub: bytes) -> bool:
'''
Compares the private information in `sec` with public, user-provided
information in `pub`. Runs in constant time, corresponding to a length
of `pub`. Can access memory behind valid length of `sec`, caller is
expected to avoid any invalid memory access.
'''
# extmod/modtrezorutils/modtrezorutils.c
def memcpy(dst: bytearray, dst_ofs: int,
src: bytearray, src_ofs: int,

View File

@ -1,3 +1,7 @@
import micropython
import gc
from uctypes import bytes_at, bytearray_at
from trezor import log
from trezor import loop
from trezor.utils import unimport
@ -5,62 +9,50 @@ from trezor.wire import register, protobuf_workflow
from trezor.messages.wire_types import \
DebugLinkDecision, DebugLinkGetState, DebugLinkStop, \
DebugLinkMemoryRead, DebugLinkMemoryWrite, DebugLinkFlashErase
@unimport
async def dispatch_DebugLinkDecision(ctx, msg):
from trezor.ui.confirm import CONFIRMED, CANCELLED
from apps.common.confirm import signal
signal.send(CONFIRMED if msg.yes_no else CANCELLED)
@unimport
async def dispatch_DebugLinkGetState(ctx, msg):
from trezor.messages.DebugLinkMemory import DebugLinkMemory
from trezor.messages.DebugLinkState import DebugLinkState
from trezor.ui.confirm import CONFIRMED, CANCELLED
from apps.common.confirm import signal
from apps.common import storage
from apps.management import reset_device
async def dispatch_DebugLinkDecision(ctx, msg):
signal.send(CONFIRMED if msg.yes_no else CANCELLED)
async def dispatch_DebugLinkGetState(ctx, msg):
m = DebugLinkState()
m.mnemonic = storage.get_mnemonic()
m.passphrase_protection = storage.has_passphrase()
m.reset_entropy = reset_device.internal_entropy
m.reset_word = reset_device.current_word
return m
@unimport
async def dispatch_DebugLinkStop(ctx, msg):
pass
@unimport
async def dispatch_DebugLinkMemoryRead(ctx, msg):
from trezor.messages.DebugLinkMemory import DebugLinkMemory
from uctypes import bytes_at
m = DebugLinkMemory()
m.memory = bytes_at(msg.address, msg.length)
return m
@unimport
async def dispatch_DebugLinkMemoryWrite(ctx, msg):
from uctypes import bytearray_at
l = len(msg.memory)
data = bytearray_at(msg.address, l)
data[0:l] = msg.memory
@unimport
async def dispatch_DebugLinkFlashErase(ctx, msg):
# TODO: erase(msg.sector)
pass
async def memory_stats(interval):
import micropython
import gc
sleep = loop.sleep(interval * 1000 * 1000)
while True:
micropython.mem_info()

View File

@ -1,24 +1,20 @@
from micropython import const
from trezor import wire, ui
from trezor import ui
async def layout_get_address(ctx, msg):
from trezor.messages.Address import Address
from trezor.messages.InputScriptType import SPENDWITNESS
from trezor.messages.FailureType import ProcessError
from ..common import coins
from ..common import seed
from ..wallet.sign_tx import addresses
if msg.multisig:
raise wire.FailureError(ProcessError, 'GetAddress.multisig is unsupported')
address_n = msg.address_n or ()
coin_name = msg.coin_name or 'Bitcoin'
coin = coins.by_name(coin_name)
node = await seed.derive_node(ctx, address_n)
address = addresses.get_address(msg.script_type, coin, node)
address = addresses.get_address(msg.script_type, coin, node, msg.multisig)
if msg.show_display:
while True:

View File

@ -21,6 +21,10 @@ async def sign_tx(ctx, msg):
raise wire.FailureError(*e.args)
except signing.AddressError as e:
raise wire.FailureError(*e.args)
except signing.ScriptsError as e:
raise wire.FailureError(*e.args)
except signing.Bip143Error as e:
raise wire.FailureError(*e.args)
if req.__qualname__ == 'TxRequest':
if req.request_type == TXFINISHED:
break

View File

@ -8,6 +8,9 @@ from trezor.messages.CoinType import CoinType
from trezor.messages import FailureType
from trezor.messages import InputScriptType
from apps.wallet.sign_tx.scripts import *
from apps.wallet.sign_tx.multisig import *
# supported witness version for bech32 addresses
_BECH32_WITVER = const(0x00)
@ -16,21 +19,50 @@ class AddressError(Exception):
pass
def get_address(script_type: InputScriptType, coin: CoinType, node) -> str:
def get_address(script_type: InputScriptType, coin: CoinType, node, multisig=None) -> str:
if script_type == InputScriptType.SPENDADDRESS: # p2pkh
if script_type == InputScriptType.SPENDADDRESS or script_type == InputScriptType.SPENDMULTISIG:
if multisig: # p2sh multisig
pubkey = node.public_key()
index = multisig_pubkey_index(multisig, pubkey)
if index is None:
raise AddressError(FailureType.ProcessError,
'Public key not found')
if coin.address_type_p2sh is None:
raise AddressError(FailureType.ProcessError,
'Multisig not enabled on this coin')
pubkeys = multisig_get_pubkeys(multisig)
return address_multisig_p2sh(pubkeys, multisig.m, coin.address_type_p2sh)
if script_type == InputScriptType.SPENDMULTISIG:
raise AddressError(FailureType.ProcessError,
'Multisig details required')
# p2pkh
return node.address(coin.address_type)
elif script_type == InputScriptType.SPENDWITNESS: # native p2wpkh
elif script_type == InputScriptType.SPENDWITNESS: # native p2wpkh or native p2wsh
if not coin.segwit or not coin.bech32_prefix:
raise AddressError(FailureType.ProcessError,
'Segwit not enabled on this coin')
# native p2wsh multisig
if multisig is not None:
pubkeys = multisig_get_pubkeys(multisig)
return address_multisig_p2wsh(pubkeys, multisig.m, coin.bech32_prefix)
# native p2wpkh
return address_p2wpkh(node.public_key(), coin.bech32_prefix)
elif script_type == InputScriptType.SPENDP2SHWITNESS: # p2wpkh using p2sh
if not coin.segwit or not coin.address_type_p2sh:
elif script_type == InputScriptType.SPENDP2SHWITNESS: # p2wpkh or p2wsh nested in p2sh
if not coin.segwit or coin.address_type_p2sh is None:
raise AddressError(FailureType.ProcessError,
'Segwit not enabled on this coin')
# p2wsh multisig nested in p2sh
if multisig is not None:
pubkeys = multisig_get_pubkeys(multisig)
return address_multisig_p2wsh_in_p2sh(pubkeys, multisig.m, coin.address_type_p2sh)
# p2wpkh nested in p2sh
return address_p2wpkh_in_p2sh(node.public_key(), coin.address_type_p2sh)
else:
@ -38,21 +70,51 @@ def get_address(script_type: InputScriptType, coin: CoinType, node) -> str:
'Invalid script type')
def address_p2wpkh_in_p2sh(pubkey: bytes, addrtype: int) -> str:
def address_multisig_p2sh(pubkeys: bytes, m: int, addrtype: int):
if addrtype is None:
raise AddressError(FailureType.ProcessError,
'Multisig not enabled on this coin')
redeem_script = output_script_multisig(pubkeys, m)
redeem_script_hash = sha256_ripemd160_digest(redeem_script)
return address_p2sh(redeem_script_hash, addrtype)
def address_multisig_p2wsh_in_p2sh(pubkeys: bytes, m: int, addrtype: int):
if addrtype is None:
raise AddressError(FailureType.ProcessError,
'Multisig not enabled on this coin')
witness_script = output_script_multisig(pubkeys, m)
witness_script_hash = sha256(witness_script).digest()
return address_p2wsh_in_p2sh(witness_script_hash, addrtype)
def address_multisig_p2wsh(pubkeys: bytes, m: int, hrp: str):
if not hrp:
raise AddressError(FailureType.ProcessError,
'Multisig not enabled on this coin')
witness_script = output_script_multisig(pubkeys, m)
witness_script_hash = sha256(witness_script).digest()
return address_p2wsh(witness_script_hash, hrp)
def address_p2sh(redeem_script_hash: bytes, addrtype: int) -> str:
s = bytearray(21)
s[0] = addrtype
s[1:21] = address_p2wpkh_in_p2sh_raw(pubkey)
s[1:21] = redeem_script_hash
return base58.encode_check(bytes(s))
def address_p2wpkh_in_p2sh_raw(pubkey: bytes) -> bytes:
s = bytearray(22)
s[0] = 0x00 # OP_0
s[1] = 0x14 # pushing 20 bytes
s[2:22] = ecdsa_hash_pubkey(pubkey)
h = sha256(s).digest()
h = ripemd160(h).digest()
return h
def address_p2wpkh_in_p2sh(pubkey: bytes, addrtype: int) -> str:
pubkey_hash = ecdsa_hash_pubkey(pubkey)
redeem_script = output_script_native_p2wpkh_or_p2wsh(pubkey_hash)
redeem_script_hash = sha256_ripemd160_digest(redeem_script)
return address_p2sh(redeem_script_hash, addrtype)
def address_p2wsh_in_p2sh(witness_script_hash: bytes, addrtype: int) -> str:
redeem_script = output_script_native_p2wpkh_or_p2wsh(witness_script_hash)
redeem_script_hash = sha256_ripemd160_digest(redeem_script)
return address_p2sh(redeem_script_hash, addrtype)
def address_p2wpkh(pubkey: bytes, hrp: str) -> str:
@ -64,6 +126,14 @@ def address_p2wpkh(pubkey: bytes, hrp: str) -> str:
return address
def address_p2wsh(witness_script_hash: bytes, hrp: str) -> str:
address = bech32.encode(hrp, _BECH32_WITVER, witness_script_hash)
if address is None:
raise AddressError(FailureType.ProcessError,
'Invalid address')
return address
def decode_bech32_address(prefix: str, address: str) -> bytes:
witver, raw = bech32.decode(prefix, address)
if witver != _BECH32_WITVER:

View File

@ -0,0 +1,88 @@
from trezor.crypto.hashlib import sha256
from trezor.crypto import bip32
from trezor.messages.MultisigRedeemScriptType import MultisigRedeemScriptType
from trezor.messages.HDNodePathType import HDNodePathType
from apps.wallet.sign_tx.writers import *
from apps.common.hash_writer import *
class MultisigFingerprint:
def __init__(self):
self.fingerprint = None # multisig fingerprint bytes
self.mismatch = False # flag if multisig input fingerprints are equal
def add(self, multisig: MultisigRedeemScriptType):
fp = multisig_fingerprint(multisig)
assert fp is not None
if self.fingerprint is None:
self.fingerprint = fp
elif self.fingerprint != fp:
self.mismatch = True
def matches(self, multisig: MultisigRedeemScriptType):
fp = multisig_fingerprint(multisig)
assert fp is not None
if self.mismatch is False and self.fingerprint == fp:
return True
else:
return False
def multisig_fingerprint(multisig: MultisigRedeemScriptType) -> bytes:
pubkeys = multisig.pubkeys
m = multisig.m
n = len(pubkeys)
if n < 1 or n > 15 or m < 1 or m > 15:
raise SigningError(FailureType.DataError,
'Invalid multisig parameters')
for hd in pubkeys:
d = hd.node
if len(d.public_key) != 33 or len(d.chain_code) != 32:
raise SigningError(FailureType.DataError,
'Invalid multisig parameters')
# casting to bytes(), sorting on bytearray() is not supported in MicroPython
pubkeys = sorted(pubkeys, key=lambda hd: bytes(hd.node.public_key))
h = HashWriter(sha256)
write_uint32(h, m)
write_uint32(h, n)
for hd in pubkeys:
d = hd.node
write_uint32(h, d.depth)
write_uint32(h, d.fingerprint)
write_uint32(h, d.child_num)
write_bytes(h, d.chain_code)
write_bytes(h, d.public_key)
return h.get_digest()
def multisig_pubkey_index(multisig: MultisigRedeemScriptType, pubkey: bytes) -> int:
for i, hd in enumerate(multisig.pubkeys):
if multisig_get_pubkey(hd) == pubkey:
return i
raise SigningError(FailureType.DataError,
'Pubkey not found in multisig script')
def multisig_get_pubkey(hd: HDNodePathType) -> bytes:
p = hd.address_n
n = hd.node
node = bip32.HDNode(
depth=n.depth,
fingerprint=n.fingerprint,
child_num=n.child_num,
chain_code=n.chain_code,
public_key=n.public_key)
for i in p:
node.derive(i, True)
return node.public_key()
def multisig_get_pubkeys(multisig: MultisigRedeemScriptType):
return [multisig_get_pubkey(hd) for hd in multisig.pubkeys]

View File

@ -1,20 +1,21 @@
from trezor.crypto.hashlib import ripemd160, sha256
from apps.wallet.sign_tx.multisig import multisig_get_pubkeys
from apps.wallet.sign_tx.writers import *
# TX Scripts
class ScriptsError(ValueError):
pass
# P2PKH, P2SH
# ===
# https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki
# -------------------------- First gen --------------------------
# =============== P2PK ===============
# obsolete
# =============== P2PKH ===============
def input_script_p2pkh_or_p2sh(pubkey: bytes, signature: bytes, sighash: int) -> bytearray:
w = bytearray_with_cap(5 + len(signature) + 1 + 5 + len(pubkey))
append_signature_and_pubkey(w, pubkey, signature, sighash)
append_signature(w, signature, sighash)
append_pubkey(w, pubkey)
return w
@ -29,13 +30,9 @@ def output_script_p2pkh(pubkeyhash: bytes) -> bytearray:
return s
# =============== P2SH ===============
# see https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki
# input script (scriptSig) is the same as input_script_p2pkh_or_p2sh
# output script (scriptPubKey) is A9 14 <scripthash> 87
def output_script_p2sh(scripthash: bytes) -> bytearray:
# A9 14 <scripthash> 87
s = bytearray(23)
s[0] = 0xA9 # OP_HASH_160
s[1] = 0x14 # pushing 20 bytes
@ -44,22 +41,28 @@ def output_script_p2sh(scripthash: bytes) -> bytearray:
return s
# -------------------------- SegWit --------------------------
# SegWit: Native P2WPKH or P2WSH
# ===
# https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#p2wpkh
# https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#p2wsh
#
# P2WPKH (Pay-to-Witness-Public-Key-Hash) is the segwit native P2PKH.
# Not backwards compatible.
#
# P2WSH (Pay-to-Witness-Script-Hash) is segwit native P2SH.
# Not backwards compatible.
# =============== Native P2WPKH ===============
# see https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#p2wpkh
# P2WPKH (Pay-to-Witness-Public-Key-Hash) is the segwit native P2PKH
# not backwards compatible
# input script is completely replaced by the witness and therefore empty
def input_script_native_p2wpkh_or_p2wsh() -> bytearray:
# Completely replaced by the witness and therefore empty.
return bytearray(0)
# output script is either:
def output_script_native_p2wpkh_or_p2wsh(witprog: bytes) -> bytearray:
# Either:
# 00 14 <20-byte-key-hash>
# 00 20 <32-byte-script-hash>
def output_script_native_p2wpkh_or_p2wsh(witprog: bytes) -> bytearray:
w = bytearray_with_cap(3 + len(witprog))
w.append(0x00) # witness version byte
w.append(len(witprog)) # pub key hash length is 20 (P2WPKH) or 32 (P2WSH) bytes
@ -67,39 +70,139 @@ def output_script_native_p2wpkh_or_p2wsh(witprog: bytes) -> bytearray:
return w
# =============== Native P2WPKH nested in P2SH ===============
# P2WPKH is nested in P2SH to be backwards compatible
# see https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#witness-program
# SegWit: P2WPKH nested in P2SH
# ===
# https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#witness-program
#
# P2WPKH is nested in P2SH to be backwards compatible.
# Uses normal P2SH output scripts.
# input script (scriptSig) is 16 00 14 <pubkeyhash>
# signature is moved to the witness
def input_script_p2wpkh_in_p2sh(pubkeyhash: bytes) -> bytearray:
# 16 00 14 <pubkeyhash>
# Signature is moved to the witness.
w = bytearray_with_cap(3 + len(pubkeyhash))
w.append(0x16) # 0x16 - length of the redeemScript
w.append(0x16) # length of the data
w.append(0x00) # witness version byte
w.append(0x14) # P2WPKH witness program (pub key hash length)
write_bytes(w, pubkeyhash) # pub key hash
return w
# output script (scriptPubKey) is A9 14 <scripthash> 87
# which is same as the output_script_p2sh
# SegWit: P2WSH nested in P2SH
# ===
# https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#p2wsh-nested-in-bip16-p2sh
#
# P2WSH is nested in P2SH to be backwards compatible.
# Uses normal P2SH output scripts.
# =============== Native P2WSH ===============
# see https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#p2wsh
# P2WSH (Pay-to-Witness-Script-Hash) is segwit native P2SH
# not backwards compatible
def input_script_p2wsh_in_p2sh(script_hash: bytes) -> bytearray:
# 22 00 20 <redeem script hash>
# Signature is moved to the witness.
# input script is completely replaced by the witness and therefore empty
# same as input_script_native_p2wpkh_or_p2wsh
if len(script_hash) != 32:
raise ScriptsError('Redeem script hash should be 32 bytes long')
# output script consists of 00 20 <32-byte-key-hash>
# same as output_script_native_p2wpkh_or_p2wsh (only different length)
w = bytearray_with_cap(3 + len(script_hash))
w.append(0x22) # length of the data
w.append(0x00) # witness version byte
w.append(0x20) # P2WSH witness program (redeem script hash length)
write_bytes(w, script_hash)
return w
# -------------------------- Others --------------------------
# SegWit: Witness getters
# ===
def witness_p2wpkh(signature: bytes, pubkey: bytes, sighash: int):
w = bytearray_with_cap(1 + 5 + len(signature) + 1 + 5 + len(pubkey))
write_varint(w, 0x02) # num of segwit items, in P2WPKH it's always 2
append_signature(w, signature, sighash)
append_pubkey(w, pubkey)
return w
def witness_p2wsh(multisig: MultisigRedeemScriptType, signature: bytes, signature_index: int, sighash: int):
signatures = multisig.signatures # other signatures
if len(signatures[signature_index]) > 0:
raise ScriptsError('Invalid multisig parameters')
signatures[signature_index] = signature # our signature
# filter empty
signatures = [s for s in multisig.signatures if len(s) > 0]
# witness program + signatures + redeem script
num_of_witness_items = 1 + len(signatures) + 1
w = bytearray()
write_varint(w, num_of_witness_items)
write_varint(w, 0) # version 0 witness program
for s in signatures:
append_signature(w, s, sighash) # size of the witness included
# redeem script
pubkeys = multisig_get_pubkeys(multisig)
redeem_script = output_script_multisig(pubkeys, multisig.m)
write_varint(w, len(redeem_script))
write_bytes(w, redeem_script)
return w
# Multisig
# ===
#
# Used either as P2SH, P2WSH, or P2WSH nested in P2SH.
def input_script_multisig(multisig: MultisigRedeemScriptType, signature: bytes, signature_index: int, sighash: int):
signatures = multisig.signatures # other signatures
if len(signatures[signature_index]) > 0:
raise ScriptsError('Invalid multisig parameters')
signatures[signature_index] = signature # our signature
w = bytearray()
# Starts with OP_FALSE because of an old OP_CHECKMULTISIG bug, which
# consumes one additional item on the stack:
# https://bitcoin.org/en/developer-guide#standard-transactions
w.append(0x00)
for s in signatures:
if len(s):
append_signature(w, s, sighash)
# redeem script
pubkeys = multisig_get_pubkeys(multisig)
redeem_script = output_script_multisig(pubkeys, multisig.m)
write_op_push(w, len(redeem_script))
write_bytes(w, redeem_script)
return w
def output_script_multisig(pubkeys, m: int) -> bytearray:
n = len(pubkeys)
if n < 1 or n > 15 or m < 1 or m > 15:
raise ScriptsError('Invalid multisig parameters')
for pubkey in pubkeys:
if len(pubkey) != 33:
raise ScriptsError('Invalid multisig parameters')
w = bytearray()
w.append(0x50 + m) # numbers 1 to 16 are pushed as 0x50 + value
for p in pubkeys:
append_pubkey(w, p)
w.append(0x50 + n)
w.append(0xAE) # OP_CHECKMULTISIG
return w
# OP_RETURN
# ===
# === OP_RETURN script
def output_script_paytoopreturn(data: bytes) -> bytearray:
w = bytearray_with_cap(1 + 5 + len(data))
@ -109,12 +212,24 @@ def output_script_paytoopreturn(data: bytes) -> bytearray:
return w
# === helpers
# Helpers
# ===
def append_signature_and_pubkey(w: bytearray, pubkey: bytes, signature: bytes, sighash: int) -> bytearray:
def append_signature(w: bytearray, signature: bytes, sighash: int) -> bytearray:
write_op_push(w, len(signature) + 1)
write_bytes(w, signature)
w.append(sighash)
return w
def append_pubkey(w: bytearray, pubkey: bytes) -> bytearray:
write_op_push(w, len(pubkey))
write_bytes(w, pubkey)
return w
def sha256_ripemd160_digest(b: bytes) -> bytes:
h = sha256(b).digest()
h = ripemd160(h).digest()
return h

View File

@ -3,6 +3,8 @@ from trezor.messages.SignTx import SignTx
from trezor.messages import InputScriptType, FailureType
from apps.wallet.sign_tx.writers import *
from apps.wallet.sign_tx.scripts import output_script_p2pkh, output_script_multisig
from apps.wallet.sign_tx.multisig import multisig_get_pubkeys
from apps.common.hash_writer import HashWriter
@ -58,22 +60,21 @@ class Bip143:
return get_tx_hash(h_preimage, True)
# this not redeemScript nor scriptPubKey
# for P2WPKH this is always 0x1976a914{20-byte-pubkey-hash}88ac
# see https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki#specification
# item 5 for details
def derive_script_code(self, txi: TxInputType, pubkeyhash: bytes) -> bytearray:
# p2wpkh in p2sh or native p2wpkh
if txi.multisig:
return output_script_multisig(multisig_get_pubkeys(txi.multisig), txi.multisig.m)
p2pkh = (txi.script_type == InputScriptType.SPENDWITNESS or
txi.script_type == InputScriptType.SPENDP2SHWITNESS or
txi.script_type == InputScriptType.SPENDADDRESS)
if p2pkh:
s = bytearray(25)
s[0] = 0x76 # OP_DUP
s[1] = 0xA9 # OP_HASH_160
s[2] = 0x14 # pushing 20 bytes
s[3:23] = pubkeyhash
s[23] = 0x88 # OP_EQUALVERIFY
s[24] = 0xAC # OP_CHECKSIG
return s
# for p2wpkh in p2sh or native p2wpkh
# the scriptCode is a classic p2pkh
return output_script_p2pkh(pubkeyhash)
else:
raise Bip143Error(FailureType.DataError,
'Unknown input script type for bip143 script code')

View File

@ -1,22 +1,21 @@
from micropython import const
from trezor.crypto.hashlib import sha256
from trezor.crypto import base58, bip32, der
from trezor.crypto.curve import secp256k1
from trezor.crypto import base58, der
from trezor.crypto.hashlib import sha256
from trezor.messages.TxRequestSerializedType import TxRequestSerializedType
from trezor.messages.TxRequestDetailsType import TxRequestDetailsType
from trezor.messages import OutputScriptType
from trezor.messages.TxRequestDetailsType import TxRequestDetailsType
from trezor.messages.TxRequestSerializedType import TxRequestSerializedType
from apps.common import address_type
from apps.common import coins
from apps.common import address_type, coins
from apps.common.hash_writer import HashWriter
from apps.wallet.sign_tx.addresses import *
from apps.wallet.sign_tx.helpers import *
from apps.wallet.sign_tx.segwit_bip143 import *
from apps.wallet.sign_tx.scripts import *
from apps.wallet.sign_tx.writers import *
from apps.wallet.sign_tx.segwit_bip143 import *
from apps.wallet.sign_tx.tx_weight_calculator import *
from apps.common.hash_writer import HashWriter
from apps.wallet.sign_tx.writers import *
# the number of bip32 levels used in a wallet (chain and address)
_BIP32_WALLET_DEPTH = const(2)
@ -44,20 +43,17 @@ class SigningError(ValueError):
# - check inputs, previous transactions, and outputs
# - ask for confirmations
# - check fee
async def check_tx_fee(tx: SignTx, root):
async def check_tx_fee(tx: SignTx, root: bip32.HDNode):
coin = coins.by_name(tx.coin_name)
# h_first is used to make sure the inputs and outputs streamed in Phase 1
# are the same as in Phase 2. it is thus not required to fully hash the
# tx, as the SignTx info is streamed only once
h_first = HashWriter(sha256) # not a real tx hash
bip143 = Bip143()
weight = TxWeightCalculator(tx.inputs_count, tx.outputs_count)
txo_bin = TxOutputBinType()
tx_req = TxRequest()
tx_req.details = TxRequestDetailsType()
bip143 = Bip143() # bip143 transaction hashing
multifp = MultisigFingerprint() # control checksum of multisig inputs
weight = TxWeightCalculator(tx.inputs_count, tx.outputs_count)
total_in = 0 # sum of input amounts
segwit_in = 0 # sum of segwit input amounts
@ -66,28 +62,25 @@ async def check_tx_fee(tx: SignTx, root):
wallet_path = [] # common prefix of input paths
segwit = {} # dict of booleans stating if input is segwit
# output structures
txo_bin = TxOutputBinType()
tx_req = TxRequest()
tx_req.details = TxRequestDetailsType()
for i in range(tx.inputs_count):
# STAGE_REQUEST_1_INPUT
txi = await request_tx_input(tx_req, i)
wallet_path = input_extract_wallet_path(txi, wallet_path)
write_tx_input_check(h_first, txi)
weight.add_input(txi)
bip143.add_prevouts(txi)
bip143.add_prevouts(txi) # all inputs are included (non-segwit as well)
bip143.add_sequence(txi)
is_segwit = (txi.script_type == InputScriptType.SPENDWITNESS or
txi.script_type == InputScriptType.SPENDP2SHWITNESS)
if coin.force_bip143:
is_bip143 = (txi.script_type == InputScriptType.SPENDADDRESS)
if not is_bip143:
raise SigningError(FailureType.DataError,
'Wrong input script type')
if not txi.amount:
raise SigningError(FailureType.DataError,
'BIP 143 input without amount')
segwit[i] = False
segwit_in += txi.amount
total_in += txi.amount
elif is_segwit:
if txi.multisig:
multifp.add(txi.multisig)
if txi.script_type in (InputScriptType.SPENDWITNESS,
InputScriptType.SPENDP2SHWITNESS):
if not coin.segwit:
raise SigningError(FailureType.DataError,
'Segwit not enabled on this coin')
@ -97,10 +90,21 @@ async def check_tx_fee(tx: SignTx, root):
segwit[i] = True
segwit_in += txi.amount
total_in += txi.amount
elif txi.script_type == InputScriptType.SPENDADDRESS:
elif txi.script_type in (InputScriptType.SPENDADDRESS,
InputScriptType.SPENDMULTISIG):
if coin.force_bip143:
if not txi.amount:
raise SigningError(FailureType.DataError,
'BIP 143 input without amount')
segwit[i] = False
segwit_in += txi.amount
total_in += txi.amount
else:
segwit[i] = False
total_in += await get_prevtx_output_value(
tx_req, txi.prev_hash, txi.prev_index)
else:
raise SigningError(FailureType.DataError,
'Wrong input script type')
@ -111,14 +115,14 @@ async def check_tx_fee(tx: SignTx, root):
txo_bin.amount = txo.amount
txo_bin.script_pubkey = output_derive_script(txo, coin, root)
weight.add_output(txo_bin.script_pubkey)
if output_is_change(txo, wallet_path, segwit_in):
if change_out != 0:
raise SigningError(FailureType.ProcessError,
'Only one change output is valid')
if change_out == 0 and is_change(txo, wallet_path, segwit_in, multifp):
# output is change and does not need confirmation
change_out = txo.amount
elif not await confirm_output(txo, coin):
raise SigningError(FailureType.ActionCancelled,
'Output cancelled')
write_tx_output(h_first, txo_bin)
bip143.add_output(txo_bin)
total_out += txo_bin.amount
@ -141,8 +145,7 @@ async def check_tx_fee(tx: SignTx, root):
return h_first, bip143, segwit, total_in, wallet_path
async def sign_tx(tx: SignTx, root):
async def sign_tx(tx: SignTx, root: bip32.HDNode):
tx = sanitize_sign_tx(tx)
# Phase 1
@ -171,7 +174,8 @@ async def sign_tx(tx: SignTx, root):
txi_sign = await request_tx_input(tx_req, i_sign)
input_check_wallet_path(txi_sign, wallet_path)
is_bip143 = (txi_sign.script_type == InputScriptType.SPENDADDRESS)
is_bip143 = (txi_sign.script_type == InputScriptType.SPENDADDRESS or
txi_sign.script_type == InputScriptType.SPENDMULTISIG)
if not is_bip143 or txi_sign.amount > authorized_in:
raise SigningError(FailureType.ProcessError,
'Transaction has changed during signing')
@ -182,6 +186,10 @@ async def sign_tx(tx: SignTx, root):
bip143_hash = bip143.preimage_hash(
tx, txi_sign, ecdsa_hash_pubkey(key_sign_pub), get_hash_type(coin))
# if multisig, check if singing with a key that is included in multisig
if txi_sign.multisig:
multisig_pubkey_index(txi_sign.multisig, key_sign_pub)
signature = ecdsa_sign(key_sign, bip143_hash)
tx_ser.signature_index = i_sign
tx_ser.signature = signature
@ -239,8 +247,18 @@ async def sign_tx(tx: SignTx, root):
txi_sign = txi
key_sign = node_derive(root, txi.address_n)
key_sign_pub = key_sign.public_key()
# for the signing process the script_sig is equal
# to the previous tx's scriptPubKey (P2PKH) or a redeem script (P2SH)
if txi_sign.script_type == InputScriptType.SPENDMULTISIG:
txi_sign.script_sig = output_script_multisig(
multisig_get_pubkeys(txi_sign.multisig),
txi_sign.multisig.m)
elif txi_sign.script_type == InputScriptType.SPENDADDRESS:
txi_sign.script_sig = output_script_p2pkh(
ecdsa_hash_pubkey(key_sign_pub))
else:
raise SigningError(FailureType.ProcessError,
'Unknown transaction type')
else:
txi.script_sig = bytes()
write_tx_input(h_sign, txi)
@ -264,6 +282,10 @@ async def sign_tx(tx: SignTx, root):
raise SigningError(FailureType.ProcessError,
'Transaction has changed during signing')
# if multisig, check if singing with a key that is included in multisig
if txi_sign.multisig:
multisig_pubkey_index(txi_sign.multisig, key_sign_pub)
# compute the signature from the tx digest
signature = ecdsa_sign(key_sign, get_tx_hash(h_sign, True))
tx_ser.signature_index = i_sign
@ -321,7 +343,12 @@ async def sign_tx(tx: SignTx, root):
tx, txi, ecdsa_hash_pubkey(key_sign_pub), get_hash_type(coin))
signature = ecdsa_sign(key_sign, bip143_hash)
witness = get_p2wpkh_witness(coin, signature, key_sign_pub)
if txi.multisig:
# find out place of our signature based on the pubkey
signature_index = multisig_pubkey_index(txi.multisig, key_sign_pub)
witness = witness_p2wsh(txi.multisig, signature, signature_index, get_hash_type(coin))
else:
witness = witness_p2wpkh(signature, key_sign_pub, get_hash_type(coin))
tx_ser.serialized_tx = witness
tx_ser.signature_index = i
@ -392,7 +419,7 @@ def get_hash_type(coin: CoinType) -> int:
return hashtype
def get_tx_header(tx: SignTx, segwit=False):
def get_tx_header(tx: SignTx, segwit: bool = False):
w_txi = bytearray()
write_uint32(w_txi, tx.version)
if segwit:
@ -402,26 +429,21 @@ def get_tx_header(tx: SignTx, segwit=False):
return w_txi
def get_p2wpkh_witness(coin: CoinType, signature: bytes, pubkey: bytes):
w = bytearray_with_cap(1 + 5 + len(signature) + 1 + 5 + len(pubkey))
write_varint(w, 0x02) # num of segwit items, in P2WPKH it's always 2
append_signature_and_pubkey(w, pubkey, signature, get_hash_type(coin))
return w
# TX Outputs
# ===
def output_derive_script(o: TxOutputType, coin: CoinType, root) -> bytes:
def output_derive_script(o: TxOutputType, coin: CoinType, root: bip32.HDNode) -> bytes:
if o.script_type == OutputScriptType.PAYTOOPRETURN:
# op_return output
if o.amount != 0:
raise SigningError(FailureType.DataError,
'OP_RETURN output with non-zero amount')
return output_script_paytoopreturn(o.op_return_data)
if o.address_n: # change output
if o.address_n:
# change output
if o.address:
raise SigningError(FailureType.DataError, 'Address in change output')
o.address = get_address_for_change(o, coin, root)
@ -429,24 +451,27 @@ def output_derive_script(o: TxOutputType, coin: CoinType, root) -> bytes:
if not o.address:
raise SigningError(FailureType.DataError, 'Missing address')
if coin.bech32_prefix and o.address.startswith(coin.bech32_prefix): # p2wpkh or p2wsh
if coin.bech32_prefix and o.address.startswith(coin.bech32_prefix):
# p2wpkh or p2wsh
witprog = decode_bech32_address(coin.bech32_prefix, o.address)
return output_script_native_p2wpkh_or_p2wsh(witprog)
raw_address = base58.decode_check(o.address)
if address_type.check(coin.address_type, raw_address): # p2pkh
if address_type.check(coin.address_type, raw_address):
# p2pkh
pubkeyhash = address_type.strip(coin.address_type, raw_address)
return output_script_p2pkh(pubkeyhash)
elif address_type.check(coin.address_type_p2sh, raw_address): # p2sh
elif address_type.check(coin.address_type_p2sh, raw_address):
# p2sh
scripthash = address_type.strip(coin.address_type_p2sh, raw_address)
return output_script_p2sh(scripthash)
raise SigningError(FailureType.DataError, 'Invalid address type')
def get_address_for_change(o: TxOutputType, coin: CoinType, root):
def get_address_for_change(o: TxOutputType, coin: CoinType, root: bip32.HDNode):
if o.script_type == OutputScriptType.PAYTOADDRESS:
input_script_type = InputScriptType.SPENDADDRESS
elif o.script_type == OutputScriptType.PAYTOMULTISIG:
@ -457,11 +482,10 @@ def get_address_for_change(o: TxOutputType, coin: CoinType, root):
input_script_type = InputScriptType.SPENDP2SHWITNESS
else:
raise SigningError(FailureType.DataError, 'Invalid script type')
return get_address(input_script_type, coin, node_derive(root, o.address_n))
return get_address(input_script_type, coin, node_derive(root, o.address_n), o.multisig)
def output_is_change(o: TxOutputType, wallet_path: list, segwit_in: int) -> bool:
address_n = o.address_n
is_segwit = (o.script_type == OutputScriptType.PAYTOWITNESS or
o.script_type == OutputScriptType.PAYTOP2SHWITNESS)
if is_segwit and o.amount > segwit_in:
@ -469,10 +493,10 @@ def output_is_change(o: TxOutputType, wallet_path: list, segwit_in: int) -> bool
# segwit inputs paid. this is to prevent user being tricked into
# creating ANYONECANSPEND outputs before full segwit activation.
return False
return (address_n is not None and wallet_path is not None and
wallet_path == address_n[:-_BIP32_WALLET_DEPTH] and
address_n[-2] == _BIP32_CHANGE_CHAIN and
address_n[-1] <= _BIP32_MAX_LAST_ELEMENT)
return (wallet_path is not None and
wallet_path == o.address_n[:-_BIP32_WALLET_DEPTH] and
o.address_n[-2] <= _BIP32_CHANGE_CHAIN and
o.address_n[-1] <= _BIP32_MAX_LAST_ELEMENT)
# Tx Inputs
@ -481,11 +505,33 @@ def output_is_change(o: TxOutputType, wallet_path: list, segwit_in: int) -> bool
def input_derive_script(coin: CoinType, i: TxInputType, pubkey: bytes, signature: bytes=None) -> bytes:
if i.script_type == InputScriptType.SPENDADDRESS:
return input_script_p2pkh_or_p2sh(pubkey, signature, get_hash_type(coin)) # p2pkh or p2sh
if i.script_type == InputScriptType.SPENDP2SHWITNESS: # p2wpkh using p2sh
# p2pkh or p2sh
return input_script_p2pkh_or_p2sh(
pubkey, signature, get_hash_type(coin))
if i.script_type == InputScriptType.SPENDP2SHWITNESS:
# p2wpkh or p2wsh using p2sh
if i.multisig:
# p2wsh in p2sh
pubkeys = multisig_get_pubkeys(i.multisig)
witness_script = output_script_multisig(pubkeys, i.multisig.m)
witness_script_hash = sha256(witness_script).digest()
return input_script_p2wsh_in_p2sh(witness_script_hash)
# p2wpkh in p2sh
return input_script_p2wpkh_in_p2sh(ecdsa_hash_pubkey(pubkey))
elif i.script_type == InputScriptType.SPENDWITNESS: # native p2wpkh or p2wsh
elif i.script_type == InputScriptType.SPENDWITNESS:
# native p2wpkh or p2wsh
return input_script_native_p2wpkh_or_p2wsh()
elif i.script_type == InputScriptType.SPENDMULTISIG:
# p2sh multisig
signature_index = multisig_pubkey_index(i.multisig, pubkey)
return input_script_multisig(
i.multisig, signature, signature_index, get_hash_type(coin))
else:
raise SigningError(FailureType.ProcessError, 'Invalid script type')
@ -512,13 +558,24 @@ def input_check_wallet_path(txi: TxInputType, wallet_path: list) -> list:
'Transaction has changed during signing')
def node_derive(root, address_n: list):
def node_derive(root: bip32.HDNode, address_n: list):
node = root.clone()
node.derive_path(address_n)
return node
def ecdsa_sign(node, digest: bytes) -> bytes:
def ecdsa_sign(node: bip32.HDNode, digest: bytes) -> bytes:
sig = secp256k1.sign(node.private_key(), digest)
sigder = der.encode_seq((sig[1:33], sig[33:65]))
return sigder
def is_change(
txo: TxOutputType,
wallet_path: list,
segwit_in: int,
multifp: MultisigFingerprint) -> bool:
if txo.multisig:
if not multifp.matches(txo.multisig):
return False
return output_is_change(txo, wallet_path, segwit_in)

View File

@ -55,7 +55,7 @@ class TxWeightCalculator:
if i.multisig:
multisig_script_size = (
_TXSIZE_MULTISIGSCRIPT +
i.multisig.pubkeys_count * (1 + _TXSIZE_PUBKEY))
len(i.multisig.pubkeys) * (1 + _TXSIZE_PUBKEY))
input_script_size = (
1 + # the OP_FALSE bug in multisig
i.multisig.m * (1 + _TXSIZE_SIGNATURE) +

View File

@ -1,8 +1,8 @@
from trezor.crypto.hashlib import sha256
from apps.wallet.sign_tx.writers import *
# TX Serialization
# ===

View File

@ -7,3 +7,11 @@ class Address(p.MessageType):
1: ('address', p.UnicodeType, 0), # required
}
MESSAGE_WIRE_TYPE = 30
def __init__(
self,
address: str = None,
**kwargs,
):
self.address = address
p.MessageType.__init__(self, **kwargs)

View File

@ -7,3 +7,11 @@ class ApplyFlags(p.MessageType):
1: ('flags', p.UVarintType, 0),
}
MESSAGE_WIRE_TYPE = 28
def __init__(
self,
flags: int = None,
**kwargs,
):
self.flags = flags
p.MessageType.__init__(self, **kwargs)

View File

@ -10,3 +10,17 @@ class ApplySettings(p.MessageType):
4: ('homescreen', p.BytesType, 0),
}
MESSAGE_WIRE_TYPE = 25
def __init__(
self,
language: str = None,
label: str = None,
use_passphrase: bool = None,
homescreen: bytes = None,
**kwargs,
):
self.language = language
self.label = label
self.use_passphrase = use_passphrase
self.homescreen = homescreen
p.MessageType.__init__(self, **kwargs)

View File

@ -4,3 +4,9 @@ import protobuf as p
class BackupDevice(p.MessageType):
MESSAGE_WIRE_TYPE = 34
def __init__(
self,
**kwargs,
):
p.MessageType.__init__(self, **kwargs)

View File

@ -4,3 +4,9 @@ import protobuf as p
class ButtonAck(p.MessageType):
MESSAGE_WIRE_TYPE = 27
def __init__(
self,
**kwargs,
):
p.MessageType.__init__(self, **kwargs)

View File

@ -8,3 +8,13 @@ class ButtonRequest(p.MessageType):
2: ('data', p.UnicodeType, 0),
}
MESSAGE_WIRE_TYPE = 26
def __init__(
self,
code: int = None,
data: str = None,
**kwargs,
):
self.code = code
self.data = data
p.MessageType.__init__(self, **kwargs)

View File

@ -4,3 +4,9 @@ import protobuf as p
class Cancel(p.MessageType):
MESSAGE_WIRE_TYPE = 20
def __init__(
self,
**kwargs,
):
p.MessageType.__init__(self, **kwargs)

View File

@ -7,3 +7,11 @@ class ChangePin(p.MessageType):
1: ('remove', p.BoolType, 0),
}
MESSAGE_WIRE_TYPE = 4
def __init__(
self,
remove: bool = None,
**kwargs,
):
self.remove = remove
p.MessageType.__init__(self, **kwargs)

View File

@ -13,3 +13,23 @@ class CipherKeyValue(p.MessageType):
7: ('iv', p.BytesType, 0),
}
MESSAGE_WIRE_TYPE = 23
def __init__(
self,
address_n: list = [],
key: str = None,
value: bytes = None,
encrypt: bool = None,
ask_on_encrypt: bool = None,
ask_on_decrypt: bool = None,
iv: bytes = None,
**kwargs,
):
self.address_n = address_n
self.key = key
self.value = value
self.encrypt = encrypt
self.ask_on_encrypt = ask_on_encrypt
self.ask_on_decrypt = ask_on_decrypt
self.iv = iv
p.MessageType.__init__(self, **kwargs)

View File

@ -7,3 +7,11 @@ class CipheredKeyValue(p.MessageType):
1: ('value', p.BytesType, 0),
}
MESSAGE_WIRE_TYPE = 48
def __init__(
self,
value: bytes = None,
**kwargs,
):
self.value = value
p.MessageType.__init__(self, **kwargs)

View File

@ -4,3 +4,9 @@ import protobuf as p
class ClearSession(p.MessageType):
MESSAGE_WIRE_TYPE = 24
def __init__(
self,
**kwargs,
):
p.MessageType.__init__(self, **kwargs)

View File

@ -14,5 +14,30 @@ class CoinType(p.MessageType):
10: ('xprv_magic', p.UVarintType, 0), # default=76066276
11: ('segwit', p.BoolType, 0),
12: ('forkid', p.UVarintType, 0),
13: ('force_bip143', p.BoolType, 0),
}
def __init__(
self,
coin_name: str = None,
coin_shortcut: str = None,
address_type: int = None,
maxfee_kb: int = None,
address_type_p2sh: int = None,
signed_message_header: str = None,
xpub_magic: int = None,
xprv_magic: int = None,
segwit: bool = None,
forkid: int = None,
**kwargs,
):
self.coin_name = coin_name
self.coin_shortcut = coin_shortcut
self.address_type = address_type
self.maxfee_kb = maxfee_kb
self.address_type_p2sh = address_type_p2sh
self.signed_message_header = signed_message_header
self.xpub_magic = xpub_magic
self.xprv_magic = xprv_magic
self.segwit = segwit
self.forkid = forkid
p.MessageType.__init__(self, **kwargs)

View File

@ -8,3 +8,13 @@ class CosiCommit(p.MessageType):
2: ('data', p.BytesType, 0),
}
MESSAGE_WIRE_TYPE = 71
def __init__(
self,
address_n: list = [],
data: bytes = None,
**kwargs,
):
self.address_n = address_n
self.data = data
p.MessageType.__init__(self, **kwargs)

View File

@ -8,3 +8,13 @@ class CosiCommitment(p.MessageType):
2: ('pubkey', p.BytesType, 0),
}
MESSAGE_WIRE_TYPE = 72
def __init__(
self,
commitment: bytes = None,
pubkey: bytes = None,
**kwargs,
):
self.commitment = commitment
self.pubkey = pubkey
p.MessageType.__init__(self, **kwargs)

View File

@ -10,3 +10,17 @@ class CosiSign(p.MessageType):
4: ('global_pubkey', p.BytesType, 0),
}
MESSAGE_WIRE_TYPE = 73
def __init__(
self,
address_n: list = [],
data: bytes = None,
global_commitment: bytes = None,
global_pubkey: bytes = None,
**kwargs,
):
self.address_n = address_n
self.data = data
self.global_commitment = global_commitment
self.global_pubkey = global_pubkey
p.MessageType.__init__(self, **kwargs)

View File

@ -7,3 +7,11 @@ class CosiSignature(p.MessageType):
1: ('signature', p.BytesType, 0),
}
MESSAGE_WIRE_TYPE = 74
def __init__(
self,
signature: bytes = None,
**kwargs,
):
self.signature = signature
p.MessageType.__init__(self, **kwargs)

View File

@ -7,3 +7,11 @@ class DebugLinkDecision(p.MessageType):
1: ('yes_no', p.BoolType, 0), # required
}
MESSAGE_WIRE_TYPE = 100
def __init__(
self,
yes_no: bool = None,
**kwargs,
):
self.yes_no = yes_no
p.MessageType.__init__(self, **kwargs)

View File

@ -7,3 +7,11 @@ class DebugLinkFlashErase(p.MessageType):
1: ('sector', p.UVarintType, 0),
}
MESSAGE_WIRE_TYPE = 113
def __init__(
self,
sector: int = None,
**kwargs,
):
self.sector = sector
p.MessageType.__init__(self, **kwargs)

View File

@ -4,3 +4,9 @@ import protobuf as p
class DebugLinkGetState(p.MessageType):
MESSAGE_WIRE_TYPE = 101
def __init__(
self,
**kwargs,
):
p.MessageType.__init__(self, **kwargs)

View File

@ -9,3 +9,15 @@ class DebugLinkLog(p.MessageType):
3: ('text', p.UnicodeType, 0),
}
MESSAGE_WIRE_TYPE = 104
def __init__(
self,
level: int = None,
bucket: str = None,
text: str = None,
**kwargs,
):
self.level = level
self.bucket = bucket
self.text = text
p.MessageType.__init__(self, **kwargs)

View File

@ -7,3 +7,11 @@ class DebugLinkMemory(p.MessageType):
1: ('memory', p.BytesType, 0),
}
MESSAGE_WIRE_TYPE = 111
def __init__(
self,
memory: bytes = None,
**kwargs,
):
self.memory = memory
p.MessageType.__init__(self, **kwargs)

View File

@ -8,3 +8,13 @@ class DebugLinkMemoryRead(p.MessageType):
2: ('length', p.UVarintType, 0),
}
MESSAGE_WIRE_TYPE = 110
def __init__(
self,
address: int = None,
length: int = None,
**kwargs,
):
self.address = address
self.length = length
p.MessageType.__init__(self, **kwargs)

View File

@ -9,3 +9,15 @@ class DebugLinkMemoryWrite(p.MessageType):
3: ('flash', p.BoolType, 0),
}
MESSAGE_WIRE_TYPE = 112
def __init__(
self,
address: int = None,
memory: bytes = None,
flash: bool = None,
**kwargs,
):
self.address = address
self.memory = memory
self.flash = flash
p.MessageType.__init__(self, **kwargs)

View File

@ -17,3 +17,29 @@ class DebugLinkState(p.MessageType):
10: ('recovery_word_pos', p.UVarintType, 0),
}
MESSAGE_WIRE_TYPE = 102
def __init__(
self,
layout: bytes = None,
pin: str = None,
matrix: str = None,
mnemonic: str = None,
node: HDNodeType = None,
passphrase_protection: bool = None,
reset_word: str = None,
reset_entropy: bytes = None,
recovery_fake_word: str = None,
recovery_word_pos: int = None,
**kwargs,
):
self.layout = layout
self.pin = pin
self.matrix = matrix
self.mnemonic = mnemonic
self.node = node
self.passphrase_protection = passphrase_protection
self.reset_word = reset_word
self.reset_entropy = reset_entropy
self.recovery_fake_word = recovery_fake_word
self.recovery_word_pos = recovery_word_pos
p.MessageType.__init__(self, **kwargs)

View File

@ -4,3 +4,9 @@ import protobuf as p
class DebugLinkStop(p.MessageType):
MESSAGE_WIRE_TYPE = 103
def __init__(
self,
**kwargs,
):
p.MessageType.__init__(self, **kwargs)

View File

@ -10,3 +10,17 @@ class DecryptMessage(p.MessageType):
4: ('hmac', p.BytesType, 0),
}
MESSAGE_WIRE_TYPE = 51
def __init__(
self,
address_n: list = [],
nonce: bytes = None,
message: bytes = None,
hmac: bytes = None,
**kwargs,
):
self.address_n = address_n
self.nonce = nonce
self.message = message
self.hmac = hmac
p.MessageType.__init__(self, **kwargs)

View File

@ -8,3 +8,13 @@ class DecryptedMessage(p.MessageType):
2: ('address', p.UnicodeType, 0),
}
MESSAGE_WIRE_TYPE = 52
def __init__(
self,
message: bytes = None,
address: str = None,
**kwargs,
):
self.message = message
self.address = address
p.MessageType.__init__(self, **kwargs)

View File

@ -7,3 +7,11 @@ class ECDHSessionKey(p.MessageType):
1: ('session_key', p.BytesType, 0),
}
MESSAGE_WIRE_TYPE = 62
def __init__(
self,
session_key: bytes = None,
**kwargs,
):
self.session_key = session_key
p.MessageType.__init__(self, **kwargs)

View File

@ -11,3 +11,19 @@ class EncryptMessage(p.MessageType):
5: ('coin_name', p.UnicodeType, 0), # default='Bitcoin'
}
MESSAGE_WIRE_TYPE = 49
def __init__(
self,
pubkey: bytes = None,
message: bytes = None,
display_only: bool = None,
address_n: list = [],
coin_name: str = None,
**kwargs,
):
self.pubkey = pubkey
self.message = message
self.display_only = display_only
self.address_n = address_n
self.coin_name = coin_name
p.MessageType.__init__(self, **kwargs)

View File

@ -9,3 +9,15 @@ class EncryptedMessage(p.MessageType):
3: ('hmac', p.BytesType, 0),
}
MESSAGE_WIRE_TYPE = 50
def __init__(
self,
nonce: bytes = None,
message: bytes = None,
hmac: bytes = None,
**kwargs,
):
self.nonce = nonce
self.message = message
self.hmac = hmac
p.MessageType.__init__(self, **kwargs)

View File

@ -7,3 +7,11 @@ class Entropy(p.MessageType):
1: ('entropy', p.BytesType, 0), # required
}
MESSAGE_WIRE_TYPE = 10
def __init__(
self,
entropy: bytes = None,
**kwargs,
):
self.entropy = entropy
p.MessageType.__init__(self, **kwargs)

View File

@ -7,3 +7,11 @@ class EntropyAck(p.MessageType):
1: ('entropy', p.BytesType, 0),
}
MESSAGE_WIRE_TYPE = 36
def __init__(
self,
entropy: bytes = None,
**kwargs,
):
self.entropy = entropy
p.MessageType.__init__(self, **kwargs)

View File

@ -4,3 +4,9 @@ import protobuf as p
class EntropyRequest(p.MessageType):
MESSAGE_WIRE_TYPE = 35
def __init__(
self,
**kwargs,
):
p.MessageType.__init__(self, **kwargs)

View File

@ -9,3 +9,15 @@ class EstimateTxSize(p.MessageType):
3: ('coin_name', p.UnicodeType, 0), # default='Bitcoin'
}
MESSAGE_WIRE_TYPE = 43
def __init__(
self,
outputs_count: int = None,
inputs_count: int = None,
coin_name: str = None,
**kwargs,
):
self.outputs_count = outputs_count
self.inputs_count = inputs_count
self.coin_name = coin_name
p.MessageType.__init__(self, **kwargs)

View File

@ -7,3 +7,11 @@ class EthereumAddress(p.MessageType):
1: ('address', p.BytesType, 0), # required
}
MESSAGE_WIRE_TYPE = 57
def __init__(
self,
address: bytes = None,
**kwargs,
):
self.address = address
p.MessageType.__init__(self, **kwargs)

View File

@ -8,3 +8,13 @@ class EthereumGetAddress(p.MessageType):
2: ('show_display', p.BoolType, 0),
}
MESSAGE_WIRE_TYPE = 56
def __init__(
self,
address_n: list = [],
show_display: bool = None,
**kwargs,
):
self.address_n = address_n
self.show_display = show_display
p.MessageType.__init__(self, **kwargs)

View File

@ -8,3 +8,13 @@ class EthereumMessageSignature(p.MessageType):
2: ('signature', p.BytesType, 0),
}
MESSAGE_WIRE_TYPE = 66
def __init__(
self,
address: bytes = None,
signature: bytes = None,
**kwargs,
):
self.address = address
self.signature = signature
p.MessageType.__init__(self, **kwargs)

View File

@ -8,3 +8,13 @@ class EthereumSignMessage(p.MessageType):
2: ('message', p.BytesType, 0), # required
}
MESSAGE_WIRE_TYPE = 64
def __init__(
self,
address_n: list = [],
message: bytes = None,
**kwargs,
):
self.address_n = address_n
self.message = message
p.MessageType.__init__(self, **kwargs)

View File

@ -15,3 +15,27 @@ class EthereumSignTx(p.MessageType):
9: ('chain_id', p.UVarintType, 0),
}
MESSAGE_WIRE_TYPE = 58
def __init__(
self,
address_n: list = [],
nonce: bytes = None,
gas_price: bytes = None,
gas_limit: bytes = None,
to: bytes = None,
value: bytes = None,
data_initial_chunk: bytes = None,
data_length: int = None,
chain_id: int = None,
**kwargs,
):
self.address_n = address_n
self.nonce = nonce
self.gas_price = gas_price
self.gas_limit = gas_limit
self.to = to
self.value = value
self.data_initial_chunk = data_initial_chunk
self.data_length = data_length
self.chain_id = chain_id
p.MessageType.__init__(self, **kwargs)

View File

@ -7,3 +7,11 @@ class EthereumTxAck(p.MessageType):
1: ('data_chunk', p.BytesType, 0),
}
MESSAGE_WIRE_TYPE = 60
def __init__(
self,
data_chunk: bytes = None,
**kwargs,
):
self.data_chunk = data_chunk
p.MessageType.__init__(self, **kwargs)

View File

@ -10,3 +10,17 @@ class EthereumTxRequest(p.MessageType):
4: ('signature_s', p.BytesType, 0),
}
MESSAGE_WIRE_TYPE = 59
def __init__(
self,
data_length: int = None,
signature_v: int = None,
signature_r: bytes = None,
signature_s: bytes = None,
**kwargs,
):
self.data_length = data_length
self.signature_v = signature_v
self.signature_r = signature_r
self.signature_s = signature_s
p.MessageType.__init__(self, **kwargs)

View File

@ -9,3 +9,15 @@ class EthereumVerifyMessage(p.MessageType):
3: ('message', p.BytesType, 0),
}
MESSAGE_WIRE_TYPE = 65
def __init__(
self,
address: bytes = None,
signature: bytes = None,
message: bytes = None,
**kwargs,
):
self.address = address
self.signature = signature
self.message = message
p.MessageType.__init__(self, **kwargs)

View File

@ -8,3 +8,13 @@ class Failure(p.MessageType):
2: ('message', p.UnicodeType, 0),
}
MESSAGE_WIRE_TYPE = 3
def __init__(
self,
code: int = None,
message: str = None,
**kwargs,
):
self.code = code
self.message = message
p.MessageType.__init__(self, **kwargs)

View File

@ -25,12 +25,51 @@ class Features(p.MessageType):
18: ('firmware_present', p.BoolType, 0),
19: ('needs_backup', p.BoolType, 0),
20: ('flags', p.UVarintType, 0),
21: ('model', p.UnicodeType, 0),
22: ('fw_major', p.UVarintType, 0),
23: ('fw_minor', p.UVarintType, 0),
24: ('fw_patch', p.UVarintType, 0),
25: ('fw_vendor', p.UnicodeType, 0),
26: ('fw_vendor_keys', p.BytesType, 0),
27: ('state', p.BytesType, 0),
}
MESSAGE_WIRE_TYPE = 17
def __init__(
self,
vendor: str = None,
major_version: int = None,
minor_version: int = None,
patch_version: int = None,
bootloader_mode: bool = None,
device_id: str = None,
pin_protection: bool = None,
passphrase_protection: bool = None,
language: str = None,
label: str = None,
coins: list = [],
initialized: bool = None,
revision: bytes = None,
bootloader_hash: bytes = None,
imported: bool = None,
pin_cached: bool = None,
passphrase_cached: bool = None,
firmware_present: bool = None,
needs_backup: bool = None,
flags: int = None,
**kwargs,
):
self.vendor = vendor
self.major_version = major_version
self.minor_version = minor_version
self.patch_version = patch_version
self.bootloader_mode = bootloader_mode
self.device_id = device_id
self.pin_protection = pin_protection
self.passphrase_protection = passphrase_protection
self.language = language
self.label = label
self.coins = coins
self.initialized = initialized
self.revision = revision
self.bootloader_hash = bootloader_hash
self.imported = imported
self.pin_cached = pin_cached
self.passphrase_cached = passphrase_cached
self.firmware_present = firmware_present
self.needs_backup = needs_backup
self.flags = flags
p.MessageType.__init__(self, **kwargs)

View File

@ -7,3 +7,11 @@ class FirmwareErase(p.MessageType):
1: ('length', p.UVarintType, 0),
}
MESSAGE_WIRE_TYPE = 6
def __init__(
self,
length: int = None,
**kwargs,
):
self.length = length
p.MessageType.__init__(self, **kwargs)

View File

@ -8,3 +8,13 @@ class FirmwareRequest(p.MessageType):
2: ('length', p.UVarintType, 0),
}
MESSAGE_WIRE_TYPE = 8
def __init__(
self,
offset: int = None,
length: int = None,
**kwargs,
):
self.offset = offset
self.length = length
p.MessageType.__init__(self, **kwargs)

View File

@ -8,3 +8,13 @@ class FirmwareUpload(p.MessageType):
2: ('hash', p.BytesType, 0),
}
MESSAGE_WIRE_TYPE = 7
def __init__(
self,
payload: bytes = None,
hash: bytes = None,
**kwargs,
):
self.payload = payload
self.hash = hash
p.MessageType.__init__(self, **kwargs)

View File

@ -12,3 +12,19 @@ class GetAddress(p.MessageType):
5: ('script_type', p.UVarintType, 0), # default=0
}
MESSAGE_WIRE_TYPE = 29
def __init__(
self,
address_n: list = [],
coin_name: str = None,
show_display: bool = None,
multisig: MultisigRedeemScriptType = None,
script_type: int = None,
**kwargs,
):
self.address_n = address_n
self.coin_name = coin_name
self.show_display = show_display
self.multisig = multisig
self.script_type = script_type
p.MessageType.__init__(self, **kwargs)

View File

@ -10,3 +10,15 @@ class GetECDHSessionKey(p.MessageType):
3: ('ecdsa_curve_name', p.UnicodeType, 0),
}
MESSAGE_WIRE_TYPE = 61
def __init__(
self,
identity: IdentityType = None,
peer_public_key: bytes = None,
ecdsa_curve_name: str = None,
**kwargs,
):
self.identity = identity
self.peer_public_key = peer_public_key
self.ecdsa_curve_name = ecdsa_curve_name
p.MessageType.__init__(self, **kwargs)

View File

@ -7,3 +7,11 @@ class GetEntropy(p.MessageType):
1: ('size', p.UVarintType, 0), # required
}
MESSAGE_WIRE_TYPE = 9
def __init__(
self,
size: int = None,
**kwargs,
):
self.size = size
p.MessageType.__init__(self, **kwargs)

View File

@ -4,3 +4,9 @@ import protobuf as p
class GetFeatures(p.MessageType):
MESSAGE_WIRE_TYPE = 55
def __init__(
self,
**kwargs,
):
p.MessageType.__init__(self, **kwargs)

View File

@ -10,3 +10,17 @@ class GetPublicKey(p.MessageType):
4: ('coin_name', p.UnicodeType, 0), # default='Bitcoin'
}
MESSAGE_WIRE_TYPE = 11
def __init__(
self,
address_n: list = [],
ecdsa_curve_name: str = None,
show_display: bool = None,
coin_name: str = None,
**kwargs,
):
self.address_n = address_n
self.ecdsa_curve_name = ecdsa_curve_name
self.show_display = show_display
self.coin_name = coin_name
p.MessageType.__init__(self, **kwargs)

View File

@ -8,3 +8,13 @@ class HDNodePathType(p.MessageType):
1: ('node', HDNodeType, 0), # required
2: ('address_n', p.UVarintType, p.FLAG_REPEATED),
}
def __init__(
self,
node: HDNodeType = None,
address_n: list = [],
**kwargs,
):
self.node = node
self.address_n = address_n
p.MessageType.__init__(self, **kwargs)

View File

@ -11,3 +11,21 @@ class HDNodeType(p.MessageType):
5: ('private_key', p.BytesType, 0),
6: ('public_key', p.BytesType, 0),
}
def __init__(
self,
depth: int = None,
fingerprint: int = None,
child_num: int = None,
chain_code: bytes = None,
private_key: bytes = None,
public_key: bytes = None,
**kwargs,
):
self.depth = depth
self.fingerprint = fingerprint
self.child_num = child_num
self.chain_code = chain_code
self.private_key = private_key
self.public_key = public_key
p.MessageType.__init__(self, **kwargs)

View File

@ -11,3 +11,21 @@ class IdentityType(p.MessageType):
5: ('path', p.UnicodeType, 0),
6: ('index', p.UVarintType, 0), # default=0
}
def __init__(
self,
proto: str = None,
user: str = None,
host: str = None,
port: str = None,
path: str = None,
index: int = None,
**kwargs,
):
self.proto = proto
self.user = user
self.host = host
self.port = port
self.path = path
self.index = index
p.MessageType.__init__(self, **kwargs)

View File

@ -3,7 +3,10 @@ import protobuf as p
class Initialize(p.MessageType):
FIELDS = {
1: ('state', p.BytesType, 0),
}
MESSAGE_WIRE_TYPE = 0
def __init__(
self,
**kwargs,
):
p.MessageType.__init__(self, **kwargs)

View File

@ -15,3 +15,25 @@ class LoadDevice(p.MessageType):
8: ('u2f_counter', p.UVarintType, 0),
}
MESSAGE_WIRE_TYPE = 13
def __init__(
self,
mnemonic: str = None,
node: HDNodeType = None,
pin: str = None,
passphrase_protection: bool = None,
language: str = None,
label: str = None,
skip_checksum: bool = None,
u2f_counter: int = None,
**kwargs,
):
self.mnemonic = mnemonic
self.node = node
self.pin = pin
self.passphrase_protection = passphrase_protection
self.language = language
self.label = label
self.skip_checksum = skip_checksum
self.u2f_counter = u2f_counter
p.MessageType.__init__(self, **kwargs)

View File

@ -8,3 +8,13 @@ class MessageSignature(p.MessageType):
2: ('signature', p.BytesType, 0),
}
MESSAGE_WIRE_TYPE = 40
def __init__(
self,
address: str = None,
signature: bytes = None,
**kwargs,
):
self.address = address
self.signature = signature
p.MessageType.__init__(self, **kwargs)

View File

@ -73,8 +73,6 @@ CosiCommit = const(71)
CosiCommitment = const(72)
CosiSign = const(73)
CosiSignature = const(74)
NEMDecryptMessage = const(75)
NEMDecryptedMessage = const(76)
DebugLinkDecision = const(100)
DebugLinkGetState = const(101)
DebugLinkState = const(102)

View File

@ -9,3 +9,15 @@ class MultisigRedeemScriptType(p.MessageType):
2: ('signatures', p.BytesType, p.FLAG_REPEATED),
3: ('m', p.UVarintType, 0),
}
def __init__(
self,
pubkeys: list = [],
signatures: list = [],
m: int = None,
**kwargs,
):
self.pubkeys = pubkeys
self.signatures = signatures
self.m = m
p.MessageType.__init__(self, **kwargs)

View File

@ -7,3 +7,11 @@ class NEMAddress(p.MessageType):
1: ('address', p.UnicodeType, 0), # required
}
MESSAGE_WIRE_TYPE = 68
def __init__(
self,
address: str = None,
**kwargs,
):
self.address = address
p.MessageType.__init__(self, **kwargs)

View File

@ -8,3 +8,13 @@ class NEMAggregateModification(p.MessageType):
1: ('modifications', NEMCosignatoryModification, p.FLAG_REPEATED),
2: ('relative_change', p.Sint32Type, 0),
}
def __init__(
self,
modifications: list = [],
relative_change: int = None,
**kwargs,
):
self.modifications = modifications
self.relative_change = relative_change
p.MessageType.__init__(self, **kwargs)

View File

@ -7,3 +7,13 @@ class NEMCosignatoryModification(p.MessageType):
1: ('type', p.UVarintType, 0),
2: ('public_key', p.BytesType, 0),
}
def __init__(
self,
type: int = None,
public_key: bytes = None,
**kwargs,
):
self.type = type
self.public_key = public_key
p.MessageType.__init__(self, **kwargs)

View File

@ -1,12 +0,0 @@
# Automatically generated by pb2py
import protobuf as p
class NEMDecryptMessage(p.MessageType):
FIELDS = {
1: ('address_n', p.UVarintType, p.FLAG_REPEATED),
2: ('network', p.UVarintType, 0),
3: ('public_key', p.BytesType, 0),
4: ('payload', p.BytesType, 0),
}
MESSAGE_WIRE_TYPE = 75

View File

@ -1,9 +0,0 @@
# Automatically generated by pb2py
import protobuf as p
class NEMDecryptedMessage(p.MessageType):
FIELDS = {
1: ('payload', p.BytesType, 0),
}
MESSAGE_WIRE_TYPE = 76

View File

@ -9,3 +9,15 @@ class NEMGetAddress(p.MessageType):
3: ('show_display', p.BoolType, 0),
}
MESSAGE_WIRE_TYPE = 67
def __init__(
self,
address_n: list = [],
network: int = None,
show_display: bool = None,
**kwargs,
):
self.address_n = address_n
self.network = network
self.show_display = show_display
p.MessageType.__init__(self, **kwargs)

View File

@ -7,3 +7,13 @@ class NEMImportanceTransfer(p.MessageType):
1: ('mode', p.UVarintType, 0),
2: ('public_key', p.BytesType, 0),
}
def __init__(
self,
mode: int = None,
public_key: bytes = None,
**kwargs,
):
self.mode = mode
self.public_key = public_key
p.MessageType.__init__(self, **kwargs)

View File

@ -8,3 +8,15 @@ class NEMMosaic(p.MessageType):
2: ('mosaic', p.UnicodeType, 0),
3: ('quantity', p.UVarintType, 0),
}
def __init__(
self,
namespace: str = None,
mosaic: str = None,
quantity: int = None,
**kwargs,
):
self.namespace = namespace
self.mosaic = mosaic
self.quantity = quantity
p.MessageType.__init__(self, **kwargs)

View File

@ -9,3 +9,15 @@ class NEMMosaicCreation(p.MessageType):
2: ('sink', p.UnicodeType, 0),
3: ('fee', p.UVarintType, 0),
}
def __init__(
self,
definition: NEMMosaicDefinition = None,
sink: str = None,
fee: int = None,
**kwargs,
):
self.definition = definition
self.sink = sink
self.fee = fee
p.MessageType.__init__(self, **kwargs)

View File

@ -20,3 +20,39 @@ class NEMMosaicDefinition(p.MessageType):
14: ('description', p.UnicodeType, 0),
15: ('networks', p.UVarintType, p.FLAG_REPEATED),
}
def __init__(
self,
name: str = None,
ticker: str = None,
namespace: str = None,
mosaic: str = None,
divisibility: int = None,
levy: int = None,
fee: int = None,
levy_address: str = None,
levy_namespace: str = None,
levy_mosaic: str = None,
supply: int = None,
mutable_supply: bool = None,
transferable: bool = None,
description: str = None,
networks: list = [],
**kwargs,
):
self.name = name
self.ticker = ticker
self.namespace = namespace
self.mosaic = mosaic
self.divisibility = divisibility
self.levy = levy
self.fee = fee
self.levy_address = levy_address
self.levy_namespace = levy_namespace
self.levy_mosaic = levy_mosaic
self.supply = supply
self.mutable_supply = mutable_supply
self.transferable = transferable
self.description = description
self.networks = networks
p.MessageType.__init__(self, **kwargs)

View File

@ -9,3 +9,17 @@ class NEMMosaicSupplyChange(p.MessageType):
3: ('type', p.UVarintType, 0),
4: ('delta', p.UVarintType, 0),
}
def __init__(
self,
namespace: str = None,
mosaic: str = None,
type: int = None,
delta: int = None,
**kwargs,
):
self.namespace = namespace
self.mosaic = mosaic
self.type = type
self.delta = delta
p.MessageType.__init__(self, **kwargs)

View File

@ -9,3 +9,17 @@ class NEMProvisionNamespace(p.MessageType):
3: ('sink', p.UnicodeType, 0),
4: ('fee', p.UVarintType, 0),
}
def __init__(
self,
namespace: str = None,
parent: str = None,
sink: str = None,
fee: int = None,
**kwargs,
):
self.namespace = namespace
self.parent = parent
self.sink = sink
self.fee = fee
p.MessageType.__init__(self, **kwargs)

View File

@ -22,3 +22,27 @@ class NEMSignTx(p.MessageType):
9: ('importance_transfer', NEMImportanceTransfer, 0),
}
MESSAGE_WIRE_TYPE = 69
def __init__(
self,
transaction: NEMTransactionCommon = None,
multisig: NEMTransactionCommon = None,
transfer: NEMTransfer = None,
cosigning: bool = None,
provision_namespace: NEMProvisionNamespace = None,
mosaic_creation: NEMMosaicCreation = None,
supply_change: NEMMosaicSupplyChange = None,
aggregate_modification: NEMAggregateModification = None,
importance_transfer: NEMImportanceTransfer = None,
**kwargs,
):
self.transaction = transaction
self.multisig = multisig
self.transfer = transfer
self.cosigning = cosigning
self.provision_namespace = provision_namespace
self.mosaic_creation = mosaic_creation
self.supply_change = supply_change
self.aggregate_modification = aggregate_modification
self.importance_transfer = importance_transfer
p.MessageType.__init__(self, **kwargs)

View File

@ -8,3 +8,13 @@ class NEMSignedTx(p.MessageType):
2: ('signature', p.BytesType, 0),
}
MESSAGE_WIRE_TYPE = 70
def __init__(
self,
data: bytes = None,
signature: bytes = None,
**kwargs,
):
self.data = data
self.signature = signature
p.MessageType.__init__(self, **kwargs)

View File

@ -11,3 +11,21 @@ class NEMTransactionCommon(p.MessageType):
5: ('deadline', p.UVarintType, 0),
6: ('signer', p.BytesType, 0),
}
def __init__(
self,
address_n: list = [],
network: int = None,
timestamp: int = None,
fee: int = None,
deadline: int = None,
signer: bytes = None,
**kwargs,
):
self.address_n = address_n
self.network = network
self.timestamp = timestamp
self.fee = fee
self.deadline = deadline
self.signer = signer
p.MessageType.__init__(self, **kwargs)

View File

@ -11,3 +11,19 @@ class NEMTransfer(p.MessageType):
4: ('public_key', p.BytesType, 0),
5: ('mosaics', NEMMosaic, p.FLAG_REPEATED),
}
def __init__(
self,
recipient: str = None,
amount: int = None,
payload: bytes = None,
public_key: bytes = None,
mosaics: list = [],
**kwargs,
):
self.recipient = recipient
self.amount = amount
self.payload = payload
self.public_key = public_key
self.mosaics = mosaics
p.MessageType.__init__(self, **kwargs)

View File

@ -5,6 +5,13 @@ import protobuf as p
class PassphraseAck(p.MessageType):
FIELDS = {
1: ('passphrase', p.UnicodeType, 0), # required
2: ('state', p.BytesType, 0),
}
MESSAGE_WIRE_TYPE = 42
def __init__(
self,
passphrase: str = None,
**kwargs,
):
self.passphrase = passphrase
p.MessageType.__init__(self, **kwargs)

View File

@ -3,7 +3,10 @@ import protobuf as p
class PassphraseRequest(p.MessageType):
FIELDS = {
1: ('on_device', p.BoolType, 0),
}
MESSAGE_WIRE_TYPE = 41
def __init__(
self,
**kwargs,
):
p.MessageType.__init__(self, **kwargs)

View File

@ -7,3 +7,11 @@ class PinMatrixAck(p.MessageType):
1: ('pin', p.UnicodeType, 0), # required
}
MESSAGE_WIRE_TYPE = 19
def __init__(
self,
pin: str = None,
**kwargs,
):
self.pin = pin
p.MessageType.__init__(self, **kwargs)

View File

@ -7,3 +7,11 @@ class PinMatrixRequest(p.MessageType):
1: ('type', p.UVarintType, 0),
}
MESSAGE_WIRE_TYPE = 18
def __init__(
self,
type: int = None,
**kwargs,
):
self.type = type
p.MessageType.__init__(self, **kwargs)

View File

@ -10,3 +10,17 @@ class Ping(p.MessageType):
4: ('passphrase_protection', p.BoolType, 0),
}
MESSAGE_WIRE_TYPE = 1
def __init__(
self,
message: str = None,
button_protection: bool = None,
pin_protection: bool = None,
passphrase_protection: bool = None,
**kwargs,
):
self.message = message
self.button_protection = button_protection
self.pin_protection = pin_protection
self.passphrase_protection = passphrase_protection
p.MessageType.__init__(self, **kwargs)

View File

@ -9,3 +9,13 @@ class PublicKey(p.MessageType):
2: ('xpub', p.UnicodeType, 0),
}
MESSAGE_WIRE_TYPE = 12
def __init__(
self,
node: HDNodeType = None,
xpub: str = None,
**kwargs,
):
self.node = node
self.xpub = xpub
p.MessageType.__init__(self, **kwargs)

View File

@ -15,3 +15,27 @@ class RecoveryDevice(p.MessageType):
10: ('dry_run', p.BoolType, 0),
}
MESSAGE_WIRE_TYPE = 45
def __init__(
self,
word_count: int = None,
passphrase_protection: bool = None,
pin_protection: bool = None,
language: str = None,
label: str = None,
enforce_wordlist: bool = None,
type: int = None,
u2f_counter: int = None,
dry_run: bool = None,
**kwargs,
):
self.word_count = word_count
self.passphrase_protection = passphrase_protection
self.pin_protection = pin_protection
self.language = language
self.label = label
self.enforce_wordlist = enforce_wordlist
self.type = type
self.u2f_counter = u2f_counter
self.dry_run = dry_run
p.MessageType.__init__(self, **kwargs)

Some files were not shown because too many files have changed in this diff Show More