You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
trezor-firmware/core/src/apps/bitcoin/sign_tx/hash143.py

104 lines
3.1 KiB

from trezor.crypto.hashlib import sha256
from trezor.messages.PrevTx import PrevTx
from trezor.messages.SignTx import SignTx
from trezor.messages.TxInput import TxInput
from trezor.messages.TxOutput import TxOutput
from trezor.utils import HashWriter
from apps.common import coininfo
from .. import scripts, writers
if False:
from typing import Protocol
class Hash143(Protocol):
def add_input(self, txi: TxInput) -> None:
...
def add_output(self, txo: TxOutput, script_pubkey: bytes) -> None:
...
def preimage_hash(
self,
txi: TxInput,
public_keys: list[bytes],
threshold: int,
tx: SignTx | PrevTx,
coin: coininfo.CoinInfo,
sighash_type: int,
) -> bytes:
...
# BIP-0143 hash
class Bip143Hash:
def __init__(self) -> None:
self.h_prevouts = HashWriter(sha256())
self.h_sequence = HashWriter(sha256())
self.h_outputs = HashWriter(sha256())
def add_input(self, txi: TxInput) -> None:
writers.write_bytes_reversed(
self.h_prevouts, txi.prev_hash, writers.TX_HASH_SIZE
)
writers.write_uint32(self.h_prevouts, txi.prev_index)
writers.write_uint32(self.h_sequence, txi.sequence)
def add_output(self, txo: TxOutput, script_pubkey: bytes) -> None:
writers.write_tx_output(self.h_outputs, txo, script_pubkey)
def preimage_hash(
self,
txi: TxInput,
public_keys: list[bytes],
threshold: int,
tx: SignTx | PrevTx,
coin: coininfo.CoinInfo,
sighash_type: int,
) -> bytes:
h_preimage = HashWriter(sha256())
# nVersion
writers.write_uint32(h_preimage, tx.version)
# hashPrevouts
prevouts_hash = writers.get_tx_hash(
self.h_prevouts, double=coin.sign_hash_double
)
writers.write_bytes_fixed(h_preimage, prevouts_hash, writers.TX_HASH_SIZE)
# hashSequence
sequence_hash = writers.get_tx_hash(
self.h_sequence, double=coin.sign_hash_double
)
writers.write_bytes_fixed(h_preimage, sequence_hash, writers.TX_HASH_SIZE)
# outpoint
writers.write_bytes_reversed(h_preimage, txi.prev_hash, writers.TX_HASH_SIZE)
writers.write_uint32(h_preimage, txi.prev_index)
# scriptCode
script_code = scripts.bip143_derive_script_code(
txi, public_keys, threshold, coin
)
writers.write_bytes_prefixed(h_preimage, script_code)
# amount
writers.write_uint64(h_preimage, txi.amount)
# nSequence
writers.write_uint32(h_preimage, txi.sequence)
# hashOutputs
outputs_hash = writers.get_tx_hash(self.h_outputs, double=coin.sign_hash_double)
writers.write_bytes_fixed(h_preimage, outputs_hash, writers.TX_HASH_SIZE)
# nLockTime
writers.write_uint32(h_preimage, tx.lock_time)
# nHashType
writers.write_uint32(h_preimage, sighash_type)
return writers.get_tx_hash(h_preimage, double=coin.sign_hash_double)