diff --git a/core/src/apps/wallet/sign_tx/multisig.py b/core/src/apps/wallet/sign_tx/multisig.py index 5cbf62f2e..aff137dd6 100644 --- a/core/src/apps/wallet/sign_tx/multisig.py +++ b/core/src/apps/wallet/sign_tx/multisig.py @@ -7,17 +7,20 @@ from trezor.utils import HashWriter, ensure from apps.wallet.sign_tx.writers import write_bytes_fixed, write_uint32 +if False: + from typing import List, Optional + class MultisigError(ValueError): pass class MultisigFingerprint: - def __init__(self): - self.fingerprint = None # multisig fingerprint bytes + def __init__(self) -> None: + self.fingerprint = None # type: Optional[bytes] # multisig fingerprint bytes self.mismatch = False # flag if multisig input fingerprints are equal - def add(self, multisig: MultisigRedeemScriptType): + def add(self, multisig: MultisigRedeemScriptType) -> None: fp = multisig_fingerprint(multisig) ensure(fp is not None) if self.fingerprint is None: @@ -25,7 +28,7 @@ class MultisigFingerprint: elif self.fingerprint != fp: self.mismatch = True - def matches(self, multisig: MultisigRedeemScriptType): + def matches(self, multisig: MultisigRedeemScriptType) -> bool: fp = multisig_fingerprint(multisig) ensure(fp is not None) if self.mismatch is False and self.fingerprint == fp: @@ -90,14 +93,14 @@ def multisig_get_pubkey(n: HDNodeType, p: list) -> bytes: return node.public_key() -def multisig_get_pubkeys(multisig: MultisigRedeemScriptType): +def multisig_get_pubkeys(multisig: MultisigRedeemScriptType) -> List[bytes]: if multisig.nodes: return [multisig_get_pubkey(hd, multisig.address_n) for hd in multisig.nodes] else: return [multisig_get_pubkey(hd.node, hd.address_n) for hd in multisig.pubkeys] -def multisig_get_pubkey_count(multisig: MultisigRedeemScriptType): +def multisig_get_pubkey_count(multisig: MultisigRedeemScriptType) -> int: if multisig.nodes: return len(multisig.nodes) else: diff --git a/core/src/apps/wallet/sign_tx/omni.py b/core/src/apps/wallet/sign_tx/omni.py index 7d150bedf..81b2a3662 100644 --- a/core/src/apps/wallet/sign_tx/omni.py +++ b/core/src/apps/wallet/sign_tx/omni.py @@ -2,6 +2,9 @@ from ustruct import unpack from trezor.strings import format_amount +if False: + from typing import Optional + currencies = { 1: ("OMNI", True), 2: ("tOMNI", True), @@ -14,7 +17,7 @@ def is_valid(data: bytes) -> bool: return len(data) >= 8 and data[:4] == b"omni" -def parse(data: bytes) -> bool: +def parse(data: bytes) -> Optional[str]: if not is_valid(data): return None tx_version, tx_type = unpack(">HH", data[4:8]) diff --git a/core/src/apps/wallet/sign_tx/progress.py b/core/src/apps/wallet/sign_tx/progress.py index 1dc64d29c..0971c6ddf 100644 --- a/core/src/apps/wallet/sign_tx/progress.py +++ b/core/src/apps/wallet/sign_tx/progress.py @@ -4,7 +4,7 @@ _progress = 0 _steps = 0 -def init(inputs, outputs): +def init(inputs: int, outputs: int) -> None: global _progress, _steps _progress = 0 _steps = inputs + inputs + outputs + inputs @@ -12,18 +12,18 @@ def init(inputs, outputs): report() -def advance(): +def advance() -> None: global _progress _progress += 1 report() -def report_init(): +def report_init() -> None: ui.display.clear() ui.header("Signing transaction") -def report(): +def report() -> None: if utils.DISABLE_ANIMATION: return p = 1000 * _progress // _steps diff --git a/core/src/apps/wallet/sign_tx/scripts.py b/core/src/apps/wallet/sign_tx/scripts.py index b1495c785..d02171d0b 100644 --- a/core/src/apps/wallet/sign_tx/scripts.py +++ b/core/src/apps/wallet/sign_tx/scripts.py @@ -132,7 +132,7 @@ def input_script_p2wsh_in_p2sh(script_hash: bytes) -> bytearray: # === -def witness_p2wpkh(signature: bytes, pubkey: bytes, sighash: int): +def witness_p2wpkh(signature: bytes, pubkey: bytes, sighash: int) -> bytearray: w = empty_bytearray(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) diff --git a/core/src/apps/wallet/sign_tx/zcash.py b/core/src/apps/wallet/sign_tx/zcash.py index 4f5c8e6ff..cde31b5c4 100644 --- a/core/src/apps/wallet/sign_tx/zcash.py +++ b/core/src/apps/wallet/sign_tx/zcash.py @@ -47,7 +47,7 @@ def derive_script_code(txi: TxInputType, pubkeyhash: bytes) -> bytearray: class Zip143: - def __init__(self, branch_id): + def __init__(self, branch_id: int) -> None: self.branch_id = branch_id self.h_prevouts = HashWriter(blake2b(outlen=32, personal=b"ZcashPrevoutHash")) self.h_sequence = HashWriter(blake2b(outlen=32, personal=b"ZcashSequencHash")) @@ -119,7 +119,7 @@ class Zip143: class Zip243(Zip143): - def __init__(self, branch_id): + def __init__(self, branch_id) -> None: super().__init__(branch_id) def preimage_hash( diff --git a/core/src/trezor/crypto/base58.py b/core/src/trezor/crypto/base58.py index a472f5c32..310439807 100644 --- a/core/src/trezor/crypto/base58.py +++ b/core/src/trezor/crypto/base58.py @@ -13,11 +13,14 @@ # This module adds shiny packaging and support for python3. # +if False: + from typing import Callable + # 58 character alphabet used _alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" -def encode(data: bytes, alphabet=_alphabet) -> str: +def encode(data: bytes, alphabet: str = _alphabet) -> str: """ Convert bytes to base58 encoded string. """ @@ -38,7 +41,7 @@ def encode(data: bytes, alphabet=_alphabet) -> str: return "".join((c for c in reversed(result + alphabet[0] * (origlen - newlen)))) -def decode(string: str, alphabet=_alphabet) -> bytes: +def decode(string: str, alphabet: str = _alphabet) -> bytes: """ Convert base58 encoded string to bytes. """ @@ -89,14 +92,16 @@ def ripemd160_32(data: bytes) -> bytes: return ripemd160(data).digest()[:4] -def encode_check(data: bytes, digestfunc=sha256d_32) -> str: +def encode_check(data: bytes, digestfunc: Callable[[bytes], bytes] = sha256d_32) -> str: """ Convert bytes to base58 encoded string, append checksum. """ return encode(data + digestfunc(data)) -def decode_check(string: str, digestfunc=sha256d_32) -> bytes: +def decode_check( + string: str, digestfunc: Callable[[bytes], bytes] = sha256d_32 +) -> bytes: """ Convert base58 encoded string to bytes and verify checksum. """ @@ -104,7 +109,7 @@ def decode_check(string: str, digestfunc=sha256d_32) -> bytes: return verify_checksum(result, digestfunc) -def verify_checksum(data: bytes, digestfunc) -> bytes: +def verify_checksum(data: bytes, digestfunc: Callable[[bytes], bytes]) -> bytes: digestlen = len(digestfunc(b"")) result, check = data[:-digestlen], data[-digestlen:] diff --git a/core/src/trezor/crypto/bech32.py b/core/src/trezor/crypto/bech32.py index 212705d55..d7a82cf40 100644 --- a/core/src/trezor/crypto/bech32.py +++ b/core/src/trezor/crypto/bech32.py @@ -20,11 +20,13 @@ """Reference implementation for Bech32 and segwit addresses.""" +if False: + from typing import List, Optional, Tuple CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l" -def bech32_polymod(values): +def bech32_polymod(values: List[int]) -> int: """Internal function that computes the Bech32 checksum.""" generator = [0x3B6A57B2, 0x26508E6D, 0x1EA119FA, 0x3D4233DD, 0x2A1462B3] chk = 1 @@ -36,30 +38,30 @@ def bech32_polymod(values): return chk -def bech32_hrp_expand(hrp): +def bech32_hrp_expand(hrp: str) -> List[int]: """Expand the HRP into values for checksum computation.""" return [ord(x) >> 5 for x in hrp] + [0] + [ord(x) & 31 for x in hrp] -def bech32_verify_checksum(hrp, data): +def bech32_verify_checksum(hrp: str, data: List[int]) -> bool: """Verify a checksum given HRP and converted data characters.""" return bech32_polymod(bech32_hrp_expand(hrp) + data) == 1 -def bech32_create_checksum(hrp, data): +def bech32_create_checksum(hrp: str, data: List[int]) -> List[int]: """Compute the checksum values given HRP and data.""" values = bech32_hrp_expand(hrp) + data polymod = bech32_polymod(values + [0, 0, 0, 0, 0, 0]) ^ 1 return [(polymod >> 5 * (5 - i)) & 31 for i in range(6)] -def bech32_encode(hrp, data): +def bech32_encode(hrp: str, data: List[int]) -> str: """Compute a Bech32 string given HRP and data values.""" combined = data + bech32_create_checksum(hrp, data) return hrp + "1" + "".join([CHARSET[d] for d in combined]) -def bech32_decode(bech): +def bech32_decode(bech: str) -> Tuple[Optional[str], Optional[List[int]]]: """Validate a Bech32 string, and determine HRP and data.""" if (any(ord(x) < 33 or ord(x) > 126 for x in bech)) or ( bech.lower() != bech and bech.upper() != bech @@ -78,7 +80,9 @@ def bech32_decode(bech): return (hrp, data[:-6]) -def convertbits(data, frombits, tobits, pad=True): +def convertbits( + data: List[int], frombits: int, tobits: int, pad: bool = True +) -> List[int]: """General power-of-2 base conversion.""" acc = 0 bits = 0 @@ -87,7 +91,7 @@ def convertbits(data, frombits, tobits, pad=True): max_acc = (1 << (frombits + tobits - 1)) - 1 for value in data: if value < 0 or (value >> frombits): - return None + raise ValueError acc = ((acc << frombits) | value) & max_acc bits += frombits while bits >= tobits: @@ -97,17 +101,17 @@ def convertbits(data, frombits, tobits, pad=True): if bits: ret.append((acc << (tobits - bits)) & maxv) elif bits >= frombits or ((acc << (tobits - bits)) & maxv): - return None + raise ValueError return ret -def decode(hrp, addr): +def decode(hrp: str, addr: str) -> Tuple[Optional[int], Optional[List[int]]]: """Decode a segwit address.""" hrpgot, data = bech32_decode(addr) - if hrpgot != hrp: + if data is None or hrpgot != hrp: return (None, None) decoded = convertbits(data[1:], 5, 8, False) - if decoded is None or len(decoded) < 2 or len(decoded) > 40: + if len(decoded) < 2 or len(decoded) > 40: return (None, None) if data[0] > 16: return (None, None) @@ -116,7 +120,7 @@ def decode(hrp, addr): return (data[0], decoded) -def encode(hrp, witver, witprog): +def encode(hrp: str, witver: int, witprog: List[int]) -> Optional[str]: """Encode a segwit address.""" ret = bech32_encode(hrp, [witver] + convertbits(witprog, 8, 5)) if decode(hrp, ret) == (None, None): diff --git a/core/src/trezor/crypto/cashaddr.py b/core/src/trezor/crypto/cashaddr.py index c8c8b576b..1ced926d4 100644 --- a/core/src/trezor/crypto/cashaddr.py +++ b/core/src/trezor/crypto/cashaddr.py @@ -20,12 +20,15 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. +if False: + from typing import Iterable, List, Tuple + CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l" ADDRESS_TYPE_P2KH = 0 ADDRESS_TYPE_P2SH = 8 -def cashaddr_polymod(values): +def cashaddr_polymod(values: List[int]) -> int: generator = [0x98F2BC8E61, 0x79B76D99E2, 0xF33E5FB3C4, 0xAE2EABE2A8, 0x1E4F43E470] chk = 1 for value in values: @@ -36,11 +39,11 @@ def cashaddr_polymod(values): return chk ^ 1 -def prefix_expand(prefix): +def prefix_expand(prefix: str) -> List[int]: return [ord(x) & 0x1F for x in prefix] + [0] -def calculate_checksum(prefix, payload): +def calculate_checksum(prefix: str, payload: List[int]) -> List[int]: poly = cashaddr_polymod(prefix_expand(prefix) + payload + [0, 0, 0, 0, 0, 0, 0, 0]) out = list() for i in range(8): @@ -48,25 +51,27 @@ def calculate_checksum(prefix, payload): return out -def verify_checksum(prefix, payload): +def verify_checksum(prefix: str, payload: List[int]) -> bool: return cashaddr_polymod(prefix_expand(prefix) + payload) == 0 -def b32decode(inputs): +def b32decode(inputs: str) -> List[int]: out = list() for letter in inputs: out.append(CHARSET.find(letter)) return out -def b32encode(inputs): +def b32encode(inputs: List[int]) -> str: out = "" for char_code in inputs: out += CHARSET[char_code] return out -def convertbits(data, frombits, tobits, pad=True): +def convertbits( + data: Iterable[int], frombits: int, tobits: int, pad: bool = True +) -> List[int]: acc = 0 bits = 0 ret = [] @@ -74,7 +79,7 @@ def convertbits(data, frombits, tobits, pad=True): max_acc = (1 << (frombits + tobits - 1)) - 1 for value in data: if value < 0 or (value >> frombits): - return None + raise ValueError acc = ((acc << frombits) | value) & max_acc bits += frombits while bits >= tobits: @@ -84,18 +89,18 @@ def convertbits(data, frombits, tobits, pad=True): if bits: ret.append((acc << (tobits - bits)) & maxv) elif bits >= frombits or ((acc << (tobits - bits)) & maxv): - return None + raise ValueError return ret -def encode(prefix, version, payload): - payload = bytes([version]) + payload - payload = convertbits(payload, 8, 5) +def encode(prefix: str, version: int, payload_bytes: bytes) -> str: + payload_bytes = bytes([version]) + payload_bytes + payload = convertbits(payload_bytes, 8, 5) checksum = calculate_checksum(prefix, payload) return prefix + ":" + b32encode(payload + checksum) -def decode(prefix, addr): +def decode(prefix: str, addr: str) -> Tuple[int, bytes]: addr = addr.lower() decoded = b32decode(addr) if not verify_checksum(prefix, decoded):