From 9cab61fbd37286b4ee996b48891000449ebdde76 Mon Sep 17 00:00:00 2001 From: matejcik Date: Mon, 16 Mar 2020 12:42:19 +0100 Subject: [PATCH] core/sign_tx: remove write_bytes_unchecked where appropriate --- core/src/apps/wallet/sign_tx/multisig.py | 6 +-- core/src/apps/wallet/sign_tx/scripts.py | 20 +++++--- core/src/apps/wallet/sign_tx/segwit_bip143.py | 21 +++++---- core/src/apps/wallet/sign_tx/signing.py | 7 ++- core/src/apps/wallet/sign_tx/writers.py | 30 ++++++++---- core/src/apps/wallet/sign_tx/zcash.py | 47 +++++++++++-------- 6 files changed, 79 insertions(+), 52 deletions(-) diff --git a/core/src/apps/wallet/sign_tx/multisig.py b/core/src/apps/wallet/sign_tx/multisig.py index 3c52473a8..5cbf62f2e 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_unchecked, write_uint32 +from apps.wallet.sign_tx.writers import write_bytes_fixed, 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_unchecked(h, d.chain_code) - write_bytes_unchecked(h, d.public_key) + write_bytes_fixed(h, d.chain_code, 32) + write_bytes_fixed(h, d.public_key, 33) 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 7fc69a4b4..b1495c785 100644 --- a/core/src/apps/wallet/sign_tx/scripts.py +++ b/core/src/apps/wallet/sign_tx/scripts.py @@ -4,7 +4,12 @@ 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_unchecked, write_op_push, write_varint +from apps.wallet.sign_tx.writers import ( + write_bytes_fixed, + write_bytes_unchecked, + write_op_push, + write_varint, +) class ScriptsError(ValueError): @@ -69,12 +74,13 @@ def output_script_native_p2wpkh_or_p2wsh(witprog: bytes) -> bytearray: # Either: # 00 14 <20-byte-key-hash> # 00 20 <32-byte-script-hash> - utils.ensure(len(witprog) == 20 or len(witprog) == 32) + length = len(witprog) + utils.ensure(length == 20 or length == 32) - w = empty_bytearray(3 + len(witprog)) + w = empty_bytearray(3 + length) w.append(0x00) # witness version byte - w.append(len(witprog)) # pub key hash length is 20 (P2WPKH) or 32 (P2WSH) bytes - write_bytes_unchecked(w, witprog) # pub key hash + w.append(length) # pub key hash length is 20 (P2WPKH) or 32 (P2WSH) bytes + write_bytes_fixed(w, witprog, length) # pub key hash return w @@ -95,7 +101,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_unchecked(w, pubkeyhash) # pub key hash + write_bytes_fixed(w, pubkeyhash, 20) # pub key hash return w @@ -118,7 +124,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_unchecked(w, script_hash) + write_bytes_fixed(w, script_hash, 32) 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 333c7bd66..40c26db7f 100644 --- a/core/src/apps/wallet/sign_tx/segwit_bip143.py +++ b/core/src/apps/wallet/sign_tx/segwit_bip143.py @@ -9,13 +9,14 @@ from apps.common.coininfo import CoinInfo 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 ( + TX_HASH_SIZE, get_tx_hash, - write_bytes_unchecked, + write_bytes_fixed, + write_bytes_prefixed, write_bytes_reversed, write_tx_output, write_uint32, write_uint64, - write_varint, ) @@ -30,7 +31,7 @@ class Bip143: self.h_outputs = HashWriter(sha256()) def add_prevouts(self, txi: TxInputType): - write_bytes_reversed(self.h_prevouts, txi.prev_hash) + write_bytes_reversed(self.h_prevouts, txi.prev_hash, TX_HASH_SIZE) write_uint32(self.h_prevouts, txi.prev_index) def add_sequence(self, txi: TxInputType): @@ -61,19 +62,21 @@ class Bip143: ensure(not coin.overwintered) write_uint32(h_preimage, tx.version) # nVersion - write_bytes_unchecked(h_preimage, self.get_prevouts_hash(coin)) # hashPrevouts - write_bytes_unchecked(h_preimage, self.get_sequence_hash(coin)) # hashSequence + # hashPrevouts + write_bytes_fixed(h_preimage, self.get_prevouts_hash(coin), TX_HASH_SIZE) + # hashSequence + write_bytes_fixed(h_preimage, self.get_sequence_hash(coin), TX_HASH_SIZE) - write_bytes_reversed(h_preimage, txi.prev_hash) # outpoint + write_bytes_reversed(h_preimage, txi.prev_hash, TX_HASH_SIZE) # 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_unchecked(h_preimage, script_code) + write_bytes_prefixed(h_preimage, script_code) write_uint64(h_preimage, txi.amount) # amount write_uint32(h_preimage, txi.sequence) # nSequence - write_bytes_unchecked(h_preimage, self.get_outputs_hash(coin)) # hashOutputs + # hashOutputs + write_bytes_fixed(h_preimage, self.get_outputs_hash(coin), TX_HASH_SIZE) 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 4a084fc57..3a2797a45 100644 --- a/core/src/apps/wallet/sign_tx/signing.py +++ b/core/src/apps/wallet/sign_tx/signing.py @@ -366,8 +366,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_unchecked(h_witness, prev_pkscript) + writers.write_bytes_prefixed(h_witness, prev_pkscript) else: writers.write_varint(h_witness, 0) @@ -377,8 +376,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_unchecked(h_sign, prefix_hash) - writers.write_bytes_unchecked(h_sign, witness_hash) + writers.write_bytes_fixed(h_sign, prefix_hash, writers.TX_HASH_SIZE) + writers.write_bytes_fixed(h_sign, witness_hash, writers.TX_HASH_SIZE) sig_hash = writers.get_tx_hash(h_sign, double=coin.sign_hash_double) signature = ecdsa_sign(key_sign, sig_hash) diff --git a/core/src/apps/wallet/sign_tx/writers.py b/core/src/apps/wallet/sign_tx/writers.py index d69b5b80c..5482457cf 100644 --- a/core/src/apps/wallet/sign_tx/writers.py +++ b/core/src/apps/wallet/sign_tx/writers.py @@ -1,3 +1,5 @@ +from micropython import const + from trezor.crypto.hashlib import sha256 from trezor.messages.TxInputType import TxInputType from trezor.messages.TxOutputBinType import TxOutputBinType @@ -5,29 +7,39 @@ from trezor.utils import ensure from apps.common.writers import ( # noqa: F401 empty_bytearray, - write_bytes_unchecked, + write_bytes_fixed, write_bytes_reversed, + write_bytes_unchecked, write_uint8, write_uint16_le, write_uint32_le, write_uint64_le, ) +if False: + from apps.common.writers import Writer + write_uint16 = write_uint16_le write_uint32 = write_uint32_le write_uint64 = write_uint64_le +TX_HASH_SIZE = const(32) + + +def write_bytes_prefixed(w: Writer, b: bytes) -> None: + write_varint(w, len(b)) + write_bytes_unchecked(w, b) + def write_tx_input(w, i: TxInputType): - write_bytes_reversed(w, i.prev_hash) + write_bytes_reversed(w, i.prev_hash, TX_HASH_SIZE) write_uint32(w, i.prev_index) - write_varint(w, len(i.script_sig)) - write_bytes_unchecked(w, i.script_sig) + write_bytes_prefixed(w, i.script_sig) write_uint32(w, i.sequence) def write_tx_input_check(w, i: TxInputType): - write_bytes_unchecked(w, i.prev_hash) + write_bytes_fixed(w, i.prev_hash, TX_HASH_SIZE) write_uint32(w, i.prev_index) write_uint32(w, i.script_type) write_uint32(w, len(i.address_n)) @@ -38,7 +50,7 @@ def write_tx_input_check(w, i: TxInputType): def write_tx_input_decred(w, i: TxInputType): - write_bytes_reversed(w, i.prev_hash) + write_bytes_reversed(w, i.prev_hash, TX_HASH_SIZE) write_uint32(w, i.prev_index or 0) write_uint8(w, i.decred_tree or 0) write_uint32(w, i.sequence) @@ -48,16 +60,14 @@ def write_tx_input_decred_witness(w, i: TxInputType): write_uint64(w, i.amount or 0) 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_unchecked(w, i.script_sig) + write_bytes_prefixed(w, i.script_sig) def write_tx_output(w, o: TxOutputBinType): write_uint64(w, o.amount) if o.decred_script_version is not None: write_uint16(w, o.decred_script_version) - write_varint(w, len(o.script_pubkey)) - write_bytes_unchecked(w, o.script_pubkey) + write_bytes_prefixed(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 c4b40d392..4f5c8e6ff 100644 --- a/core/src/apps/wallet/sign_tx/zcash.py +++ b/core/src/apps/wallet/sign_tx/zcash.py @@ -12,13 +12,14 @@ from apps.common.coininfo import CoinInfo 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 ( + TX_HASH_SIZE, get_tx_hash, - write_bytes_unchecked, + write_bytes_fixed, + write_bytes_prefixed, write_bytes_reversed, write_tx_output, write_uint32, write_uint64, - write_varint, ) OVERWINTERED = const(0x80000000) @@ -53,7 +54,7 @@ class Zip143: self.h_outputs = HashWriter(blake2b(outlen=32, personal=b"ZcashOutputsHash")) def add_prevouts(self, txi: TxInputType): - write_bytes_reversed(self.h_prevouts, txi.prev_hash) + write_bytes_reversed(self.h_prevouts, txi.prev_hash, TX_HASH_SIZE) write_uint32(self.h_prevouts, txi.prev_index) def add_sequence(self, txi: TxInputType): @@ -92,20 +93,23 @@ class Zip143: h_preimage, tx.version | OVERWINTERED ) # 1. nVersion | fOverwintered write_uint32(h_preimage, tx.version_group_id) # 2. nVersionGroupId - 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 + # 3. hashPrevouts + write_bytes_fixed(h_preimage, bytearray(self.get_prevouts_hash()), TX_HASH_SIZE) + # 4. hashSequence + write_bytes_fixed(h_preimage, bytearray(self.get_sequence_hash()), TX_HASH_SIZE) + # 5. hashOutputs + write_bytes_fixed(h_preimage, bytearray(self.get_outputs_hash()), TX_HASH_SIZE) + # 6. hashJoinSplits + write_bytes_fixed(h_preimage, b"\x00" * TX_HASH_SIZE, TX_HASH_SIZE) write_uint32(h_preimage, tx.lock_time) # 7. nLockTime write_uint32(h_preimage, tx.expiry) # 8. expiryHeight write_uint32(h_preimage, sighash) # 9. nHashType - write_bytes_reversed(h_preimage, txi.prev_hash) # 10a. outpoint + write_bytes_reversed(h_preimage, txi.prev_hash, TX_HASH_SIZE) # 10a. outpoint write_uint32(h_preimage, txi.prev_index) script_code = derive_script_code(txi, pubkeyhash) # 10b. scriptCode - write_varint(h_preimage, len(script_code)) - write_bytes_unchecked(h_preimage, script_code) + write_bytes_prefixed(h_preimage, script_code) write_uint64(h_preimage, txi.amount) # 10c. value @@ -139,23 +143,28 @@ class Zip243(Zip143): h_preimage, tx.version | OVERWINTERED ) # 1. nVersion | fOverwintered write_uint32(h_preimage, tx.version_group_id) # 2. nVersionGroupId - 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 + # 3. hashPrevouts + write_bytes_fixed(h_preimage, bytearray(self.get_prevouts_hash()), TX_HASH_SIZE) + # 4. hashSequence + write_bytes_fixed(h_preimage, bytearray(self.get_sequence_hash()), TX_HASH_SIZE) + # 5. hashOutputs + write_bytes_fixed(h_preimage, bytearray(self.get_outputs_hash()), TX_HASH_SIZE) + + zero_hash = b"\x00" * TX_HASH_SIZE + write_bytes_fixed(h_preimage, zero_hash, TX_HASH_SIZE) # 6. hashJoinSplits + write_bytes_fixed(h_preimage, zero_hash, TX_HASH_SIZE) # 7. hashShieldedSpends + write_bytes_fixed(h_preimage, zero_hash, TX_HASH_SIZE) # 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 write_uint32(h_preimage, sighash) # 12. nHashType - write_bytes_reversed(h_preimage, txi.prev_hash) # 13a. outpoint + write_bytes_reversed(h_preimage, txi.prev_hash, TX_HASH_SIZE) # 13a. outpoint write_uint32(h_preimage, txi.prev_index) script_code = derive_script_code(txi, pubkeyhash) # 13b. scriptCode - write_varint(h_preimage, len(script_code)) - write_bytes_unchecked(h_preimage, script_code) + write_bytes_prefixed(h_preimage, script_code) write_uint64(h_preimage, txi.amount) # 13c. value