diff --git a/core/src/apps/bitcoin/scripts.py b/core/src/apps/bitcoin/scripts.py index 451f1b75a..0fbe73607 100644 --- a/core/src/apps/bitcoin/scripts.py +++ b/core/src/apps/bitcoin/scripts.py @@ -16,11 +16,7 @@ from .multisig import ( multisig_get_pubkeys, multisig_pubkey_index, ) -from .writers import ( - write_bytes_fixed, - write_bytes_unchecked, - write_op_push, -) +from .writers import write_bytes_fixed, write_bytes_unchecked, write_op_push if False: from typing import List, Optional @@ -248,7 +244,7 @@ def input_script_p2wsh_in_p2sh(script_hash: bytes) -> bytearray: 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 + write_bitcoin_varint(w, 0x02) # num of segwit items, in P2WPKH it's always 2 append_signature(w, signature, sighash) append_pubkey(w, pubkey) return w @@ -287,17 +283,17 @@ def witness_p2wsh( w = empty_bytearray(total_length) - write_varint(w, num_of_witness_items) + write_bitcoin_varint(w, num_of_witness_items) # 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 - write_varint(w, 0) + write_bitcoin_varint(w, 0) for s in signatures: append_signature(w, s, sighash) # size of the witness included # redeem script - write_varint(w, redeem_script_length) + write_bitcoin_varint(w, redeem_script_length) write_output_script_multisig(w, pubkeys, multisig.m) return w diff --git a/core/src/apps/bitcoin/sign_tx/bitcoin.py b/core/src/apps/bitcoin/sign_tx/bitcoin.py index 8480cceee..06755153c 100644 --- a/core/src/apps/bitcoin/sign_tx/bitcoin.py +++ b/core/src/apps/bitcoin/sign_tx/bitcoin.py @@ -139,7 +139,7 @@ class Bitcoin: async def step4_serialize_inputs(self) -> None: self.write_tx_header(self.serialized_tx, self.tx, bool(self.segwit)) - writers.write_varint(self.serialized_tx, self.tx.inputs_count) + write_bitcoin_varint(self.serialized_tx, self.tx.inputs_count) for i in range(self.tx.inputs_count): progress.advance() @@ -149,7 +149,7 @@ class Bitcoin: await self.sign_nonsegwit_input(i) async def step5_serialize_outputs(self) -> None: - writers.write_varint(self.serialized_tx, self.tx.outputs_count) + write_bitcoin_varint(self.serialized_tx, self.tx.outputs_count) for i in range(self.tx.outputs_count): progress.advance() await self.serialize_output(i) @@ -275,7 +275,7 @@ class Bitcoin: h_check = self.create_hash_writer() self.write_tx_header(h_sign, self.tx, witness_marker=False) - writers.write_varint(h_sign, self.tx.inputs_count) + write_bitcoin_varint(h_sign, self.tx.inputs_count) for i in range(self.tx.inputs_count): # STAGE_REQUEST_4_INPUT in legacy @@ -307,7 +307,7 @@ class Bitcoin: script_pubkey = bytes() self.write_tx_input(h_sign, txi, script_pubkey) - writers.write_varint(h_sign, self.tx.outputs_count) + write_bitcoin_varint(h_sign, self.tx.outputs_count) for i in range(self.tx.outputs_count): # STAGE_REQUEST_4_OUTPUT in legacy @@ -353,14 +353,14 @@ class Bitcoin: # witnesses are not included in txid hash self.write_tx_header(txh, tx, witness_marker=False) - writers.write_varint(txh, tx.inputs_cnt) + write_bitcoin_varint(txh, tx.inputs_cnt) for i in range(tx.inputs_cnt): # STAGE_REQUEST_2_PREV_INPUT in legacy txi = await helpers.request_tx_input(self.tx_req, i, self.coin, prev_hash) self.write_tx_input(txh, txi, txi.script_sig) - writers.write_varint(txh, tx.outputs_cnt) + write_bitcoin_varint(txh, tx.outputs_cnt) for i in range(tx.outputs_cnt): # STAGE_REQUEST_2_PREV_OUTPUT in legacy @@ -413,8 +413,8 @@ class Bitcoin: ) -> None: writers.write_uint32(w, tx.version) # nVersion if witness_marker: - writers.write_varint(w, 0x00) # segwit witness marker - writers.write_varint(w, 0x01) # segwit witness flag + write_bitcoin_varint(w, 0x00) # segwit witness marker + write_bitcoin_varint(w, 0x01) # segwit witness flag def write_tx_footer( self, w: writers.Writer, tx: Union[SignTx, TransactionType] diff --git a/core/src/apps/bitcoin/sign_tx/bitcoinlike.py b/core/src/apps/bitcoin/sign_tx/bitcoinlike.py index 18ddea23f..ab67ef91e 100644 --- a/core/src/apps/bitcoin/sign_tx/bitcoinlike.py +++ b/core/src/apps/bitcoin/sign_tx/bitcoinlike.py @@ -6,6 +6,8 @@ from trezor.messages.SignTx import SignTx from trezor.messages.TransactionType import TransactionType from trezor.messages.TxInputType import TxInputType +from apps.common.writers import write_bitcoin_varint + from .. import multisig, writers from . import helpers from .bitcoin import Bitcoin, input_is_nonsegwit @@ -74,8 +76,8 @@ class Bitcoinlike(Bitcoin): if self.coin.timestamp: writers.write_uint32(w, tx.timestamp) if witness_marker: - writers.write_varint(w, 0x00) # segwit witness marker - writers.write_varint(w, 0x01) # segwit witness flag + write_bitcoin_varint(w, 0x00) # segwit witness marker + write_bitcoin_varint(w, 0x01) # segwit witness flag async def write_prev_tx_footer( self, w: writers.Writer, tx: TransactionType, prev_hash: bytes diff --git a/core/src/apps/bitcoin/sign_tx/decred.py b/core/src/apps/bitcoin/sign_tx/decred.py index aefd140d2..b38643045 100644 --- a/core/src/apps/bitcoin/sign_tx/decred.py +++ b/core/src/apps/bitcoin/sign_tx/decred.py @@ -12,6 +12,7 @@ from trezor.messages.TxOutputType import TxOutputType from trezor.utils import HashWriter, ensure from apps.common import coininfo, seed +from apps.common.writers import write_bitcoin_varint from .. import multisig, scripts, writers from ..common import ecdsa_hash_pubkey, ecdsa_sign @@ -36,21 +37,21 @@ class Decred(Bitcoin): super().__init__(tx, keychain, coin) self.write_tx_header(self.serialized_tx, self.tx, witness_marker=True) - writers.write_varint(self.serialized_tx, self.tx.inputs_count) + write_bitcoin_varint(self.serialized_tx, self.tx.inputs_count) def init_hash143(self) -> None: self.h_prefix = self.create_hash_writer() writers.write_uint32( self.h_prefix, self.tx.version | DECRED_SERIALIZE_NO_WITNESS ) - writers.write_varint(self.h_prefix, self.tx.inputs_count) + write_bitcoin_varint(self.h_prefix, self.tx.inputs_count) def create_hash_writer(self) -> HashWriter: return HashWriter(blake256()) async def step2_confirm_outputs(self) -> None: - writers.write_varint(self.serialized_tx, self.tx.outputs_count) - writers.write_varint(self.h_prefix, self.tx.outputs_count) + write_bitcoin_varint(self.serialized_tx, self.tx.outputs_count) + write_bitcoin_varint(self.h_prefix, self.tx.outputs_count) await super().step2_confirm_outputs() self.write_tx_footer(self.serialized_tx, self.tx) self.write_tx_footer(self.h_prefix, self.tx) @@ -68,7 +69,7 @@ class Decred(Bitcoin): self.write_tx_output(self.serialized_tx, txo, script_pubkey) async def step4_serialize_inputs(self) -> None: - writers.write_varint(self.serialized_tx, self.tx.inputs_count) + write_bitcoin_varint(self.serialized_tx, self.tx.inputs_count) prefix_hash = self.h_prefix.get_digest() @@ -99,13 +100,13 @@ class Decred(Bitcoin): writers.write_uint32( h_witness, self.tx.version | DECRED_SERIALIZE_WITNESS_SIGNING ) - writers.write_varint(h_witness, self.tx.inputs_count) + write_bitcoin_varint(h_witness, self.tx.inputs_count) for ii in range(self.tx.inputs_count): if ii == i_sign: writers.write_bytes_prefixed(h_witness, prev_pkscript) else: - writers.write_varint(h_witness, 0) + write_bitcoin_varint(h_witness, 0) witness_hash = writers.get_tx_hash( h_witness, double=self.coin.sign_hash_double, reverse=False diff --git a/core/src/apps/bitcoin/sign_tx/zcash.py b/core/src/apps/bitcoin/sign_tx/zcash.py index 95c7c9906..748379128 100644 --- a/core/src/apps/bitcoin/sign_tx/zcash.py +++ b/core/src/apps/bitcoin/sign_tx/zcash.py @@ -11,6 +11,7 @@ from trezor.utils import HashWriter, ensure from apps.common.coininfo import CoinInfo from apps.common.seed import Keychain +from apps.common.writers import write_bitcoin_varint from ..multisig import multisig_get_pubkeys from ..scripts import output_script_multisig, output_script_p2pkh @@ -22,7 +23,6 @@ from ..writers import ( write_bytes_reversed, write_uint32, write_uint64, - write_varint, ) from . import helpers from .bitcoinlike import Bitcoinlike @@ -53,13 +53,13 @@ class Overwintered(Bitcoinlike): if self.tx.version == 3: write_uint32(self.serialized_tx, self.tx.expiry) # expiryHeight - write_varint(self.serialized_tx, 0) # nJoinSplit + write_bitcoin_varint(self.serialized_tx, 0) # nJoinSplit elif self.tx.version == 4: write_uint32(self.serialized_tx, self.tx.expiry) # expiryHeight write_uint64(self.serialized_tx, 0) # valueBalance - write_varint(self.serialized_tx, 0) # nShieldedSpend - write_varint(self.serialized_tx, 0) # nShieldedOutput - write_varint(self.serialized_tx, 0) # nJoinSplit + write_bitcoin_varint(self.serialized_tx, 0) # nShieldedSpend + write_bitcoin_varint(self.serialized_tx, 0) # nShieldedOutput + write_bitcoin_varint(self.serialized_tx, 0) # nJoinSplit else: raise wire.DataError("Unsupported version for overwintered transaction") diff --git a/core/src/apps/bitcoin/writers.py b/core/src/apps/bitcoin/writers.py index 16041b068..ffd08fe49 100644 --- a/core/src/apps/bitcoin/writers.py +++ b/core/src/apps/bitcoin/writers.py @@ -8,6 +8,7 @@ from trezor.utils import ensure from apps.common.writers import ( # noqa: F401 empty_bytearray, + write_bitcoin_varint, write_bytes_fixed, write_bytes_reversed, write_bytes_unchecked, @@ -30,7 +31,7 @@ TX_HASH_SIZE = const(32) def write_bytes_prefixed(w: Writer, b: bytes) -> None: - write_varint(w, len(b)) + write_bitcoin_varint(w, len(b)) write_bytes_unchecked(w, b) @@ -100,22 +101,6 @@ def write_op_push(w: Writer, n: int) -> None: w.append((n >> 24) & 0xFF) -def write_varint(w: Writer, n: int) -> None: - ensure(n >= 0 and n <= 0xFFFFFFFF) - if n < 253: - w.append(n & 0xFF) - elif n < 0x10000: - w.append(253) - w.append(n & 0xFF) - w.append((n >> 8) & 0xFF) - else: - w.append(254) - w.append(n & 0xFF) - w.append((n >> 8) & 0xFF) - w.append((n >> 16) & 0xFF) - w.append((n >> 24) & 0xFF) - - def get_tx_hash(w: HashWriter, double: bool = False, reverse: bool = False) -> bytes: d = w.get_digest() if double: diff --git a/core/src/apps/common/signverify.py b/core/src/apps/common/signverify.py index 57c3e0390..0670a79a3 100644 --- a/core/src/apps/common/signverify.py +++ b/core/src/apps/common/signverify.py @@ -4,9 +4,9 @@ from trezor import utils, wire from trezor.crypto.hashlib import blake256, sha256 from trezor.ui.text import Text -from apps.bitcoin.writers import write_varint from apps.common.confirm import require_confirm from apps.common.layout import split_address +from apps.common.writers import write_bitcoin_varint if False: from typing import List @@ -18,9 +18,9 @@ def message_digest(coin: CoinType, message: bytes) -> bytes: h = utils.HashWriter(blake256()) else: h = utils.HashWriter(sha256()) - write_varint(h, len(coin.signed_message_header)) + write_bitcoin_varint(h, len(coin.signed_message_header)) h.extend(coin.signed_message_header) - write_varint(h, len(message)) + write_bitcoin_varint(h, len(message)) h.extend(message) ret = h.get_digest() if coin.sign_hash_double: diff --git a/core/src/apps/common/writers.py b/core/src/apps/common/writers.py index 118757d36..cda8c0cce 100644 --- a/core/src/apps/common/writers.py +++ b/core/src/apps/common/writers.py @@ -93,3 +93,19 @@ def write_bytes_reversed(w: Writer, b: bytes, length: int) -> int: ensure(len(b) == length) w.extend(bytes(reversed(b))) return length + + +def write_bitcoin_varint(w: Writer, n: int) -> None: + ensure(n >= 0 and n <= 0xFFFFFFFF) + if n < 253: + w.append(n & 0xFF) + elif n < 0x10000: + w.append(253) + w.append(n & 0xFF) + w.append((n >> 8) & 0xFF) + else: + w.append(254) + w.append(n & 0xFF) + w.append((n >> 8) & 0xFF) + w.append((n >> 16) & 0xFF) + w.append((n >> 24) & 0xFF) diff --git a/core/src/apps/lisk/sign_message.py b/core/src/apps/lisk/sign_message.py index 105b50956..f911172ec 100644 --- a/core/src/apps/lisk/sign_message.py +++ b/core/src/apps/lisk/sign_message.py @@ -3,10 +3,10 @@ from trezor.crypto.hashlib import sha256 from trezor.messages.LiskMessageSignature import LiskMessageSignature from trezor.utils import HashWriter -from apps.bitcoin.sign_tx.writers import write_varint from apps.common import paths from apps.common.seed import with_slip44_keychain from apps.common.signverify import require_confirm_sign_message +from apps.common.writers import write_bitcoin_varint from apps.lisk import CURVE, SLIP44_ID from apps.lisk.helpers import validate_full_path @@ -14,9 +14,9 @@ from apps.lisk.helpers import validate_full_path def message_digest(message): h = HashWriter(sha256()) signed_message_header = "Lisk Signed Message:\n" - write_varint(h, len(signed_message_header)) + write_bitcoin_varint(h, len(signed_message_header)) h.extend(signed_message_header) - write_varint(h, len(message)) + write_bitcoin_varint(h, len(message)) h.extend(message) return sha256(h.get_digest()).digest()