mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-03-03 16:56:07 +00:00
chore(core): In apps.bitcoin move BIP143 hashing back to a separate class.
This commit is contained in:
parent
443e0c101e
commit
5fc491c597
@ -15,6 +15,7 @@ from ..common import BIP32_WALLET_DEPTH, SIGHASH_ALL, ecdsa_sign
|
|||||||
from ..ownership import verify_nonownership
|
from ..ownership import verify_nonownership
|
||||||
from ..verification import SignatureVerifier
|
from ..verification import SignatureVerifier
|
||||||
from . import approvers, helpers, progress
|
from . import approvers, helpers, progress
|
||||||
|
from .hash143 import Hash143
|
||||||
from .matchcheck import MultisigFingerprintChecker, WalletPathChecker
|
from .matchcheck import MultisigFingerprintChecker, WalletPathChecker
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
@ -114,19 +115,22 @@ class Bitcoin:
|
|||||||
self.h_inputs = None # type: Optional[bytes]
|
self.h_inputs = None # type: Optional[bytes]
|
||||||
|
|
||||||
# BIP-0143 transaction hashing
|
# BIP-0143 transaction hashing
|
||||||
self.init_hash143()
|
self.hash143 = self.create_hash143()
|
||||||
|
|
||||||
progress.init(self.tx.inputs_count, self.tx.outputs_count)
|
progress.init(self.tx.inputs_count, self.tx.outputs_count)
|
||||||
|
|
||||||
def create_hash_writer(self) -> HashWriter:
|
def create_hash_writer(self) -> HashWriter:
|
||||||
return HashWriter(sha256())
|
return HashWriter(sha256())
|
||||||
|
|
||||||
|
def create_hash143(self) -> Hash143:
|
||||||
|
return Hash143()
|
||||||
|
|
||||||
async def step1_process_inputs(self) -> None:
|
async def step1_process_inputs(self) -> None:
|
||||||
for i in range(self.tx.inputs_count):
|
for i in range(self.tx.inputs_count):
|
||||||
# STAGE_REQUEST_1_INPUT in legacy
|
# STAGE_REQUEST_1_INPUT in legacy
|
||||||
txi = await helpers.request_tx_input(self.tx_req, i, self.coin)
|
txi = await helpers.request_tx_input(self.tx_req, i, self.coin)
|
||||||
|
|
||||||
self.hash143_add_input(txi) # all inputs are included (non-segwit as well)
|
self.hash143.add_input(txi) # all inputs are included (non-segwit as well)
|
||||||
writers.write_tx_input_check(self.h_approved, txi)
|
writers.write_tx_input_check(self.h_approved, txi)
|
||||||
|
|
||||||
if input_is_segwit(txi):
|
if input_is_segwit(txi):
|
||||||
@ -229,7 +233,7 @@ class Bitcoin:
|
|||||||
await self.approver.add_external_output(txo, script_pubkey)
|
await self.approver.add_external_output(txo, script_pubkey)
|
||||||
|
|
||||||
self.write_tx_output(self.h_approved, txo, script_pubkey)
|
self.write_tx_output(self.h_approved, txo, script_pubkey)
|
||||||
self.hash143_add_output(txo, script_pubkey)
|
self.hash143.add_output(txo, script_pubkey)
|
||||||
|
|
||||||
async def get_tx_digest(
|
async def get_tx_digest(
|
||||||
self,
|
self,
|
||||||
@ -240,7 +244,14 @@ class Bitcoin:
|
|||||||
script_pubkey: bytes,
|
script_pubkey: bytes,
|
||||||
) -> bytes:
|
) -> bytes:
|
||||||
if txi.witness:
|
if txi.witness:
|
||||||
return self.hash143_preimage_hash(txi, public_keys, threshold)
|
return self.hash143.preimage_hash(
|
||||||
|
txi,
|
||||||
|
public_keys,
|
||||||
|
threshold,
|
||||||
|
self.tx,
|
||||||
|
self.coin,
|
||||||
|
self.get_sighash_type(txi),
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
digest, _, _ = await self.get_legacy_tx_digest(i, script_pubkey)
|
digest, _, _ = await self.get_legacy_tx_digest(i, script_pubkey)
|
||||||
return digest
|
return digest
|
||||||
@ -304,7 +315,9 @@ class Bitcoin:
|
|||||||
else:
|
else:
|
||||||
public_keys = [public_key]
|
public_keys = [public_key]
|
||||||
threshold = 1
|
threshold = 1
|
||||||
hash143_hash = self.hash143_preimage_hash(txi, public_keys, threshold)
|
hash143_hash = self.hash143.preimage_hash(
|
||||||
|
txi, public_keys, threshold, self.tx, self.coin, self.get_sighash_type(txi)
|
||||||
|
)
|
||||||
|
|
||||||
signature = ecdsa_sign(node, hash143_hash)
|
signature = ecdsa_sign(node, hash143_hash)
|
||||||
|
|
||||||
@ -478,16 +491,16 @@ class Bitcoin:
|
|||||||
# the fork ID value.
|
# the fork ID value.
|
||||||
return self.get_sighash_type(txi) & 0xFF
|
return self.get_sighash_type(txi) & 0xFF
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
def write_tx_input(
|
def write_tx_input(
|
||||||
self,
|
|
||||||
w: writers.Writer,
|
w: writers.Writer,
|
||||||
txi: Union[TxInput, PrevInput],
|
txi: Union[TxInput, PrevInput],
|
||||||
script: bytes,
|
script: bytes,
|
||||||
) -> None:
|
) -> None:
|
||||||
writers.write_tx_input(w, txi, script)
|
writers.write_tx_input(w, txi, script)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
def write_tx_output(
|
def write_tx_output(
|
||||||
self,
|
|
||||||
w: writers.Writer,
|
w: writers.Writer,
|
||||||
txo: Union[TxOutput, PrevOutput],
|
txo: Union[TxOutput, PrevOutput],
|
||||||
script_pubkey: bytes,
|
script_pubkey: bytes,
|
||||||
@ -574,74 +587,6 @@ class Bitcoin:
|
|||||||
signature,
|
signature,
|
||||||
)
|
)
|
||||||
|
|
||||||
# BIP-0143
|
|
||||||
# ===
|
|
||||||
|
|
||||||
def init_hash143(self) -> None:
|
|
||||||
self.h_prevouts = HashWriter(sha256())
|
|
||||||
self.h_sequence = HashWriter(sha256())
|
|
||||||
self.h_outputs = HashWriter(sha256())
|
|
||||||
|
|
||||||
def hash143_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 hash143_add_output(self, txo: TxOutput, script_pubkey: bytes) -> None:
|
|
||||||
writers.write_tx_output(self.h_outputs, txo, script_pubkey)
|
|
||||||
|
|
||||||
def hash143_preimage_hash(
|
|
||||||
self, txi: TxInput, public_keys: List[bytes], threshold: int
|
|
||||||
) -> bytes:
|
|
||||||
h_preimage = HashWriter(sha256())
|
|
||||||
|
|
||||||
# nVersion
|
|
||||||
writers.write_uint32(h_preimage, self.tx.version)
|
|
||||||
|
|
||||||
# hashPrevouts
|
|
||||||
prevouts_hash = writers.get_tx_hash(
|
|
||||||
self.h_prevouts, double=self.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=self.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, self.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=self.coin.sign_hash_double
|
|
||||||
)
|
|
||||||
writers.write_bytes_fixed(h_preimage, outputs_hash, writers.TX_HASH_SIZE)
|
|
||||||
|
|
||||||
# nLockTime
|
|
||||||
writers.write_uint32(h_preimage, self.tx.lock_time)
|
|
||||||
|
|
||||||
# nHashType
|
|
||||||
writers.write_uint32(h_preimage, self.get_sighash_type(txi))
|
|
||||||
|
|
||||||
return writers.get_tx_hash(h_preimage, double=self.coin.sign_hash_double)
|
|
||||||
|
|
||||||
|
|
||||||
def input_is_segwit(txi: TxInput) -> bool:
|
def input_is_segwit(txi: TxInput) -> bool:
|
||||||
return txi.script_type in common.SEGWIT_INPUT_SCRIPT_TYPES or (
|
return txi.script_type in common.SEGWIT_INPUT_SCRIPT_TYPES or (
|
||||||
|
@ -49,7 +49,14 @@ class Bitcoinlike(Bitcoin):
|
|||||||
script_pubkey: bytes,
|
script_pubkey: bytes,
|
||||||
) -> bytes:
|
) -> bytes:
|
||||||
if self.coin.force_bip143:
|
if self.coin.force_bip143:
|
||||||
return self.hash143_preimage_hash(txi, public_keys, threshold)
|
return self.hash143.preimage_hash(
|
||||||
|
txi,
|
||||||
|
public_keys,
|
||||||
|
threshold,
|
||||||
|
self.tx,
|
||||||
|
self.coin,
|
||||||
|
self.get_sighash_type(txi),
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
return await super().get_tx_digest(
|
return await super().get_tx_digest(
|
||||||
i, txi, public_keys, threshold, script_pubkey
|
i, txi, public_keys, threshold, script_pubkey
|
||||||
|
@ -12,6 +12,7 @@ from .. import multisig, scripts, writers
|
|||||||
from ..common import ecdsa_hash_pubkey, ecdsa_sign
|
from ..common import ecdsa_hash_pubkey, ecdsa_sign
|
||||||
from . import approvers, helpers, progress
|
from . import approvers, helpers, progress
|
||||||
from .bitcoin import Bitcoin
|
from .bitcoin import Bitcoin
|
||||||
|
from .hash143 import Hash143
|
||||||
|
|
||||||
DECRED_SERIALIZE_FULL = const(0 << 16)
|
DECRED_SERIALIZE_FULL = const(0 << 16)
|
||||||
DECRED_SERIALIZE_NO_WITNESS = const(1 << 16)
|
DECRED_SERIALIZE_NO_WITNESS = const(1 << 16)
|
||||||
@ -33,6 +34,17 @@ if False:
|
|||||||
from apps.common.keychain import Keychain
|
from apps.common.keychain import Keychain
|
||||||
|
|
||||||
|
|
||||||
|
class DecredHash(Hash143):
|
||||||
|
def __init__(self, h_prefix: HashWriter) -> None:
|
||||||
|
self.h_prefix = h_prefix
|
||||||
|
|
||||||
|
def add_input(self, txi: TxInput) -> None:
|
||||||
|
Decred.write_tx_input(self.h_prefix, txi, bytes())
|
||||||
|
|
||||||
|
def add_output(self, txo: TxOutput, script_pubkey: bytes) -> None:
|
||||||
|
Decred.write_tx_output(self.h_prefix, txo, script_pubkey)
|
||||||
|
|
||||||
|
|
||||||
class Decred(Bitcoin):
|
class Decred(Bitcoin):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@ -42,21 +54,22 @@ class Decred(Bitcoin):
|
|||||||
approver: approvers.Approver,
|
approver: approvers.Approver,
|
||||||
) -> None:
|
) -> None:
|
||||||
ensure(coin.decred)
|
ensure(coin.decred)
|
||||||
|
|
||||||
|
self.h_prefix = HashWriter(blake256())
|
||||||
|
writers.write_uint32(self.h_prefix, tx.version | DECRED_SERIALIZE_NO_WITNESS)
|
||||||
|
write_bitcoin_varint(self.h_prefix, tx.inputs_count)
|
||||||
|
|
||||||
super().__init__(tx, keychain, coin, approver)
|
super().__init__(tx, keychain, coin, approver)
|
||||||
|
|
||||||
self.write_tx_header(self.serialized_tx, self.tx, witness_marker=True)
|
self.write_tx_header(self.serialized_tx, self.tx, witness_marker=True)
|
||||||
write_bitcoin_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
|
|
||||||
)
|
|
||||||
write_bitcoin_varint(self.h_prefix, self.tx.inputs_count)
|
|
||||||
|
|
||||||
def create_hash_writer(self) -> HashWriter:
|
def create_hash_writer(self) -> HashWriter:
|
||||||
return HashWriter(blake256())
|
return HashWriter(blake256())
|
||||||
|
|
||||||
|
def create_hash143(self) -> Hash143:
|
||||||
|
return DecredHash(self.h_prefix)
|
||||||
|
|
||||||
async def step2_approve_outputs(self) -> None:
|
async def step2_approve_outputs(self) -> None:
|
||||||
write_bitcoin_varint(self.serialized_tx, self.tx.outputs_count)
|
write_bitcoin_varint(self.serialized_tx, self.tx.outputs_count)
|
||||||
write_bitcoin_varint(self.h_prefix, self.tx.outputs_count)
|
write_bitcoin_varint(self.h_prefix, self.tx.outputs_count)
|
||||||
@ -148,14 +161,8 @@ class Decred(Bitcoin):
|
|||||||
if txo_bin.decred_script_version != 0:
|
if txo_bin.decred_script_version != 0:
|
||||||
raise wire.ProcessError("Cannot use utxo that has script_version != 0")
|
raise wire.ProcessError("Cannot use utxo that has script_version != 0")
|
||||||
|
|
||||||
def hash143_add_input(self, txi: TxInput) -> None:
|
@staticmethod
|
||||||
self.write_tx_input(self.h_prefix, txi, bytes())
|
|
||||||
|
|
||||||
def hash143_add_output(self, txo: TxOutput, script_pubkey: bytes) -> None:
|
|
||||||
self.write_tx_output(self.h_prefix, txo, script_pubkey)
|
|
||||||
|
|
||||||
def write_tx_input(
|
def write_tx_input(
|
||||||
self,
|
|
||||||
w: writers.Writer,
|
w: writers.Writer,
|
||||||
txi: Union[TxInput, PrevInput],
|
txi: Union[TxInput, PrevInput],
|
||||||
script: bytes,
|
script: bytes,
|
||||||
@ -165,8 +172,8 @@ class Decred(Bitcoin):
|
|||||||
writers.write_uint8(w, txi.decred_tree or 0)
|
writers.write_uint8(w, txi.decred_tree or 0)
|
||||||
writers.write_uint32(w, txi.sequence)
|
writers.write_uint32(w, txi.sequence)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
def write_tx_output(
|
def write_tx_output(
|
||||||
self,
|
|
||||||
w: writers.Writer,
|
w: writers.Writer,
|
||||||
txo: Union[TxOutput, PrevOutput],
|
txo: Union[TxOutput, PrevOutput],
|
||||||
script_pubkey: bytes,
|
script_pubkey: bytes,
|
||||||
|
85
core/src/apps/bitcoin/sign_tx/hash143.py
Normal file
85
core/src/apps/bitcoin/sign_tx/hash143.py
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
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 List, Union
|
||||||
|
|
||||||
|
|
||||||
|
# BIP-0143 hash
|
||||||
|
class Hash143:
|
||||||
|
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: Union[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)
|
@ -26,14 +26,80 @@ from ..writers import (
|
|||||||
)
|
)
|
||||||
from . import approvers, helpers
|
from . import approvers, helpers
|
||||||
from .bitcoinlike import Bitcoinlike
|
from .bitcoinlike import Bitcoinlike
|
||||||
|
from .hash143 import Hash143
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
|
from apps.common import coininfo
|
||||||
from typing import List, Union
|
from typing import List, Union
|
||||||
from ..writers import Writer
|
from ..writers import Writer
|
||||||
|
|
||||||
OVERWINTERED = const(0x80000000)
|
OVERWINTERED = const(0x80000000)
|
||||||
|
|
||||||
|
|
||||||
|
class Zip243Hash(Hash143):
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.h_prevouts = HashWriter(blake2b(outlen=32, personal=b"ZcashPrevoutHash"))
|
||||||
|
self.h_sequence = HashWriter(blake2b(outlen=32, personal=b"ZcashSequencHash"))
|
||||||
|
self.h_outputs = HashWriter(blake2b(outlen=32, personal=b"ZcashOutputsHash"))
|
||||||
|
|
||||||
|
def preimage_hash(
|
||||||
|
self,
|
||||||
|
txi: TxInput,
|
||||||
|
public_keys: List[bytes],
|
||||||
|
threshold: int,
|
||||||
|
tx: Union[SignTx, PrevTx],
|
||||||
|
coin: coininfo.CoinInfo,
|
||||||
|
sighash_type: int,
|
||||||
|
) -> bytes:
|
||||||
|
h_preimage = HashWriter(
|
||||||
|
blake2b(
|
||||||
|
outlen=32,
|
||||||
|
personal=b"ZcashSigHash" + struct.pack("<I", tx.branch_id),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
assert tx.version_group_id is not None
|
||||||
|
assert tx.expiry is not None
|
||||||
|
zero_hash = b"\x00" * TX_HASH_SIZE
|
||||||
|
|
||||||
|
# 1. nVersion | fOverwintered
|
||||||
|
write_uint32(h_preimage, tx.version | OVERWINTERED)
|
||||||
|
# 2. nVersionGroupId
|
||||||
|
write_uint32(h_preimage, tx.version_group_id)
|
||||||
|
# 3. hashPrevouts
|
||||||
|
write_bytes_fixed(h_preimage, get_tx_hash(self.h_prevouts), TX_HASH_SIZE)
|
||||||
|
# 4. hashSequence
|
||||||
|
write_bytes_fixed(h_preimage, get_tx_hash(self.h_sequence), TX_HASH_SIZE)
|
||||||
|
# 5. hashOutputs
|
||||||
|
write_bytes_fixed(h_preimage, get_tx_hash(self.h_outputs), 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_bytes_fixed(h_preimage, zero_hash, TX_HASH_SIZE)
|
||||||
|
# 9. nLockTime
|
||||||
|
write_uint32(h_preimage, tx.lock_time)
|
||||||
|
# 10. expiryHeight
|
||||||
|
write_uint32(h_preimage, tx.expiry)
|
||||||
|
# 11. valueBalance
|
||||||
|
write_uint64(h_preimage, 0)
|
||||||
|
# 12. nHashType
|
||||||
|
write_uint32(h_preimage, sighash_type)
|
||||||
|
# 13a. outpoint
|
||||||
|
write_bytes_reversed(h_preimage, txi.prev_hash, TX_HASH_SIZE)
|
||||||
|
write_uint32(h_preimage, txi.prev_index)
|
||||||
|
# 13b. scriptCode
|
||||||
|
script_code = derive_script_code(txi, public_keys, threshold, coin)
|
||||||
|
write_bytes_prefixed(h_preimage, script_code)
|
||||||
|
# 13c. value
|
||||||
|
write_uint64(h_preimage, txi.amount)
|
||||||
|
# 13d. nSequence
|
||||||
|
write_uint32(h_preimage, txi.sequence)
|
||||||
|
|
||||||
|
return get_tx_hash(h_preimage)
|
||||||
|
|
||||||
|
|
||||||
class Zcashlike(Bitcoinlike):
|
class Zcashlike(Bitcoinlike):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@ -48,6 +114,9 @@ class Zcashlike(Bitcoinlike):
|
|||||||
if self.tx.version != 4:
|
if self.tx.version != 4:
|
||||||
raise wire.DataError("Unsupported transaction version.")
|
raise wire.DataError("Unsupported transaction version.")
|
||||||
|
|
||||||
|
def create_hash143(self) -> Hash143:
|
||||||
|
return Zip243Hash()
|
||||||
|
|
||||||
async def step7_finish(self) -> None:
|
async def step7_finish(self) -> None:
|
||||||
self.write_tx_footer(self.serialized_tx, self.tx)
|
self.write_tx_footer(self.serialized_tx, self.tx)
|
||||||
|
|
||||||
@ -69,7 +138,9 @@ class Zcashlike(Bitcoinlike):
|
|||||||
threshold: int,
|
threshold: int,
|
||||||
script_pubkey: bytes,
|
script_pubkey: bytes,
|
||||||
) -> bytes:
|
) -> bytes:
|
||||||
return self.hash143_preimage_hash(txi, public_keys, threshold)
|
return self.hash143.preimage_hash(
|
||||||
|
txi, public_keys, threshold, self.tx, self.coin, self.get_sighash_type(txi)
|
||||||
|
)
|
||||||
|
|
||||||
def write_tx_header(
|
def write_tx_header(
|
||||||
self, w: Writer, tx: Union[SignTx, PrevTx], witness_marker: bool
|
self, w: Writer, tx: Union[SignTx, PrevTx], witness_marker: bool
|
||||||
@ -90,70 +161,9 @@ class Zcashlike(Bitcoinlike):
|
|||||||
if tx.version >= 3:
|
if tx.version >= 3:
|
||||||
write_uint32(w, tx.expiry) # expiryHeight
|
write_uint32(w, tx.expiry) # expiryHeight
|
||||||
|
|
||||||
# ZIP-0143 / ZIP-0243
|
|
||||||
# ===
|
|
||||||
|
|
||||||
def init_hash143(self) -> None:
|
|
||||||
self.h_prevouts = HashWriter(blake2b(outlen=32, personal=b"ZcashPrevoutHash"))
|
|
||||||
self.h_sequence = HashWriter(blake2b(outlen=32, personal=b"ZcashSequencHash"))
|
|
||||||
self.h_outputs = HashWriter(blake2b(outlen=32, personal=b"ZcashOutputsHash"))
|
|
||||||
|
|
||||||
def hash143_preimage_hash(
|
|
||||||
self, txi: TxInput, public_keys: List[bytes], threshold: int
|
|
||||||
) -> bytes:
|
|
||||||
h_preimage = HashWriter(
|
|
||||||
blake2b(
|
|
||||||
outlen=32,
|
|
||||||
personal=b"ZcashSigHash" + struct.pack("<I", self.tx.branch_id),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
assert self.tx.version_group_id is not None
|
assert self.tx.version_group_id is not None
|
||||||
assert self.tx.expiry is not None
|
assert self.tx.expiry is not None
|
||||||
|
|
||||||
# 1. nVersion | fOverwintered
|
|
||||||
write_uint32(h_preimage, self.tx.version | OVERWINTERED)
|
|
||||||
# 2. nVersionGroupId
|
|
||||||
write_uint32(h_preimage, self.tx.version_group_id)
|
|
||||||
# 3. hashPrevouts
|
|
||||||
write_bytes_fixed(h_preimage, get_tx_hash(self.h_prevouts), TX_HASH_SIZE)
|
|
||||||
# 4. hashSequence
|
|
||||||
write_bytes_fixed(h_preimage, get_tx_hash(self.h_sequence), TX_HASH_SIZE)
|
|
||||||
# 5. hashOutputs
|
|
||||||
write_bytes_fixed(h_preimage, get_tx_hash(self.h_outputs), TX_HASH_SIZE)
|
|
||||||
|
|
||||||
zero_hash = b"\x00" * 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_bytes_fixed(h_preimage, zero_hash, TX_HASH_SIZE)
|
|
||||||
# 9. nLockTime
|
|
||||||
write_uint32(h_preimage, self.tx.lock_time)
|
|
||||||
# 10. expiryHeight
|
|
||||||
write_uint32(h_preimage, self.tx.expiry)
|
|
||||||
# 11. valueBalance
|
|
||||||
write_uint64(h_preimage, 0)
|
|
||||||
# 12. nHashType
|
|
||||||
write_uint32(h_preimage, self.get_sighash_type(txi))
|
|
||||||
|
|
||||||
# 10a /13a. outpoint
|
|
||||||
write_bytes_reversed(h_preimage, txi.prev_hash, TX_HASH_SIZE)
|
|
||||||
write_uint32(h_preimage, txi.prev_index)
|
|
||||||
|
|
||||||
# 10b / 13b. scriptCode
|
|
||||||
script_code = derive_script_code(txi, public_keys, threshold, self.coin)
|
|
||||||
write_bytes_prefixed(h_preimage, script_code)
|
|
||||||
|
|
||||||
# 10c / 13c. value
|
|
||||||
write_uint64(h_preimage, txi.amount)
|
|
||||||
|
|
||||||
# 10d / 13d. nSequence
|
|
||||||
write_uint32(h_preimage, txi.sequence)
|
|
||||||
|
|
||||||
return get_tx_hash(h_preimage)
|
|
||||||
|
|
||||||
|
|
||||||
def derive_script_code(
|
def derive_script_code(
|
||||||
txi: TxInput, public_keys: List[bytes], threshold: int, coin: CoinInfo
|
txi: TxInput, public_keys: List[bytes], threshold: int, coin: CoinInfo
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
from common import *
|
from common import *
|
||||||
|
|
||||||
|
from apps.bitcoin.common import SIGHASH_ALL
|
||||||
from apps.bitcoin.scripts import output_derive_script
|
from apps.bitcoin.scripts import output_derive_script
|
||||||
from apps.bitcoin.sign_tx.approvers import BasicApprover
|
from apps.bitcoin.sign_tx.bitcoin import Hash143
|
||||||
from apps.bitcoin.sign_tx.bitcoin import Bitcoin
|
|
||||||
from apps.bitcoin.writers import get_tx_hash
|
from apps.bitcoin.writers import get_tx_hash
|
||||||
from apps.common import coins
|
from apps.common import coins
|
||||||
from apps.common.keychain import Keychain
|
from apps.common.keychain import Keychain
|
||||||
@ -48,17 +48,17 @@ class TestSegwitBip143NativeP2WPKH(unittest.TestCase):
|
|||||||
|
|
||||||
def test_prevouts(self):
|
def test_prevouts(self):
|
||||||
coin = coins.by_name(self.tx.coin_name)
|
coin = coins.by_name(self.tx.coin_name)
|
||||||
bip143 = Bitcoin(self.tx, None, coin, BasicApprover(self.tx, coin))
|
bip143 = Hash143()
|
||||||
bip143.hash143_add_input(self.inp1)
|
bip143.add_input(self.inp1)
|
||||||
bip143.hash143_add_input(self.inp2)
|
bip143.add_input(self.inp2)
|
||||||
prevouts_hash = get_tx_hash(bip143.h_prevouts, double=coin.sign_hash_double)
|
prevouts_hash = get_tx_hash(bip143.h_prevouts, double=coin.sign_hash_double)
|
||||||
self.assertEqual(hexlify(prevouts_hash), b'96b827c8483d4e9b96712b6713a7b68d6e8003a781feba36c31143470b4efd37')
|
self.assertEqual(hexlify(prevouts_hash), b'96b827c8483d4e9b96712b6713a7b68d6e8003a781feba36c31143470b4efd37')
|
||||||
|
|
||||||
def test_sequence(self):
|
def test_sequence(self):
|
||||||
coin = coins.by_name(self.tx.coin_name)
|
coin = coins.by_name(self.tx.coin_name)
|
||||||
bip143 = Bitcoin(self.tx, None, coin, BasicApprover(self.tx, coin))
|
bip143 = Hash143()
|
||||||
bip143.hash143_add_input(self.inp1)
|
bip143.add_input(self.inp1)
|
||||||
bip143.hash143_add_input(self.inp2)
|
bip143.add_input(self.inp2)
|
||||||
sequence_hash = get_tx_hash(bip143.h_sequence, double=coin.sign_hash_double)
|
sequence_hash = get_tx_hash(bip143.h_sequence, double=coin.sign_hash_double)
|
||||||
self.assertEqual(hexlify(sequence_hash), b'52b0a642eea2fb7ae638c36f6252b6750293dbe574a806984b8e4d8548339a3b')
|
self.assertEqual(hexlify(sequence_hash), b'52b0a642eea2fb7ae638c36f6252b6750293dbe574a806984b8e4d8548339a3b')
|
||||||
|
|
||||||
@ -66,12 +66,12 @@ class TestSegwitBip143NativeP2WPKH(unittest.TestCase):
|
|||||||
|
|
||||||
seed = bip39.seed('alcohol woman abuse must during monitor noble actual mixed trade anger aisle', '')
|
seed = bip39.seed('alcohol woman abuse must during monitor noble actual mixed trade anger aisle', '')
|
||||||
coin = coins.by_name(self.tx.coin_name)
|
coin = coins.by_name(self.tx.coin_name)
|
||||||
bip143 = Bitcoin(self.tx, None, coin, BasicApprover(self.tx, coin))
|
bip143 = Hash143()
|
||||||
|
|
||||||
for txo in [self.out1, self.out2]:
|
for txo in [self.out1, self.out2]:
|
||||||
script_pubkey = output_derive_script(txo.address, coin)
|
script_pubkey = output_derive_script(txo.address, coin)
|
||||||
txo_bin = PrevOutput(amount=txo.amount, script_pubkey=script_pubkey)
|
txo_bin = PrevOutput(amount=txo.amount, script_pubkey=script_pubkey)
|
||||||
bip143.hash143_add_output(txo_bin, script_pubkey)
|
bip143.add_output(txo_bin, script_pubkey)
|
||||||
|
|
||||||
outputs_hash = get_tx_hash(bip143.h_outputs, double=coin.sign_hash_double)
|
outputs_hash = get_tx_hash(bip143.h_outputs, double=coin.sign_hash_double)
|
||||||
self.assertEqual(hexlify(outputs_hash), b'863ef3e1a92afbfdb97f31ad0fc7683ee943e9abcf2501590ff8f6551f47e5e5')
|
self.assertEqual(hexlify(outputs_hash), b'863ef3e1a92afbfdb97f31ad0fc7683ee943e9abcf2501590ff8f6551f47e5e5')
|
||||||
@ -80,21 +80,21 @@ class TestSegwitBip143NativeP2WPKH(unittest.TestCase):
|
|||||||
|
|
||||||
seed = bip39.seed('alcohol woman abuse must during monitor noble actual mixed trade anger aisle', '')
|
seed = bip39.seed('alcohol woman abuse must during monitor noble actual mixed trade anger aisle', '')
|
||||||
coin = coins.by_name(self.tx.coin_name)
|
coin = coins.by_name(self.tx.coin_name)
|
||||||
bip143 = Bitcoin(self.tx, None, coin, BasicApprover(self.tx, coin))
|
bip143 = Hash143()
|
||||||
bip143.hash143_add_input(self.inp1)
|
bip143.add_input(self.inp1)
|
||||||
bip143.hash143_add_input(self.inp2)
|
bip143.add_input(self.inp2)
|
||||||
|
|
||||||
for txo in [self.out1, self.out2]:
|
for txo in [self.out1, self.out2]:
|
||||||
script_pubkey = output_derive_script(txo.address, coin)
|
script_pubkey = output_derive_script(txo.address, coin)
|
||||||
txo_bin = PrevOutput(amount=txo.amount, script_pubkey=script_pubkey)
|
txo_bin = PrevOutput(amount=txo.amount, script_pubkey=script_pubkey)
|
||||||
bip143.hash143_add_output(txo_bin, script_pubkey)
|
bip143.add_output(txo_bin, script_pubkey)
|
||||||
|
|
||||||
keychain = Keychain(seed, coin.curve_name, [[]])
|
keychain = Keychain(seed, coin.curve_name, [[]])
|
||||||
node = keychain.derive(self.inp2.address_n)
|
node = keychain.derive(self.inp2.address_n)
|
||||||
|
|
||||||
# test data public key hash
|
# test data public key hash
|
||||||
# only for input 2 - input 1 is not segwit
|
# only for input 2 - input 1 is not segwit
|
||||||
result = bip143.hash143_preimage_hash(self.inp2, [node.public_key()], 1)
|
result = bip143.preimage_hash(self.inp2, [node.public_key()], 1, self.tx, coin, SIGHASH_ALL)
|
||||||
self.assertEqual(hexlify(result), b'2fa3f1351618b2532228d7182d3221d95c21fd3d496e7e22e9ded873cf022a8b')
|
self.assertEqual(hexlify(result), b'2fa3f1351618b2532228d7182d3221d95c21fd3d496e7e22e9ded873cf022a8b')
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
from common import *
|
from common import *
|
||||||
|
|
||||||
|
from apps.bitcoin.common import SIGHASH_ALL
|
||||||
from apps.bitcoin.scripts import output_derive_script
|
from apps.bitcoin.scripts import output_derive_script
|
||||||
from apps.bitcoin.sign_tx.approvers import BasicApprover
|
from apps.bitcoin.sign_tx.bitcoin import Hash143
|
||||||
from apps.bitcoin.sign_tx.bitcoin import Bitcoin
|
|
||||||
from apps.bitcoin.writers import get_tx_hash
|
from apps.bitcoin.writers import get_tx_hash
|
||||||
from apps.common import coins
|
from apps.common import coins
|
||||||
from apps.common.keychain import Keychain
|
from apps.common.keychain import Keychain
|
||||||
@ -40,27 +40,27 @@ class TestSegwitBip143(unittest.TestCase):
|
|||||||
|
|
||||||
def test_bip143_prevouts(self):
|
def test_bip143_prevouts(self):
|
||||||
coin = coins.by_name(self.tx.coin_name)
|
coin = coins.by_name(self.tx.coin_name)
|
||||||
bip143 = Bitcoin(self.tx, None, coin, BasicApprover(self.tx, coin))
|
bip143 = Hash143()
|
||||||
bip143.hash143_add_input(self.inp1)
|
bip143.add_input(self.inp1)
|
||||||
prevouts_hash = get_tx_hash(bip143.h_prevouts, double=coin.sign_hash_double)
|
prevouts_hash = get_tx_hash(bip143.h_prevouts, double=coin.sign_hash_double)
|
||||||
self.assertEqual(hexlify(prevouts_hash), b'b0287b4a252ac05af83d2dcef00ba313af78a3e9c329afa216eb3aa2a7b4613a')
|
self.assertEqual(hexlify(prevouts_hash), b'b0287b4a252ac05af83d2dcef00ba313af78a3e9c329afa216eb3aa2a7b4613a')
|
||||||
|
|
||||||
def test_bip143_sequence(self):
|
def test_bip143_sequence(self):
|
||||||
coin = coins.by_name(self.tx.coin_name)
|
coin = coins.by_name(self.tx.coin_name)
|
||||||
bip143 = Bitcoin(self.tx, None, coin, BasicApprover(self.tx, coin))
|
bip143 = Hash143()
|
||||||
bip143.hash143_add_input(self.inp1)
|
bip143.add_input(self.inp1)
|
||||||
sequence_hash = get_tx_hash(bip143.h_sequence, double=coin.sign_hash_double)
|
sequence_hash = get_tx_hash(bip143.h_sequence, double=coin.sign_hash_double)
|
||||||
self.assertEqual(hexlify(sequence_hash), b'18606b350cd8bf565266bc352f0caddcf01e8fa789dd8a15386327cf8cabe198')
|
self.assertEqual(hexlify(sequence_hash), b'18606b350cd8bf565266bc352f0caddcf01e8fa789dd8a15386327cf8cabe198')
|
||||||
|
|
||||||
def test_bip143_outputs(self):
|
def test_bip143_outputs(self):
|
||||||
seed = bip39.seed('alcohol woman abuse must during monitor noble actual mixed trade anger aisle', '')
|
seed = bip39.seed('alcohol woman abuse must during monitor noble actual mixed trade anger aisle', '')
|
||||||
coin = coins.by_name(self.tx.coin_name)
|
coin = coins.by_name(self.tx.coin_name)
|
||||||
bip143 = Bitcoin(self.tx, None, coin, BasicApprover(self.tx, coin))
|
bip143 = Hash143()
|
||||||
|
|
||||||
for txo in [self.out1, self.out2]:
|
for txo in [self.out1, self.out2]:
|
||||||
script_pubkey = output_derive_script(txo.address, coin)
|
script_pubkey = output_derive_script(txo.address, coin)
|
||||||
txo_bin = PrevOutput(amount=txo.amount, script_pubkey=script_pubkey)
|
txo_bin = PrevOutput(amount=txo.amount, script_pubkey=script_pubkey)
|
||||||
bip143.hash143_add_output(txo_bin, script_pubkey)
|
bip143.add_output(txo_bin, script_pubkey)
|
||||||
|
|
||||||
outputs_hash = get_tx_hash(bip143.h_outputs, double=coin.sign_hash_double)
|
outputs_hash = get_tx_hash(bip143.h_outputs, double=coin.sign_hash_double)
|
||||||
self.assertEqual(hexlify(outputs_hash), b'de984f44532e2173ca0d64314fcefe6d30da6f8cf27bafa706da61df8a226c83')
|
self.assertEqual(hexlify(outputs_hash), b'de984f44532e2173ca0d64314fcefe6d30da6f8cf27bafa706da61df8a226c83')
|
||||||
@ -68,18 +68,18 @@ class TestSegwitBip143(unittest.TestCase):
|
|||||||
def test_bip143_preimage_testdata(self):
|
def test_bip143_preimage_testdata(self):
|
||||||
seed = bip39.seed('alcohol woman abuse must during monitor noble actual mixed trade anger aisle', '')
|
seed = bip39.seed('alcohol woman abuse must during monitor noble actual mixed trade anger aisle', '')
|
||||||
coin = coins.by_name(self.tx.coin_name)
|
coin = coins.by_name(self.tx.coin_name)
|
||||||
bip143 = Bitcoin(self.tx, None, coin, BasicApprover(self.tx, coin))
|
bip143 = Hash143()
|
||||||
bip143.hash143_add_input(self.inp1)
|
bip143.add_input(self.inp1)
|
||||||
for txo in [self.out1, self.out2]:
|
for txo in [self.out1, self.out2]:
|
||||||
script_pubkey = output_derive_script(txo.address, coin)
|
script_pubkey = output_derive_script(txo.address, coin)
|
||||||
txo_bin = PrevOutput(amount=txo.amount, script_pubkey=script_pubkey)
|
txo_bin = PrevOutput(amount=txo.amount, script_pubkey=script_pubkey)
|
||||||
bip143.hash143_add_output(txo_bin, script_pubkey)
|
bip143.add_output(txo_bin, script_pubkey)
|
||||||
|
|
||||||
keychain = Keychain(seed, coin.curve_name, [[]])
|
keychain = Keychain(seed, coin.curve_name, [[]])
|
||||||
node = keychain.derive(self.inp1.address_n)
|
node = keychain.derive(self.inp1.address_n)
|
||||||
|
|
||||||
# test data public key hash
|
# test data public key hash
|
||||||
result = bip143.hash143_preimage_hash(self.inp1, [node.public_key()], 1)
|
result = bip143.preimage_hash(self.inp1, [node.public_key()], 1, self.tx, coin, SIGHASH_ALL)
|
||||||
self.assertEqual(hexlify(result), b'6e28aca7041720995d4acf59bbda64eef5d6f23723d23f2e994757546674bbd9')
|
self.assertEqual(hexlify(result), b'6e28aca7041720995d4acf59bbda64eef5d6f23723d23f2e994757546674bbd9')
|
||||||
|
|
||||||
|
|
||||||
|
@ -5,11 +5,11 @@ from trezor.messages.TxInput import TxInput
|
|||||||
from trezor.messages.PrevOutput import PrevOutput
|
from trezor.messages.PrevOutput import PrevOutput
|
||||||
|
|
||||||
from apps.common import coins
|
from apps.common import coins
|
||||||
|
from apps.bitcoin.common import SIGHASH_ALL
|
||||||
from apps.bitcoin.writers import get_tx_hash
|
from apps.bitcoin.writers import get_tx_hash
|
||||||
from apps.bitcoin.sign_tx.approvers import BasicApprover
|
|
||||||
|
|
||||||
if not utils.BITCOIN_ONLY:
|
if not utils.BITCOIN_ONLY:
|
||||||
from apps.bitcoin.sign_tx.zcash import Zcashlike
|
from apps.bitcoin.sign_tx.zcash import Zip243Hash
|
||||||
|
|
||||||
|
|
||||||
# test vectors inspired from https://github.com/zcash-hackworks/zcash-test-vectors/blob/master/zip_0243.py
|
# test vectors inspired from https://github.com/zcash-hackworks/zcash-test-vectors/blob/master/zip_0243.py
|
||||||
@ -191,7 +191,7 @@ class TestZcashZip243(unittest.TestCase):
|
|||||||
branch_id=v["branch_id"],
|
branch_id=v["branch_id"],
|
||||||
)
|
)
|
||||||
|
|
||||||
zip243 = Zcashlike(tx, None, coin, BasicApprover(tx, coin))
|
zip243 = Zip243Hash()
|
||||||
|
|
||||||
for i in v["inputs"]:
|
for i in v["inputs"]:
|
||||||
txi = TxInput(
|
txi = TxInput(
|
||||||
@ -201,18 +201,19 @@ class TestZcashZip243(unittest.TestCase):
|
|||||||
script_type = i["script_type"],
|
script_type = i["script_type"],
|
||||||
sequence = i["sequence"],
|
sequence = i["sequence"],
|
||||||
)
|
)
|
||||||
zip243.hash143_add_input(txi)
|
zip243.add_input(txi)
|
||||||
|
|
||||||
for o in v["outputs"]:
|
for o in v["outputs"]:
|
||||||
txo = PrevOutput(
|
txo = PrevOutput(
|
||||||
amount = o["amount"],
|
amount = o["amount"],
|
||||||
script_pubkey = unhexlify(o["script_pubkey"]),
|
script_pubkey = unhexlify(o["script_pubkey"]),
|
||||||
)
|
)
|
||||||
zip243.hash143_add_output(txo, txo.script_pubkey)
|
zip243.add_output(txo, txo.script_pubkey)
|
||||||
|
|
||||||
self.assertEqual(hexlify(get_tx_hash(zip243.h_prevouts)), v["prevouts_hash"])
|
self.assertEqual(hexlify(get_tx_hash(zip243.h_prevouts)), v["prevouts_hash"])
|
||||||
self.assertEqual(hexlify(get_tx_hash(zip243.h_sequence)), v["sequence_hash"])
|
self.assertEqual(hexlify(get_tx_hash(zip243.h_sequence)), v["sequence_hash"])
|
||||||
self.assertEqual(hexlify(get_tx_hash(zip243.h_outputs)), v["outputs_hash"])
|
self.assertEqual(hexlify(get_tx_hash(zip243.h_outputs)), v["outputs_hash"])
|
||||||
self.assertEqual(hexlify(zip243.hash143_preimage_hash(txi, [unhexlify(i["pubkey"])], 1)), v["preimage_hash"])
|
self.assertEqual(hexlify(zip243.preimage_hash(txi, [unhexlify(i["pubkey"])], 1, tx, coin, SIGHASH_ALL)), v["preimage_hash"])
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
Loading…
Reference in New Issue
Block a user