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.
169 lines
4.9 KiB
169 lines
4.9 KiB
from typing import TYPE_CHECKING
|
|
|
|
from trezor.crypto.hashlib import sha256
|
|
from trezor.messages import PrevTx, SignTx, TxInput, TxOutput
|
|
from trezor.utils import HashWriter
|
|
|
|
from apps.common import coininfo
|
|
|
|
from .. import scripts, writers
|
|
from ..common import tagged_hashwriter
|
|
|
|
if TYPE_CHECKING:
|
|
from typing import Protocol, Sequence
|
|
from ..common import SigHashType
|
|
|
|
class SigHasher(Protocol):
|
|
def add_input(self, txi: TxInput, script_pubkey: bytes) -> None:
|
|
...
|
|
|
|
def add_output(self, txo: TxOutput, script_pubkey: bytes) -> None:
|
|
...
|
|
|
|
def hash143(
|
|
self,
|
|
txi: TxInput,
|
|
public_keys: Sequence[bytes | memoryview],
|
|
threshold: int,
|
|
tx: SignTx | PrevTx,
|
|
coin: coininfo.CoinInfo,
|
|
hash_type: int,
|
|
) -> bytes:
|
|
...
|
|
|
|
def hash341(
|
|
self,
|
|
i: int,
|
|
tx: SignTx | PrevTx,
|
|
sighash_type: SigHashType,
|
|
) -> bytes:
|
|
...
|
|
|
|
|
|
# BIP-0143 hash
|
|
class BitcoinSigHasher:
|
|
def __init__(self) -> None:
|
|
self.h_prevouts = HashWriter(sha256())
|
|
self.h_amounts = HashWriter(sha256())
|
|
self.h_scriptpubkeys = HashWriter(sha256())
|
|
self.h_sequences = HashWriter(sha256())
|
|
self.h_outputs = HashWriter(sha256())
|
|
|
|
def add_input(self, txi: TxInput, script_pubkey: bytes) -> 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_uint64(self.h_amounts, txi.amount)
|
|
writers.write_bytes_prefixed(self.h_scriptpubkeys, script_pubkey)
|
|
writers.write_uint32(self.h_sequences, txi.sequence)
|
|
|
|
def add_output(self, txo: TxOutput, script_pubkey: bytes) -> None:
|
|
writers.write_tx_output(self.h_outputs, txo, script_pubkey)
|
|
|
|
def hash143(
|
|
self,
|
|
txi: TxInput,
|
|
public_keys: Sequence[bytes | memoryview],
|
|
threshold: int,
|
|
tx: SignTx | PrevTx,
|
|
coin: coininfo.CoinInfo,
|
|
hash_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_sequences, 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
|
|
scripts.write_bip143_script_code_prefixed(
|
|
h_preimage, txi, public_keys, threshold, coin
|
|
)
|
|
|
|
# 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, hash_type)
|
|
|
|
return writers.get_tx_hash(h_preimage, double=coin.sign_hash_double)
|
|
|
|
def hash341(
|
|
self,
|
|
i: int,
|
|
tx: SignTx | PrevTx,
|
|
sighash_type: SigHashType,
|
|
) -> bytes:
|
|
h_sigmsg = tagged_hashwriter(b"TapSighash")
|
|
|
|
# sighash epoch 0
|
|
writers.write_uint8(h_sigmsg, 0)
|
|
|
|
# nHashType
|
|
writers.write_uint8(h_sigmsg, sighash_type & 0xFF)
|
|
|
|
# nVersion
|
|
writers.write_uint32(h_sigmsg, tx.version)
|
|
|
|
# nLockTime
|
|
writers.write_uint32(h_sigmsg, tx.lock_time)
|
|
|
|
# sha_prevouts
|
|
writers.write_bytes_fixed(
|
|
h_sigmsg, self.h_prevouts.get_digest(), writers.TX_HASH_SIZE
|
|
)
|
|
|
|
# sha_amounts
|
|
writers.write_bytes_fixed(
|
|
h_sigmsg, self.h_amounts.get_digest(), writers.TX_HASH_SIZE
|
|
)
|
|
|
|
# sha_scriptpubkeys
|
|
writers.write_bytes_fixed(
|
|
h_sigmsg, self.h_scriptpubkeys.get_digest(), writers.TX_HASH_SIZE
|
|
)
|
|
|
|
# sha_sequences
|
|
writers.write_bytes_fixed(
|
|
h_sigmsg, self.h_sequences.get_digest(), writers.TX_HASH_SIZE
|
|
)
|
|
|
|
# sha_outputs
|
|
writers.write_bytes_fixed(
|
|
h_sigmsg, self.h_outputs.get_digest(), writers.TX_HASH_SIZE
|
|
)
|
|
|
|
# spend_type 0 (no tapscript message extension, no annex)
|
|
writers.write_uint8(h_sigmsg, 0)
|
|
|
|
# input_index
|
|
writers.write_uint32(h_sigmsg, i)
|
|
|
|
return h_sigmsg.get_digest()
|