From 27f6306e1dc34d7acbe3d0e3391e4825c67755b4 Mon Sep 17 00:00:00 2001 From: matejcik Date: Mon, 16 Mar 2020 11:31:11 +0100 Subject: [PATCH] core: introduce safer write_bytes functions --- core/src/apps/common/writers.py | 13 +++++++-- core/src/apps/eos/actions/__init__.py | 6 ++-- core/src/apps/eos/sign_tx.py | 4 +-- core/src/apps/eos/writers.py | 8 +++--- core/src/apps/nem/writers.py | 4 +-- core/src/apps/stellar/operations/serialize.py | 6 ++-- core/src/apps/stellar/sign_tx.py | 6 ++-- core/src/apps/stellar/writers.py | 8 +++--- core/src/apps/tezos/helpers.py | 4 +-- core/src/apps/tezos/sign_tx.py | 28 +++++++++---------- core/src/apps/wallet/sign_tx/multisig.py | 6 ++-- core/src/apps/wallet/sign_tx/scripts.py | 12 ++++---- core/src/apps/wallet/sign_tx/segwit_bip143.py | 10 +++---- core/src/apps/wallet/sign_tx/signing.py | 20 +++++++------ core/src/apps/wallet/sign_tx/writers.py | 10 +++---- core/src/apps/wallet/sign_tx/zcash.py | 26 ++++++++--------- core/tests/test_apps.wallet.address.py | 2 +- 17 files changed, 91 insertions(+), 82 deletions(-) diff --git a/core/src/apps/common/writers.py b/core/src/apps/common/writers.py index ec23c2518..118757d36 100644 --- a/core/src/apps/common/writers.py +++ b/core/src/apps/common/writers.py @@ -78,11 +78,18 @@ def write_uint64_be(w: Writer, n: int) -> int: return 8 -def write_bytes(w: Writer, b: bytes) -> int: +def write_bytes_unchecked(w: Writer, b: bytes) -> int: w.extend(b) return len(b) -def write_bytes_reversed(w: Writer, b: bytes) -> int: +def write_bytes_fixed(w: Writer, b: bytes, length: int) -> int: + ensure(len(b) == length) + w.extend(b) + return length + + +def write_bytes_reversed(w: Writer, b: bytes, length: int) -> int: + ensure(len(b) == length) w.extend(bytes(reversed(b))) - return len(b) + return length diff --git a/core/src/apps/eos/actions/__init__.py b/core/src/apps/eos/actions/__init__.py index 8adf5ccfb..8f43ac747 100644 --- a/core/src/apps/eos/actions/__init__.py +++ b/core/src/apps/eos/actions/__init__.py @@ -68,7 +68,7 @@ async def process_action( writers.write_action_common(sha, action.common) writers.write_variant32(sha, len(w)) - writers.write_bytes(sha, w) + writers.write_bytes_unchecked(sha, w) async def process_unknown_action( @@ -78,7 +78,7 @@ async def process_unknown_action( writers.write_variant32(checksum, action.unknown.data_size) checksum.extend(action.unknown.data_chunk) - writers.write_bytes(w, action.unknown.data_chunk) + writers.write_bytes_unchecked(w, action.unknown.data_chunk) bytes_left = action.unknown.data_size - len(action.unknown.data_chunk) while bytes_left != 0: @@ -90,7 +90,7 @@ async def process_unknown_action( raise ValueError("Bad response. Unknown struct expected.") checksum.extend(action.unknown.data_chunk) - writers.write_bytes(w, action.unknown.data_chunk) + writers.write_bytes_unchecked(w, action.unknown.data_chunk) bytes_left -= len(action.unknown.data_chunk) if bytes_left < 0: diff --git a/core/src/apps/eos/sign_tx.py b/core/src/apps/eos/sign_tx.py index db82da859..e47bc23b5 100644 --- a/core/src/apps/eos/sign_tx.py +++ b/core/src/apps/eos/sign_tx.py @@ -34,7 +34,7 @@ async def sign_tx( await _init(ctx, sha, msg) await _actions(ctx, sha, msg.num_actions) writers.write_variant32(sha, 0) - writers.write_bytes(sha, bytearray(32)) + writers.write_bytes_unchecked(sha, bytearray(32)) digest = sha.get_digest() signature = secp256k1.sign( @@ -45,7 +45,7 @@ async def sign_tx( async def _init(ctx: wire.Context, sha: HashWriter, msg: EosSignTx) -> None: - writers.write_bytes(sha, msg.chain_id) + writers.write_bytes_unchecked(sha, msg.chain_id) writers.write_header(sha, msg.header) writers.write_variant32(sha, 0) writers.write_variant32(sha, msg.num_actions) diff --git a/core/src/apps/eos/writers.py b/core/src/apps/eos/writers.py index 81ea92912..fc6cf589a 100644 --- a/core/src/apps/eos/writers.py +++ b/core/src/apps/eos/writers.py @@ -1,5 +1,5 @@ from apps.common.writers import ( - write_bytes, + write_bytes_unchecked, write_uint8, write_uint16_le, write_uint32_le, @@ -31,7 +31,7 @@ def write_auth(w: Writer, auth: EosAuthorization) -> None: write_variant32(w, len(auth.keys)) for key in auth.keys: write_variant32(w, key.type) - write_bytes(w, key.key) + write_bytes_unchecked(w, key.key) write_uint16_le(w, key.weight) write_variant32(w, len(auth.accounts)) @@ -60,7 +60,7 @@ def write_action_transfer(w: Writer, msg: EosActionTransfer) -> None: write_uint64_le(w, msg.receiver) write_asset(w, msg.quantity) write_variant32(w, len(msg.memo)) - write_bytes(w, msg.memo) + write_bytes_unchecked(w, msg.memo) def write_action_buyram(w: Writer, msg: EosActionBuyRam) -> None: @@ -162,4 +162,4 @@ def write_variant32(w: Writer, value: int) -> None: variant.append(b) if value == 0: break - write_bytes(w, bytes(variant)) + write_bytes_unchecked(w, bytes(variant)) diff --git a/core/src/apps/nem/writers.py b/core/src/apps/nem/writers.py index cd0e28c5a..f049a8512 100644 --- a/core/src/apps/nem/writers.py +++ b/core/src/apps/nem/writers.py @@ -1,6 +1,6 @@ from trezor.messages.NEMTransactionCommon import NEMTransactionCommon -from apps.common.writers import write_bytes, write_uint32_le, write_uint64_le +from apps.common.writers import write_bytes_unchecked, write_uint32_le, write_uint64_le def serialize_tx_common( @@ -26,4 +26,4 @@ def serialize_tx_common( def write_bytes_with_len(w, buf: bytes): write_uint32_le(w, len(buf)) - write_bytes(w, buf) + write_bytes_unchecked(w, buf) diff --git a/core/src/apps/stellar/operations/serialize.py b/core/src/apps/stellar/operations/serialize.py index 10b34f38c..2ab3e8e5d 100644 --- a/core/src/apps/stellar/operations/serialize.py +++ b/core/src/apps/stellar/operations/serialize.py @@ -119,7 +119,7 @@ def write_set_options_op(w, msg: StellarSetOptionsOp): elif msg.signer_type in consts.SIGN_TYPES: writers.write_bool(w, True) writers.write_uint32(w, msg.signer_type) - writers.write_bytes(w, msg.signer_key) + writers.write_bytes_unchecked(w, msg.signer_key) writers.write_uint32(w, msg.signer_weight) else: raise ProcessError("Stellar: unknown signer type") @@ -146,10 +146,10 @@ def _write_asset_code(w, asset_type: int, asset_code: str): return # nothing is needed elif asset_type == consts.ASSET_TYPE_ALPHANUM4: # pad with zeros to 4 chars - writers.write_bytes(w, code + bytearray([0] * (4 - len(code)))) + writers.write_bytes_unchecked(w, code + bytearray([0] * (4 - len(code)))) elif asset_type == consts.ASSET_TYPE_ALPHANUM12: # pad with zeros to 12 chars - writers.write_bytes(w, code + bytearray([0] * (12 - len(code)))) + writers.write_bytes_unchecked(w, code + bytearray([0] * (12 - len(code)))) else: raise ProcessError("Stellar: invalid asset type") diff --git a/core/src/apps/stellar/sign_tx.py b/core/src/apps/stellar/sign_tx.py index c77b99e81..13e3ad121 100644 --- a/core/src/apps/stellar/sign_tx.py +++ b/core/src/apps/stellar/sign_tx.py @@ -47,8 +47,8 @@ async def _final(ctx, w: bytearray, msg: StellarSignTx): async def _init(ctx, w: bytearray, pubkey: bytes, msg: StellarSignTx): network_passphrase_hash = sha256(msg.network_passphrase).digest() - writers.write_bytes(w, network_passphrase_hash) - writers.write_bytes(w, consts.TX_TYPE) + writers.write_bytes_unchecked(w, network_passphrase_hash) + writers.write_bytes_unchecked(w, consts.TX_TYPE) address = helpers.address_from_public_key(pubkey) accounts_match = msg.source_account == address @@ -103,7 +103,7 @@ async def _memo(ctx, w: bytearray, msg: StellarSignTx): memo_confirm_text = str(msg.memo_id) elif msg.memo_type in (consts.MEMO_TYPE_HASH, consts.MEMO_TYPE_RETURN): # Hash/Return: 32 byte hash - writers.write_bytes(w, bytearray(msg.memo_hash)) + writers.write_bytes_unchecked(w, bytearray(msg.memo_hash)) memo_confirm_text = hexlify(msg.memo_hash).decode() else: raise ProcessError("Stellar invalid memo type") diff --git a/core/src/apps/stellar/writers.py b/core/src/apps/stellar/writers.py index 0846d148f..72f25492b 100644 --- a/core/src/apps/stellar/writers.py +++ b/core/src/apps/stellar/writers.py @@ -1,6 +1,6 @@ from .helpers import public_key_from_address -from apps.common.writers import write_bytes, write_uint32_be, write_uint64_be +from apps.common.writers import write_bytes_unchecked, write_uint32_be, write_uint64_be write_uint32 = write_uint32_be write_uint64 = write_uint64_be @@ -16,11 +16,11 @@ def write_string(w, s: AnyStr) -> None: else: buf = s write_uint32(w, len(buf)) - write_bytes(w, buf) + write_bytes_unchecked(w, buf) # if len isn't a multiple of 4, add padding bytes reminder = len(buf) % 4 if reminder: - write_bytes(w, bytes([0] * (4 - reminder))) + write_bytes_unchecked(w, bytes([0] * (4 - reminder))) def write_bool(w, val: bool): @@ -33,4 +33,4 @@ def write_bool(w, val: bool): def write_pubkey(w, address: str): # first 4 bytes of an address are the type, there's only one type (0) write_uint32(w, 0) - write_bytes(w, public_key_from_address(address)) + write_bytes_unchecked(w, public_key_from_address(address)) diff --git a/core/src/apps/tezos/helpers.py b/core/src/apps/tezos/helpers.py index 1b18e8d5b..a2f0fec28 100644 --- a/core/src/apps/tezos/helpers.py +++ b/core/src/apps/tezos/helpers.py @@ -3,7 +3,7 @@ from micropython import const from trezor.crypto import base58 from apps.common import HARDENED -from apps.common.writers import write_uint8, write_bytes +from apps.common.writers import write_bytes_unchecked, write_uint8 TEZOS_AMOUNT_DECIMALS = const(6) TEZOS_ED25519_ADDRESS_PREFIX = "tz1" @@ -99,4 +99,4 @@ def write_bool(w: bytearray, boolean: bool): def write_instruction(w: bytearray, instruction: str) -> int: - write_bytes(w, MICHELSON_INSTRUCTION_BYTES[instruction]) + write_bytes_unchecked(w, MICHELSON_INSTRUCTION_BYTES[instruction]) diff --git a/core/src/apps/tezos/sign_tx.py b/core/src/apps/tezos/sign_tx.py index dcae86b76..3fcb06ce4 100644 --- a/core/src/apps/tezos/sign_tx.py +++ b/core/src/apps/tezos/sign_tx.py @@ -7,7 +7,7 @@ from trezor.messages import TezosBallotType, TezosContractType from trezor.messages.TezosSignedTx import TezosSignedTx from apps.common import paths -from apps.common.writers import write_bytes, write_uint8, write_uint32_be +from apps.common.writers import write_bytes_unchecked, write_uint8, write_uint32_be from apps.tezos import CURVE, helpers, layout PROPOSAL_LENGTH = const(32) @@ -157,13 +157,13 @@ def _get_ballot(ballot): def _get_operation_bytes(w: bytearray, msg): - write_bytes(w, msg.branch) + write_bytes_unchecked(w, msg.branch) # when the account sends first operation in lifetime, # we need to reveal its public key if msg.reveal is not None: _encode_common(w, msg.reveal, "reveal") - write_bytes(w, msg.reveal.public_key) + write_bytes_unchecked(w, msg.reveal.public_key) # transaction operation if msg.transaction is not None: @@ -194,7 +194,7 @@ def _get_operation_bytes(w: bytearray, msg): _encode_common(w, msg.origination, "origination") _encode_zarith(w, msg.origination.balance) _encode_data_with_bool_prefix(w, msg.origination.delegate) - write_bytes(w, msg.origination.script) + write_bytes_unchecked(w, msg.origination.script) # delegation operation elif msg.delegation is not None: @@ -214,7 +214,7 @@ def _encode_common(w: bytearray, operation, str_operation): "delegation": 110, } write_uint8(w, operation_tags[str_operation]) - write_bytes(w, operation.source) + write_bytes_unchecked(w, operation.source) _encode_zarith(w, operation.fee) _encode_zarith(w, operation.counter) _encode_zarith(w, operation.gas_limit) @@ -223,13 +223,13 @@ def _encode_common(w: bytearray, operation, str_operation): def _encode_contract_id(w: bytearray, contract_id): write_uint8(w, contract_id.tag) - write_bytes(w, contract_id.hash) + write_bytes_unchecked(w, contract_id.hash) def _encode_data_with_bool_prefix(w: bytearray, data): if data: helpers.write_bool(w, True) - write_bytes(w, data) + write_bytes_unchecked(w, data) else: helpers.write_bool(w, False) @@ -250,20 +250,20 @@ def _encode_proposal(w: bytearray, proposal): proposal_tag = 5 write_uint8(w, proposal_tag) - write_bytes(w, proposal.source) + write_bytes_unchecked(w, proposal.source) write_uint32_be(w, proposal.period) write_uint32_be(w, len(proposal.proposals) * PROPOSAL_LENGTH) for proposal_hash in proposal.proposals: - write_bytes(w, proposal_hash) + write_bytes_unchecked(w, proposal_hash) def _encode_ballot(w: bytearray, ballot): ballot_tag = 6 write_uint8(w, ballot_tag) - write_bytes(w, ballot.source) + write_bytes_unchecked(w, ballot.source) write_uint32_be(w, ballot.period) - write_bytes(w, ballot.proposal) + write_bytes_unchecked(w, ballot.proposal) write_uint8(w, ballot.ballot) @@ -304,7 +304,7 @@ def _encode_manager_common(w: bytearray, sequence_length, operation, to_contract else: helpers.write_instruction(w, "key_hash") if operation == "PUSH": - write_bytes(w, bytes([10])) # byte sequence + write_bytes_unchecked(w, bytes([10])) # byte sequence if to_contract is True: write_uint32_be(w, SMART_CONTRACT_ADDRESS_LENGTH) else: @@ -319,7 +319,7 @@ def _encode_manager_to_implicit_transfer(w: bytearray, manager_transfer): sequence_length = MICHELSON_LENGTH + len(value_natural) _encode_manager_common(w, sequence_length, "PUSH") - write_bytes(w, manager_transfer.destination.hash) + write_bytes_unchecked(w, manager_transfer.destination.hash) helpers.write_instruction(w, "IMPLICIT_ACCOUNT") helpers.write_instruction(w, "PUSH") helpers.write_instruction(w, "mutez") @@ -334,7 +334,7 @@ def _encode_manager_delegation(w: bytearray, delegate): MICHELSON_LENGTH = 42 # length is fixed this time(no variable length fields) _encode_manager_common(w, MICHELSON_LENGTH, "PUSH") - write_bytes(w, delegate) + write_bytes_unchecked(w, delegate) helpers.write_instruction(w, "SOME") helpers.write_instruction(w, "SET_DELEGATE") helpers.write_instruction(w, "CONS") diff --git a/core/src/apps/wallet/sign_tx/multisig.py b/core/src/apps/wallet/sign_tx/multisig.py index aa474e786..3c52473a8 100644 --- a/core/src/apps/wallet/sign_tx/multisig.py +++ b/core/src/apps/wallet/sign_tx/multisig.py @@ -5,7 +5,7 @@ from trezor.messages.HDNodeType import HDNodeType from trezor.messages.MultisigRedeemScriptType import MultisigRedeemScriptType from trezor.utils import HashWriter, ensure -from apps.wallet.sign_tx.writers import write_bytes, write_uint32 +from apps.wallet.sign_tx.writers import write_bytes_unchecked, write_uint32 class MultisigError(ValueError): @@ -59,8 +59,8 @@ def multisig_fingerprint(multisig: MultisigRedeemScriptType) -> bytes: 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) + write_bytes_unchecked(h, d.chain_code) + write_bytes_unchecked(h, d.public_key) return h.get_digest() diff --git a/core/src/apps/wallet/sign_tx/scripts.py b/core/src/apps/wallet/sign_tx/scripts.py index c6f71b1cf..7fc69a4b4 100644 --- a/core/src/apps/wallet/sign_tx/scripts.py +++ b/core/src/apps/wallet/sign_tx/scripts.py @@ -4,7 +4,7 @@ from trezor.messages.MultisigRedeemScriptType import MultisigRedeemScriptType from apps.common.coininfo import CoinInfo from apps.common.writers import empty_bytearray from apps.wallet.sign_tx.multisig import multisig_get_pubkey_count, multisig_get_pubkeys -from apps.wallet.sign_tx.writers import write_bytes, write_op_push, write_varint +from apps.wallet.sign_tx.writers import write_bytes_unchecked, write_op_push, write_varint class ScriptsError(ValueError): @@ -74,7 +74,7 @@ def output_script_native_p2wpkh_or_p2wsh(witprog: bytes) -> bytearray: w = empty_bytearray(3 + len(witprog)) w.append(0x00) # witness version byte w.append(len(witprog)) # pub key hash length is 20 (P2WPKH) or 32 (P2WSH) bytes - write_bytes(w, witprog) # pub key hash + write_bytes_unchecked(w, witprog) # pub key hash return w @@ -95,7 +95,7 @@ def input_script_p2wpkh_in_p2sh(pubkeyhash: bytes) -> bytearray: 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 + write_bytes_unchecked(w, pubkeyhash) # pub key hash return w @@ -118,7 +118,7 @@ def input_script_p2wsh_in_p2sh(script_hash: bytes) -> bytearray: 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) + write_bytes_unchecked(w, script_hash) return w @@ -272,12 +272,12 @@ def output_script_paytoopreturn(data: bytes) -> bytearray: def append_signature(w: bytearray, signature: bytes, sighash: int) -> bytearray: write_op_push(w, len(signature) + 1) - write_bytes(w, signature) + write_bytes_unchecked(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) + write_bytes_unchecked(w, pubkey) return w diff --git a/core/src/apps/wallet/sign_tx/segwit_bip143.py b/core/src/apps/wallet/sign_tx/segwit_bip143.py index a92d4a847..333c7bd66 100644 --- a/core/src/apps/wallet/sign_tx/segwit_bip143.py +++ b/core/src/apps/wallet/sign_tx/segwit_bip143.py @@ -10,7 +10,7 @@ from apps.wallet.sign_tx.multisig import multisig_get_pubkeys from apps.wallet.sign_tx.scripts import output_script_multisig, output_script_p2pkh from apps.wallet.sign_tx.writers import ( get_tx_hash, - write_bytes, + write_bytes_unchecked, write_bytes_reversed, write_tx_output, write_uint32, @@ -61,19 +61,19 @@ class Bip143: ensure(not coin.overwintered) write_uint32(h_preimage, tx.version) # nVersion - write_bytes(h_preimage, self.get_prevouts_hash(coin)) # hashPrevouts - write_bytes(h_preimage, self.get_sequence_hash(coin)) # hashSequence + write_bytes_unchecked(h_preimage, self.get_prevouts_hash(coin)) # hashPrevouts + write_bytes_unchecked(h_preimage, self.get_sequence_hash(coin)) # hashSequence write_bytes_reversed(h_preimage, txi.prev_hash) # outpoint write_uint32(h_preimage, txi.prev_index) # outpoint script_code = self.derive_script_code(txi, pubkeyhash) # scriptCode write_varint(h_preimage, len(script_code)) - write_bytes(h_preimage, script_code) + write_bytes_unchecked(h_preimage, script_code) write_uint64(h_preimage, txi.amount) # amount write_uint32(h_preimage, txi.sequence) # nSequence - write_bytes(h_preimage, self.get_outputs_hash(coin)) # hashOutputs + write_bytes_unchecked(h_preimage, self.get_outputs_hash(coin)) # hashOutputs write_uint32(h_preimage, tx.lock_time) # nLockTime write_uint32(h_preimage, sighash) # nHashType diff --git a/core/src/apps/wallet/sign_tx/signing.py b/core/src/apps/wallet/sign_tx/signing.py index eba73e089..4a084fc57 100644 --- a/core/src/apps/wallet/sign_tx/signing.py +++ b/core/src/apps/wallet/sign_tx/signing.py @@ -151,7 +151,7 @@ async def check_tx_fee(tx: SignTx, keychain: seed.Keychain, coin: coininfo.CoinI w_txi = writers.empty_bytearray(8 if i == 0 else 0 + 9 + len(txi.prev_hash)) if i == 0: # serializing first input => prepend headers # decred doesn't support segwit - writers.write_bytes(w_txi, get_tx_header(coin, tx, False)) + writers.write_bytes_unchecked(w_txi, get_tx_header(coin, tx, False)) writers.write_tx_input_decred(w_txi, txi) tx_ser.serialized_tx = w_txi tx_req.serialized = tx_ser @@ -281,7 +281,7 @@ async def sign_tx(tx: SignTx, keychain: seed.Keychain): 7 + len(txi_sign.prev_hash) + 4 + len(txi_sign.script_sig) + 4 ) if i_sign == 0: # serializing first input => prepend headers - writers.write_bytes(w_txi, get_tx_header(coin, tx, True)) + writers.write_bytes_unchecked(w_txi, get_tx_header(coin, tx, True)) writers.write_tx_input(w_txi, txi_sign) tx_ser.serialized_tx = w_txi tx_ser.signature_index = None @@ -331,7 +331,7 @@ async def sign_tx(tx: SignTx, keychain: seed.Keychain): 5 + len(txi_sign.prev_hash) + 4 + len(txi_sign.script_sig) + 4 ) if i_sign == 0: # serializing first input => prepend headers - writers.write_bytes(w_txi_sign, get_tx_header(coin, tx, any_segwit)) + writers.write_bytes_unchecked(w_txi_sign, get_tx_header(coin, tx, any_segwit)) writers.write_tx_input(w_txi_sign, txi_sign) tx_ser.serialized_tx = w_txi_sign @@ -367,7 +367,7 @@ async def sign_tx(tx: SignTx, keychain: seed.Keychain): for ii in range(tx.inputs_count): if ii == i_sign: writers.write_varint(h_witness, len(prev_pkscript)) - writers.write_bytes(h_witness, prev_pkscript) + writers.write_bytes_unchecked(h_witness, prev_pkscript) else: writers.write_varint(h_witness, 0) @@ -377,8 +377,8 @@ async def sign_tx(tx: SignTx, keychain: seed.Keychain): h_sign = utils.HashWriter(blake256()) writers.write_uint32(h_sign, decred.DECRED_SIGHASHALL) - writers.write_bytes(h_sign, prefix_hash) - writers.write_bytes(h_sign, witness_hash) + writers.write_bytes_unchecked(h_sign, prefix_hash) + writers.write_bytes_unchecked(h_sign, witness_hash) sig_hash = writers.get_tx_hash(h_sign, double=coin.sign_hash_double) signature = ecdsa_sign(key_sign, sig_hash) @@ -397,7 +397,9 @@ async def sign_tx(tx: SignTx, keychain: seed.Keychain): ) if i_sign == 0: - writers.write_bytes(w_txi_sign, hash143.get_last_output_bytes()) + writers.write_bytes_unchecked( + w_txi_sign, hash143.get_last_output_bytes() + ) writers.write_uint32(w_txi_sign, tx.lock_time) writers.write_uint32(w_txi_sign, tx.expiry) writers.write_varint(w_txi_sign, tx.inputs_count) @@ -486,7 +488,7 @@ async def sign_tx(tx: SignTx, keychain: seed.Keychain): 5 + len(txi_sign.prev_hash) + 4 + len(txi_sign.script_sig) + 4 ) if i_sign == 0: # serializing first input => prepend headers - writers.write_bytes(w_txi_sign, get_tx_header(coin, tx, any_segwit)) + writers.write_bytes_unchecked(w_txi_sign, get_tx_header(coin, tx, any_segwit)) writers.write_tx_input(w_txi_sign, txi_sign) tx_ser.serialized_tx = w_txi_sign @@ -652,7 +654,7 @@ async def get_prevtx_output_value( while ofs < tx.extra_data_len: size = min(1024, tx.extra_data_len - ofs) data = await helpers.request_tx_extra_data(tx_req, ofs, size, prev_hash) - writers.write_bytes(txh, data) + writers.write_bytes_unchecked(txh, data) ofs += len(data) if ( diff --git a/core/src/apps/wallet/sign_tx/writers.py b/core/src/apps/wallet/sign_tx/writers.py index 5a0d0d29d..d69b5b80c 100644 --- a/core/src/apps/wallet/sign_tx/writers.py +++ b/core/src/apps/wallet/sign_tx/writers.py @@ -5,7 +5,7 @@ from trezor.utils import ensure from apps.common.writers import ( # noqa: F401 empty_bytearray, - write_bytes, + write_bytes_unchecked, write_bytes_reversed, write_uint8, write_uint16_le, @@ -22,12 +22,12 @@ def write_tx_input(w, i: TxInputType): write_bytes_reversed(w, i.prev_hash) write_uint32(w, i.prev_index) write_varint(w, len(i.script_sig)) - write_bytes(w, i.script_sig) + write_bytes_unchecked(w, i.script_sig) write_uint32(w, i.sequence) def write_tx_input_check(w, i: TxInputType): - write_bytes(w, i.prev_hash) + write_bytes_unchecked(w, i.prev_hash) write_uint32(w, i.prev_index) write_uint32(w, i.script_type) write_uint32(w, len(i.address_n)) @@ -49,7 +49,7 @@ def write_tx_input_decred_witness(w, i: TxInputType): write_uint32(w, 0) # block height fraud proof write_uint32(w, 0xFFFFFFFF) # block index fraud proof write_varint(w, len(i.script_sig)) - write_bytes(w, i.script_sig) + write_bytes_unchecked(w, i.script_sig) def write_tx_output(w, o: TxOutputBinType): @@ -57,7 +57,7 @@ def write_tx_output(w, o: TxOutputBinType): if o.decred_script_version is not None: write_uint16(w, o.decred_script_version) write_varint(w, len(o.script_pubkey)) - write_bytes(w, o.script_pubkey) + write_bytes_unchecked(w, o.script_pubkey) def write_op_push(w, n: int): diff --git a/core/src/apps/wallet/sign_tx/zcash.py b/core/src/apps/wallet/sign_tx/zcash.py index d0776fa3f..c4b40d392 100644 --- a/core/src/apps/wallet/sign_tx/zcash.py +++ b/core/src/apps/wallet/sign_tx/zcash.py @@ -13,7 +13,7 @@ from apps.wallet.sign_tx.multisig import multisig_get_pubkeys from apps.wallet.sign_tx.scripts import output_script_multisig, output_script_p2pkh from apps.wallet.sign_tx.writers import ( get_tx_hash, - write_bytes, + write_bytes_unchecked, write_bytes_reversed, write_tx_output, write_uint32, @@ -92,10 +92,10 @@ class Zip143: h_preimage, tx.version | OVERWINTERED ) # 1. nVersion | fOverwintered write_uint32(h_preimage, tx.version_group_id) # 2. nVersionGroupId - write_bytes(h_preimage, bytearray(self.get_prevouts_hash())) # 3. hashPrevouts - write_bytes(h_preimage, bytearray(self.get_sequence_hash())) # 4. hashSequence - write_bytes(h_preimage, bytearray(self.get_outputs_hash())) # 5. hashOutputs - write_bytes(h_preimage, b"\x00" * 32) # 6. hashJoinSplits + write_bytes_unchecked(h_preimage, bytearray(self.get_prevouts_hash())) # 3. hashPrevouts + write_bytes_unchecked(h_preimage, bytearray(self.get_sequence_hash())) # 4. hashSequence + write_bytes_unchecked(h_preimage, bytearray(self.get_outputs_hash())) # 5. hashOutputs + write_bytes_unchecked(h_preimage, b"\x00" * 32) # 6. hashJoinSplits write_uint32(h_preimage, tx.lock_time) # 7. nLockTime write_uint32(h_preimage, tx.expiry) # 8. expiryHeight write_uint32(h_preimage, sighash) # 9. nHashType @@ -105,7 +105,7 @@ class Zip143: script_code = derive_script_code(txi, pubkeyhash) # 10b. scriptCode write_varint(h_preimage, len(script_code)) - write_bytes(h_preimage, script_code) + write_bytes_unchecked(h_preimage, script_code) write_uint64(h_preimage, txi.amount) # 10c. value @@ -139,12 +139,12 @@ class Zip243(Zip143): h_preimage, tx.version | OVERWINTERED ) # 1. nVersion | fOverwintered write_uint32(h_preimage, tx.version_group_id) # 2. nVersionGroupId - write_bytes(h_preimage, bytearray(self.get_prevouts_hash())) # 3. hashPrevouts - write_bytes(h_preimage, bytearray(self.get_sequence_hash())) # 4. hashSequence - write_bytes(h_preimage, bytearray(self.get_outputs_hash())) # 5. hashOutputs - write_bytes(h_preimage, b"\x00" * 32) # 6. hashJoinSplits - write_bytes(h_preimage, b"\x00" * 32) # 7. hashShieldedSpends - write_bytes(h_preimage, b"\x00" * 32) # 8. hashShieldedOutputs + write_bytes_unchecked(h_preimage, bytearray(self.get_prevouts_hash())) # 3. hashPrevouts + write_bytes_unchecked(h_preimage, bytearray(self.get_sequence_hash())) # 4. hashSequence + write_bytes_unchecked(h_preimage, bytearray(self.get_outputs_hash())) # 5. hashOutputs + write_bytes_unchecked(h_preimage, b"\x00" * 32) # 6. hashJoinSplits + write_bytes_unchecked(h_preimage, b"\x00" * 32) # 7. hashShieldedSpends + write_bytes_unchecked(h_preimage, b"\x00" * 32) # 8. hashShieldedOutputs write_uint32(h_preimage, tx.lock_time) # 9. nLockTime write_uint32(h_preimage, tx.expiry) # 10. expiryHeight write_uint64(h_preimage, 0) # 11. valueBalance @@ -155,7 +155,7 @@ class Zip243(Zip143): script_code = derive_script_code(txi, pubkeyhash) # 13b. scriptCode write_varint(h_preimage, len(script_code)) - write_bytes(h_preimage, script_code) + write_bytes_unchecked(h_preimage, script_code) write_uint64(h_preimage, txi.amount) # 13c. value diff --git a/core/tests/test_apps.wallet.address.py b/core/tests/test_apps.wallet.address.py index d7df64013..ad42e47ca 100644 --- a/core/tests/test_apps.wallet.address.py +++ b/core/tests/test_apps.wallet.address.py @@ -71,7 +71,7 @@ class TestAddress(unittest.TestCase): # pubkey OP_CHECKSIG script = unhexlify('210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798ac') h = HashWriter(sha256()) - write_bytes(h, script) + write_bytes_unchecked(h, script) address = address_p2wsh( h.get_digest(),