1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-18 05:28:40 +00:00

core/sign_tx: Derive Zip143 and DecredPrefixHasher from Bip143.

This commit is contained in:
Andrew Kozlik 2020-04-08 21:59:18 +02:00 committed by Andrew Kozlik
parent e9900df18d
commit 95fad83024
3 changed files with 57 additions and 46 deletions

View File

@ -13,6 +13,7 @@ from trezor.utils import HashWriter, ensure
from apps.common import coininfo, seed
from apps.wallet.sign_tx import addresses, helpers, multisig, progress, scripts, writers
from apps.wallet.sign_tx.segwit_bip143 import Bip143
from apps.wallet.sign_tx.signing import Bitcoin, SigningError, ecdsa_sign
DECRED_SERIALIZE_FULL = const(0 << 16)
@ -25,7 +26,7 @@ if False:
from typing import Union
class DecredPrefixHasher:
class DecredPrefixHasher(Bip143):
"""
While Decred does not have the exact same implementation as bip143/zip143,
the semantics for using the prefix hash of transactions are close enough
@ -53,7 +54,7 @@ class DecredPrefixHasher:
writers.write_uint32(self.h_prefix, tx.lock_time)
writers.write_uint32(self.h_prefix, tx.expiry)
def prefix_hash(self) -> bytes:
def get_prefix_hash(self) -> bytes:
return self.h_prefix.get_digest()
@ -110,7 +111,7 @@ class Decred(Bitcoin):
async def phase2(self) -> None:
self.tx_req.serialized = None
prefix_hash = self.hash143.prefix_hash()
prefix_hash = self.hash143.get_prefix_hash()
for i_sign in range(self.tx.inputs_count):
progress.advance()

View File

@ -37,9 +37,15 @@ class Bip143:
def add_sequence(self, txi: TxInputType) -> None:
write_uint32(self.h_sequence, txi.sequence)
def add_output_count(self, tx: SignTx) -> None:
pass
def add_output(self, txo_bin: TxOutputBinType) -> None:
write_tx_output(self.h_outputs, txo_bin)
def add_locktime_expiry(self, tx: SignTx) -> None:
pass
def get_prevouts_hash(self, coin: CoinInfo) -> bytes:
return get_tx_hash(self.h_prevouts, double=coin.sign_hash_double)
@ -49,6 +55,9 @@ class Bip143:
def get_outputs_hash(self, coin: CoinInfo) -> bytes:
return get_tx_hash(self.h_outputs, double=coin.sign_hash_double)
def get_prefix_hash(self) -> bytes:
pass
def preimage_hash(
self,
coin: CoinInfo,
@ -70,7 +79,7 @@ class Bip143:
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
script_code = derive_script_code(txi, pubkeyhash) # scriptCode
write_bytes_prefixed(h_preimage, script_code)
write_uint64(h_preimage, txi.amount) # amount
@ -82,27 +91,27 @@ class Bip143:
return get_tx_hash(h_preimage, double=coin.sign_hash_double)
# see https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki#specification
# item 5 for details
def derive_script_code(self, txi: TxInputType, pubkeyhash: bytes) -> bytearray:
if txi.multisig:
return output_script_multisig(
multisig_get_pubkeys(txi.multisig), txi.multisig.m
)
# see https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki#specification
# item 5 for details
def derive_script_code(txi: TxInputType, pubkeyhash: bytes) -> bytearray:
p2pkh = (
txi.script_type == InputScriptType.SPENDWITNESS
or txi.script_type == InputScriptType.SPENDP2SHWITNESS
or txi.script_type == InputScriptType.SPENDADDRESS
if txi.multisig:
return output_script_multisig(
multisig_get_pubkeys(txi.multisig), txi.multisig.m
)
if p2pkh:
# for p2wpkh in p2sh or native p2wpkh
# the scriptCode is a classic p2pkh
return output_script_p2pkh(pubkeyhash)
else:
raise Bip143Error(
FailureType.DataError,
"Unknown input script type for bip143 script code",
)
p2pkh = (
txi.script_type == InputScriptType.SPENDWITNESS
or txi.script_type == InputScriptType.SPENDP2SHWITNESS
or txi.script_type == InputScriptType.SPENDADDRESS
)
if p2pkh:
# for p2wpkh in p2sh or native p2wpkh
# the scriptCode is a classic p2pkh
return output_script_p2pkh(pubkeyhash)
else:
raise Bip143Error(
FailureType.DataError, "Unknown input script type for bip143 script code",
)

View File

@ -6,7 +6,6 @@ from trezor.messages import FailureType, InputScriptType
from trezor.messages.SignTx import SignTx
from trezor.messages.TransactionType import TransactionType
from trezor.messages.TxInputType import TxInputType
from trezor.messages.TxOutputBinType import TxOutputBinType
from trezor.utils import HashWriter, ensure
from apps.common.coininfo import CoinInfo
@ -14,6 +13,7 @@ from apps.common.seed import Keychain
from apps.wallet.sign_tx.bitcoinlike import Bitcoinlike
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.segwit_bip143 import Bip143
from apps.wallet.sign_tx.signing import SigningError
from apps.wallet.sign_tx.writers import (
TX_HASH_SIZE,
@ -21,7 +21,6 @@ from apps.wallet.sign_tx.writers import (
write_bytes_fixed,
write_bytes_prefixed,
write_bytes_reversed,
write_tx_output,
write_uint32,
write_uint64,
write_varint,
@ -55,30 +54,20 @@ def derive_script_code(txi: TxInputType, pubkeyhash: bytes) -> bytearray:
)
class Zip143:
class Zip143(Bip143):
def __init__(self, branch_id: int) -> None:
self.branch_id = branch_id
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 add_prevouts(self, txi: TxInputType) -> None:
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) -> None:
write_uint32(self.h_sequence, txi.sequence)
def add_output(self, txo_bin: TxOutputBinType) -> None:
write_tx_output(self.h_outputs, txo_bin)
def get_prevouts_hash(self) -> bytes:
def get_prevouts_hash(self, coin: CoinInfo) -> bytes:
return get_tx_hash(self.h_prevouts)
def get_sequence_hash(self) -> bytes:
def get_sequence_hash(self, coin: CoinInfo) -> bytes:
return get_tx_hash(self.h_sequence)
def get_outputs_hash(self) -> bytes:
def get_outputs_hash(self, coin: CoinInfo) -> bytes:
return get_tx_hash(self.h_outputs)
def preimage_hash(
@ -103,11 +92,17 @@ class Zip143:
) # 1. nVersion | fOverwintered
write_uint32(h_preimage, tx.version_group_id) # 2. nVersionGroupId
# 3. hashPrevouts
write_bytes_fixed(h_preimage, bytearray(self.get_prevouts_hash()), TX_HASH_SIZE)
write_bytes_fixed(
h_preimage, bytearray(self.get_prevouts_hash(coin)), TX_HASH_SIZE
)
# 4. hashSequence
write_bytes_fixed(h_preimage, bytearray(self.get_sequence_hash()), TX_HASH_SIZE)
write_bytes_fixed(
h_preimage, bytearray(self.get_sequence_hash(coin)), TX_HASH_SIZE
)
# 5. hashOutputs
write_bytes_fixed(h_preimage, bytearray(self.get_outputs_hash()), TX_HASH_SIZE)
write_bytes_fixed(
h_preimage, bytearray(self.get_outputs_hash(coin)), 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
@ -153,11 +148,17 @@ class Zip243(Zip143):
) # 1. nVersion | fOverwintered
write_uint32(h_preimage, tx.version_group_id) # 2. nVersionGroupId
# 3. hashPrevouts
write_bytes_fixed(h_preimage, bytearray(self.get_prevouts_hash()), TX_HASH_SIZE)
write_bytes_fixed(
h_preimage, bytearray(self.get_prevouts_hash(coin)), TX_HASH_SIZE
)
# 4. hashSequence
write_bytes_fixed(h_preimage, bytearray(self.get_sequence_hash()), TX_HASH_SIZE)
write_bytes_fixed(
h_preimage, bytearray(self.get_sequence_hash(coin)), TX_HASH_SIZE
)
# 5. hashOutputs
write_bytes_fixed(h_preimage, bytearray(self.get_outputs_hash()), TX_HASH_SIZE)
write_bytes_fixed(
h_preimage, bytearray(self.get_outputs_hash(coin)), TX_HASH_SIZE
)
zero_hash = b"\x00" * TX_HASH_SIZE
write_bytes_fixed(h_preimage, zero_hash, TX_HASH_SIZE) # 6. hashJoinSplits