core/sign_tx: Implement support for signed external inputs.

pull/1091/head
Andrew Kozlik 4 years ago committed by Andrew Kozlik
parent 78f14d286e
commit d48a372ca7

@ -110,22 +110,22 @@ def output_derive_script(address: str, coin: CoinInfo) -> bytes:
# see https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki#specification
# item 5 for details
def bip143_derive_script_code(txi: TxInputType, pubkeyhash: bytes) -> bytearray:
if txi.multisig:
return output_script_multisig(
multisig_get_pubkeys(txi.multisig), txi.multisig.m
)
def bip143_derive_script_code(
txi: TxInputType, public_keys: List[bytes], threshold: int, coin: CoinInfo
) -> bytearray:
if len(public_keys) > 1:
return output_script_multisig(public_keys, threshold)
p2pkh = (
txi.script_type == InputScriptType.SPENDWITNESS
or txi.script_type == InputScriptType.SPENDP2SHWITNESS
or txi.script_type == InputScriptType.SPENDADDRESS
or txi.script_type == InputScriptType.EXTERNAL
)
if p2pkh:
# for p2wpkh in p2sh or native p2wpkh
# the scriptCode is a classic p2pkh
return output_script_p2pkh(pubkeyhash)
return output_script_p2pkh(common.ecdsa_hash_pubkey(public_keys[0], coin))
else:
raise wire.DataError("Unknown input script type for bip143 script code")

@ -3,7 +3,7 @@ from micropython import const
from trezor import wire
from trezor.crypto.hashlib import sha256
from trezor.messages import InputScriptType
from trezor.messages import InputScriptType, OutputScriptType
from trezor.messages.SignTx import SignTx
from trezor.messages.TransactionType import TransactionType
from trezor.messages.TxInputType import TxInputType
@ -18,12 +18,13 @@ from apps.common import coininfo, seed
from apps.common.writers import write_bitcoin_varint
from .. import addresses, common, multisig, scripts, writers
from ..common import ecdsa_hash_pubkey, ecdsa_sign
from ..common import ecdsa_sign
from ..verification import SignatureVerifier
from . import helpers, progress, tx_weight
from .matchcheck import MultisigFingerprintChecker, WalletPathChecker
if False:
from typing import Set, Optional, Tuple, Union
from typing import List, Optional, Set, Tuple, Union
from trezor.crypto.bip32 import HDNode
# Default signature hash type in Bitcoin which signs all inputs and all outputs of the transaction.
@ -42,8 +43,6 @@ _MAX_SERIALIZED_CHUNK_SIZE = const(2048)
class Bitcoin:
async def signer(self) -> None:
progress.init(self.tx.inputs_count, self.tx.outputs_count)
# Add inputs to hash143 and h_confirmed and compute the sum of input amounts
# by requesting each previous transaction and checking its output amounts.
await self.step1_process_inputs()
@ -55,17 +54,20 @@ class Bitcoin:
# Check fee, confirm lock_time and total.
await self.step3_confirm_tx()
# Verify external inputs which have already been signed.
await self.step4_verify_external_inputs()
# Check that inputs are unchanged. Serialize inputs and sign the non-segwit ones.
await self.step4_serialize_inputs()
await self.step5_serialize_inputs()
# Serialize outputs.
await self.step5_serialize_outputs()
await self.step6_serialize_outputs()
# Sign segwit inputs and serialize witness data.
await self.step6_sign_segwit_inputs()
await self.step7_sign_segwit_inputs()
# Write footer and send remaining data.
await self.step7_finish()
await self.step8_finish()
def __init__(
self, tx: SignTx, keychain: seed.Keychain, coin: coininfo.CoinInfo
@ -83,8 +85,12 @@ class Bitcoin:
# set of indices of inputs which are segwit
self.segwit = set() # type: Set[int]
# set of indices of inputs which are external
self.external = set() # type: Set[int]
# amounts
self.total_in = 0 # sum of input amounts
self.external_in = 0 # sum of external input amounts
self.total_out = 0 # sum of output amounts
self.change_out = 0 # change output amount
self.weight = tx_weight.TxWeightCalculator(tx.inputs_count, tx.outputs_count)
@ -98,24 +104,36 @@ class Bitcoin:
# h_confirmed is used to make sure that the inputs and outputs streamed for
# confirmation in Steps 1 and 2 are the same as the ones streamed for signing
# legacy inputs in Step 4.
# legacy inputs in Step 5.
self.h_confirmed = self.create_hash_writer() # not a real tx hash
# h_external is used to make sure that the signed external inputs streamed for
# confirmation in Step 1 are the same as the ones streamed for verification
# in Step 3.
self.h_external = self.create_hash_writer()
# BIP-0143 transaction hashing
self.init_hash143()
progress.init(self.tx.inputs_count, self.tx.outputs_count)
def create_hash_writer(self) -> HashWriter:
return HashWriter(sha256())
async def step1_process_inputs(self) -> None:
for i in range(self.tx.inputs_count):
# STAGE_REQUEST_1_INPUT in legacy
progress.advance()
txi = await helpers.request_tx_input(self.tx_req, i, self.coin)
self.weight.add_input(txi)
if input_is_segwit(txi):
self.segwit.add(i)
await self.process_input(txi)
if input_is_external(txi):
self.external.add(i)
await self.process_external_input(txi)
else:
progress.advance()
await self.process_internal_input(txi)
async def step2_confirm_outputs(self) -> None:
for i in range(self.tx.outputs_count):
@ -136,40 +154,80 @@ class Bitcoin:
await helpers.confirm_feeoverthreshold(fee, self.coin)
if self.tx.lock_time > 0:
await helpers.confirm_nondefault_locktime(self.tx.lock_time)
await helpers.confirm_total(self.total_in - self.change_out, fee, self.coin)
await helpers.confirm_total(
self.total_in - self.external_in - self.change_out, fee, self.coin
)
async def step4_verify_external_inputs(self) -> None:
# should come out the same as h_external, checked before continuing
h_check = self.create_hash_writer()
async def step4_serialize_inputs(self) -> None:
for i in sorted(self.external):
progress.advance()
txi = await helpers.request_tx_input(self.tx_req, i, self.coin)
writers.write_tx_input_check(h_check, txi)
prev_amount, script_pubkey = await self.get_prevtx_output(
txi.prev_hash, txi.prev_index
)
if prev_amount != txi.amount:
raise wire.DataError("Invalid amount specified")
verifier = SignatureVerifier(
script_pubkey, txi.script_sig, txi.witness, self.coin
)
verifier.ensure_hash_type(self.get_hash_type(txi))
tx_digest = await self.get_tx_digest(
i, txi, verifier.public_keys, verifier.threshold, script_pubkey
)
verifier.verify(tx_digest)
# check that the inputs were the same as those streamed for confirmation
if self.h_external.get_digest() != h_check.get_digest():
raise wire.ProcessError("Transaction has changed during signing")
async def step5_serialize_inputs(self) -> None:
self.write_tx_header(self.serialized_tx, self.tx, bool(self.segwit))
write_bitcoin_varint(self.serialized_tx, self.tx.inputs_count)
for i in range(self.tx.inputs_count):
progress.advance()
if i in self.segwit:
if i in self.external:
await self.serialize_external_input(i)
elif i in self.segwit:
await self.serialize_segwit_input(i)
else:
await self.sign_nonsegwit_input(i)
async def step5_serialize_outputs(self) -> None:
async def step6_serialize_outputs(self) -> None:
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)
async def step6_sign_segwit_inputs(self) -> None:
any_segwit = bool(self.segwit)
async def step7_sign_segwit_inputs(self) -> None:
if not self.segwit:
progress.advance(self.tx.inputs_count)
return
for i in range(self.tx.inputs_count):
progress.advance()
if i in self.segwit:
await self.sign_segwit_input(i)
elif any_segwit:
if i in self.external:
txi = await helpers.request_tx_input(self.tx_req, i, self.coin)
self.serialized_tx.extend(txi.witness)
else:
await self.sign_segwit_input(i)
else:
# add empty witness for non-segwit inputs
self.serialized_tx.append(0)
async def step7_finish(self) -> None:
async def step8_finish(self) -> None:
self.write_tx_footer(self.serialized_tx, self.tx)
await helpers.request_tx_finish(self.tx_req)
async def process_input(self, txi: TxInputType) -> None:
async def process_internal_input(self, txi: TxInputType) -> None:
self.wallet_path.add_input(txi)
self.multisig_fingerprint.add_input(txi)
writers.write_tx_input_check(self.h_confirmed, txi)
@ -190,6 +248,16 @@ class Bitcoin:
self.total_in += prev_amount
async def process_external_input(self, txi: TxInputType) -> None:
if txi.amount is None:
raise wire.DataError("Expected input with amount")
writers.write_tx_input_check(self.h_external, txi)
writers.write_tx_input_check(self.h_confirmed, txi)
self.hash143_add_input(txi) # all inputs are included (non-segwit as well)
self.total_in += txi.amount
self.external_in += txi.amount
async def confirm_output(self, txo: TxOutputType, script_pubkey: bytes) -> None:
if self.change_out == 0 and self.output_is_change(txo):
# output is change and does not need confirmation
@ -201,9 +269,30 @@ class Bitcoin:
self.hash143_add_output(txo, script_pubkey)
self.total_out += txo.amount
async def get_tx_digest(
self,
i: int,
txi: TxInputType,
public_keys: List[bytes],
threshold: int,
script_pubkey: bytes,
) -> bytes:
if txi.witness:
return self.hash143_preimage_hash(txi, public_keys, threshold)
else:
digest, _, _ = await self.get_legacy_tx_digest(i, script_pubkey)
return digest
def on_negative_fee(self) -> None:
raise wire.NotEnoughFunds("Not enough funds")
async def serialize_external_input(self, i: int) -> None:
txi = await helpers.request_tx_input(self.tx_req, i, self.coin)
if not input_is_external(txi):
raise wire.ProcessError("Transaction has changed during signing")
self.write_tx_input(self.serialized_tx, txi, txi.script_sig)
async def serialize_segwit_input(self, i: int) -> None:
# STAGE_REQUEST_SEGWIT_INPUT in legacy
txi = await helpers.request_tx_input(self.tx_req, i, self.coin)
@ -228,9 +317,14 @@ class Bitcoin:
node = self.keychain.derive(txi.address_n)
public_key = node.public_key()
hash143_hash = self.hash143_preimage_hash(
txi, ecdsa_hash_pubkey(public_key, self.coin)
)
if txi.multisig:
public_keys = multisig.multisig_get_pubkeys(txi.multisig)
threshold = txi.multisig.m
else:
public_keys = [public_key]
threshold = 1
hash143_hash = self.hash143_preimage_hash(txi, public_keys, threshold)
signature = ecdsa_sign(node, hash143_hash)
@ -313,7 +407,7 @@ class Bitcoin:
writers.write_uint32(h_sign, self.tx.lock_time)
writers.write_uint32(h_sign, self.get_sighash_type(txi_sign))
# check the control digests
# check that the inputs were the same as those streamed for confirmation
if self.h_confirmed.get_digest() != h_check.get_digest():
raise wire.ProcessError("Transaction has changed during signing")
@ -506,10 +600,12 @@ class Bitcoin:
writers.write_uint32(self.h_prevouts, txi.prev_index)
writers.write_uint32(self.h_sequence, txi.sequence)
def hash143_add_output(self, txo: TxOutputType, script_pubkey) -> None:
def hash143_add_output(self, txo: TxOutputType, script_pubkey: bytes) -> None:
writers.write_tx_output(self.h_outputs, txo, script_pubkey)
def hash143_preimage_hash(self, txi: TxInputType, pubkeyhash: bytes) -> bytes:
def hash143_preimage_hash(
self, txi: TxInputType, public_keys: List[bytes], threshold: int
) -> bytes:
h_preimage = HashWriter(sha256())
# nVersion
@ -532,7 +628,9 @@ class Bitcoin:
writers.write_uint32(h_preimage, txi.prev_index)
# scriptCode
script_code = scripts.bip143_derive_script_code(txi, pubkeyhash)
script_code = scripts.bip143_derive_script_code(
txi, public_keys, threshold, self.coin
)
writers.write_bytes_prefixed(h_preimage, script_code)
# amount
@ -557,8 +655,16 @@ class Bitcoin:
def input_is_segwit(txi: TxInputType) -> bool:
return txi.script_type in common.SEGWIT_INPUT_SCRIPT_TYPES
return txi.script_type in common.SEGWIT_INPUT_SCRIPT_TYPES or (
txi.script_type == InputScriptType.EXTERNAL and txi.witness is not None
)
def input_is_nonsegwit(txi: TxInputType) -> bool:
return txi.script_type in common.NONSEGWIT_INPUT_SCRIPT_TYPES
return txi.script_type in common.NONSEGWIT_INPUT_SCRIPT_TYPES or (
txi.script_type == InputScriptType.EXTERNAL and txi.witness is None
)
def input_is_external(txi: TxInputType) -> bool:
return txi.script_type == InputScriptType.EXTERNAL

@ -4,6 +4,7 @@ from micropython import const
from trezor import wire
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
@ -12,7 +13,7 @@ from . import helpers
from .bitcoin import Bitcoin, input_is_nonsegwit
if False:
from typing import Union
from typing import List, Union
_SIGHASH_FORKID = const(0x40)
@ -41,6 +42,21 @@ class Bitcoinlike(Bitcoin):
else:
await super().sign_nonsegwit_input(i_sign)
async def get_tx_digest(
self,
i: int,
txi: TxInputType,
public_keys: List[bytes],
threshold: int,
script_pubkey: bytes,
) -> bytes:
if self.coin.force_bip143:
return self.hash143_preimage_hash(txi, public_keys, threshold)
else:
return await super().get_tx_digest(
i, txi, public_keys, threshold, script_pubkey
)
def on_negative_fee(self) -> None:
# some coins require negative fees for reward TX
if not self.coin.negative_fee:

@ -57,17 +57,20 @@ class Decred(Bitcoin):
self.write_tx_footer(self.serialized_tx, self.tx)
self.write_tx_footer(self.h_prefix, self.tx)
async def process_input(self, txi: TxInputType) -> None:
await super().process_input(txi)
async def process_internal_input(self, txi: TxInputType) -> None:
await super().process_internal_input(txi)
# Decred serializes inputs early.
self.write_tx_input(self.serialized_tx, txi, bytes())
async def process_external_input(self, txi: TxInputType) -> None:
raise wire.DataError("External inputs not supported")
async def confirm_output(self, txo: TxOutputType, script_pubkey: bytes) -> None:
await super().confirm_output(txo, script_pubkey)
self.write_tx_output(self.serialized_tx, txo, script_pubkey)
async def step4_serialize_inputs(self) -> None:
async def step5_serialize_inputs(self) -> None:
write_bitcoin_varint(self.serialized_tx, self.tx.inputs_count)
prefix_hash = self.h_prefix.get_digest()
@ -125,13 +128,13 @@ class Decred(Bitcoin):
self.write_tx_input_witness(self.serialized_tx, txi_sign, script_sig)
self.set_serialized_signature(i_sign, signature)
async def step5_serialize_outputs(self) -> None:
async def step6_serialize_outputs(self) -> None:
pass
async def step6_sign_segwit_inputs(self) -> None:
async def step7_sign_segwit_inputs(self) -> None:
pass
async def step7_finish(self) -> None:
async def step8_finish(self) -> None:
await helpers.request_tx_finish(self.tx_req)
def check_prevtx_output(self, txo_bin: TxOutputBinType) -> None:

@ -220,7 +220,7 @@ def sanitize_tx_input(tx: TransactionType, coin: CoinInfo) -> TxInputType:
raise wire.DataError("Input's address_n provided but not expected.")
if not coin.decred and txi.decred_tree is not None:
raise wire.DataError("Decred details provided but Decred coin not specified.")
if txi.script_type in common.SEGWIT_INPUT_SCRIPT_TYPES:
if txi.script_type in common.SEGWIT_INPUT_SCRIPT_TYPES or txi.witness is not None:
if not coin.segwit:
raise wire.DataError("Segwit not enabled on this coin")
return txi

@ -12,9 +12,9 @@ def init(inputs: int, outputs: int) -> None:
report()
def advance() -> None:
def advance(i: int = 1) -> None:
global _progress
_progress += 1
_progress += i
report()

@ -13,7 +13,7 @@ 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 ..common import ecdsa_hash_pubkey
from ..scripts import output_script_multisig, output_script_p2pkh
from ..writers import (
TX_HASH_SIZE,
@ -28,7 +28,7 @@ from . import helpers
from .bitcoinlike import Bitcoinlike
if False:
from typing import Union
from typing import List, Union
from ..writers import Writer
OVERWINTERED = const(0x80000000)
@ -48,7 +48,7 @@ class Overwintered(Bitcoinlike):
else:
raise wire.DataError("Unsupported version for overwintered transaction")
async def step7_finish(self) -> None:
async def step8_finish(self) -> None:
self.write_tx_footer(self.serialized_tx, self.tx)
if self.tx.version == 3:
@ -66,6 +66,16 @@ class Overwintered(Bitcoinlike):
async def sign_nonsegwit_input(self, i_sign: int) -> None:
await self.sign_nonsegwit_bip143_input(i_sign)
async def get_tx_digest(
self,
i: int,
txi: TxInputType,
public_keys: List[bytes],
threshold: int,
script_pubkey: bytes,
) -> bytes:
return self.hash143_preimage_hash(txi, public_keys, threshold)
def write_tx_header(
self, w: Writer, tx: Union[SignTx, TransactionType], witness_marker: bool
) -> None:
@ -90,7 +100,9 @@ class Overwintered(Bitcoinlike):
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: TxInputType, pubkeyhash: bytes) -> bytes:
def hash143_preimage_hash(
self, txi: TxInputType, public_keys: List[bytes], threshold: int
) -> bytes:
h_preimage = HashWriter(
blake2b(
outlen=32,
@ -142,7 +154,7 @@ class Overwintered(Bitcoinlike):
write_uint32(h_preimage, txi.prev_index)
# 10b / 13b. scriptCode
script_code = derive_script_code(txi, pubkeyhash)
script_code = derive_script_code(txi, public_keys, threshold, self.coin)
write_bytes_prefixed(h_preimage, script_code)
# 10c / 13c. value
@ -154,16 +166,15 @@ class Overwintered(Bitcoinlike):
return get_tx_hash(h_preimage)
def derive_script_code(txi: TxInputType, pubkeyhash: bytes) -> bytearray:
if txi.multisig:
return output_script_multisig(
multisig_get_pubkeys(txi.multisig), txi.multisig.m
)
def derive_script_code(
txi: TxInputType, public_keys: List[bytes], threshold: int, coin: CoinInfo
) -> bytearray:
if len(public_keys) > 1:
return output_script_multisig(public_keys, threshold)
p2pkh = txi.script_type == InputScriptType.SPENDADDRESS
p2pkh = txi.script_type in (InputScriptType.SPENDADDRESS, InputScriptType.EXTERNAL)
if p2pkh:
return output_script_p2pkh(pubkeyhash)
return output_script_p2pkh(ecdsa_hash_pubkey(public_keys[0], coin))
else:
raise wire.DataError("Unknown input script type for zip143 script code")

@ -4,6 +4,7 @@ from apps.bitcoin.scripts import output_derive_script
from apps.bitcoin.sign_tx.bitcoin import Bitcoin
from apps.bitcoin.writers import get_tx_hash
from apps.common import coins
from apps.common.seed import Keychain
from trezor.messages.SignTx import SignTx
from trezor.messages.TxInputType import TxInputType
from trezor.messages.TxOutputType import TxOutputType
@ -89,10 +90,13 @@ class TestSegwitBip143NativeP2WPKH(unittest.TestCase):
script_pubkey = output_derive_script(txo.address, coin)
bip143.hash143_add_output(txo_bin, script_pubkey)
keychain = Keychain(seed, [[coin.curve_name, []]])
node = keychain.derive(self.inp2.address_n)
# test data public key hash
# only for input 2 - input 1 is not segwit
result = bip143.hash143_preimage_hash(self.inp2, unhexlify('1d0f172a0ecb48aee1be1f2687d2963ae33f71a1'))
self.assertEqual(hexlify(result), b'c37af31116d1b27caf68aae9e3ac82f1477929014d5b917657d0eb49478cb670')
result = bip143.hash143_preimage_hash(self.inp2, [node.public_key()], 1)
self.assertEqual(hexlify(result), b'2fa3f1351618b2532228d7182d3221d95c21fd3d496e7e22e9ded873cf022a8b')
if __name__ == '__main__':

@ -4,6 +4,7 @@ from apps.bitcoin.scripts import output_derive_script
from apps.bitcoin.sign_tx.bitcoin import Bitcoin
from apps.bitcoin.writers import get_tx_hash
from apps.common import coins
from apps.common.seed import Keychain
from trezor.messages.SignTx import SignTx
from trezor.messages.TxInputType import TxInputType
from trezor.messages.TxOutputType import TxOutputType
@ -75,9 +76,12 @@ class TestSegwitBip143(unittest.TestCase):
script_pubkey = output_derive_script(txo.address, coin)
bip143.hash143_add_output(txo_bin, script_pubkey)
keychain = Keychain(seed, [[coin.curve_name, []]])
node = keychain.derive(self.inp1.address_n)
# test data public key hash
result = bip143.hash143_preimage_hash(self.inp1, unhexlify('79091972186c449eb1ded22b78e40d009bdf0089'))
self.assertEqual(hexlify(result), b'64f3b0f4dd2bb3aa1ce8566d220cc74dda9df97d8490cc81d89d735c92e59fb6')
result = bip143.hash143_preimage_hash(self.inp1, [node.public_key()], 1)
self.assertEqual(hexlify(result), b'6e28aca7041720995d4acf59bbda64eef5d6f23723d23f2e994757546674bbd9')
if __name__ == '__main__':

@ -25,7 +25,7 @@ class TestZcashZip143(unittest.TestCase):
"702c35a67cd7364d3fab552fb349e35c15c50250453fd18f7b855992632e2c76",
4025613248,
],
"pubkeyhash": "4d9cafb657677f2321fc538e367767dbdf551539",
"pubkey": "03c6d9cc725bb7e19c026df03bf693ee1171371a8eaf25f04b7a58f6befabcd38c",
"script_type": InputScriptType.SPENDADDRESS,
"sequence": 1999822371,
}
@ -40,7 +40,7 @@ class TestZcashZip143(unittest.TestCase):
"prevouts_hash": b"bd4318eecf841a0cf01c2be532cf4bc3303e881e2aface159f1882f153152688",
"sequence_hash": b"9ac6a31952ff626bf5a0a30d3d8ac63a0d4298d33d7bc38854bfa5860695e30a",
"outputs_hash": b"d0cadf116b4441f5e1e17814908dee509ec262a79f3c88f7f3389e8200658992",
"preimage_hash": b"287146efaa30b3c1c7bd1a72308c46205712e6944780fdc5a7f91f477fddd55b",
"preimage_hash": b"fed855ea5fcec81928fa35d39b8582c6e026a0bf52cebeed4445a7fc7d730280",
},
{
"expiry": 231041495,
@ -51,7 +51,7 @@ class TestZcashZip143(unittest.TestCase):
"76647d2be4c2cd6b3d17d6870971d7a098baf72c6f6f1214cf1faae488bd7de2",
1547817817,
],
"pubkeyhash": "9f5d230603ce57a0e8b31a8c9b6c983ad5b00cd5",
"pubkey": "03c6d9cc725bb7e19c026df03bf693ee1171371a8eaf25f04b7a58f6befabcd38c",
"script_type": InputScriptType.SPENDADDRESS,
"sequence": 3973122135,
},
@ -61,7 +61,7 @@ class TestZcashZip143(unittest.TestCase):
"cccc0df65a04943ad5cbc13f295f000fe056c40b2d88f27dc34cfeb803be3483",
3053054889,
],
"pubkeyhash": "b5e71ef1df5ed3a2589607ca58ed19634f07fb4f",
"pubkey": "02c651a011009e2c7e7b3ed2068857ca0a47cba35b73e06c32e3c06ef3aa67621d",
"script_type": InputScriptType.SPENDADDRESS,
"sequence": 3932380530,
},
@ -77,7 +77,7 @@ class TestZcashZip143(unittest.TestCase):
"prevouts_hash": b"8e286c6c0dde3119271c9c1398ef46614b0253c502b00a3691cec2e9047da35b",
"sequence_hash": b"58477fd9ecd5faf3e08159e0ab5fdaab66cab364d081498ddcef41de0af3624e",
"outputs_hash": b"c518797fc6f2c08fc22aa3f66122047b360e1db4df5c3feb28573c00cdf45fa1",
"preimage_hash": b"b71358954aca8ffe1d3f1b5707ed6c082ed2b35e35e293b897bfc12ae7c85396",
"preimage_hash": b"1c6f563d2f16002f4c59bec5e7d56ed298315630c1d7e9a431b89e6f81026a02",
},
{
"expiry": 186996458,
@ -89,7 +89,7 @@ class TestZcashZip143(unittest.TestCase):
1290359941,
],
"script_type": InputScriptType.SPENDADDRESS,
"pubkeyhash": "0873d1baed6c8696e4bd2b26755692b4d8050086",
"pubkey": "03c6d9cc725bb7e19c026df03bf693ee1171371a8eaf25f04b7a58f6befabcd38c",
"sequence": 1230917966,
}
],
@ -101,7 +101,7 @@ class TestZcashZip143(unittest.TestCase):
"prevouts_hash": b"445bc6328cd33b3c86259953dd674bded341ff1e1104dc21856919e9761036dd",
"sequence_hash": b"42e1d5c2636f165afaa954afa6d7a50779eb145e947bf668f1a40dd771c711fc",
"outputs_hash": b"869eda84eecf7257f9979a4848bbf52f4969a5736594ab7ba41452e7bb906824",
"preimage_hash": b"19ea4ce2467cb5cdcc4562ce81b22006f1fb55189ea93ccc7a3bc78ff5d97a93",
"preimage_hash": b"7159247daa16cc7e683f03ebf968314ce03324028ac138468a7b76c77e551fe8",
},
{
"expiry": 254788522,
@ -113,7 +113,7 @@ class TestZcashZip143(unittest.TestCase):
1517971891,
],
"script_type": InputScriptType.SPENDADDRESS,
"pubkeyhash": "80b6c35a9b2efd77dbfd5d5d3bb1fd03ff40f182",
"pubkey": "03c6d9cc725bb7e19c026df03bf693ee1171371a8eaf25f04b7a58f6befabcd38c",
"sequence": 3833577708,
},
{
@ -123,7 +123,7 @@ class TestZcashZip143(unittest.TestCase):
687648622,
],
"script_type": InputScriptType.SPENDADDRESS,
"pubkeyhash": "fb8c27a442afe0f0b39a3875823c4893fe8f8550",
"pubkey": "02c651a011009e2c7e7b3ed2068857ca0a47cba35b73e06c32e3c06ef3aa67621d",
"sequence": 4190617831,
},
],
@ -137,7 +137,7 @@ class TestZcashZip143(unittest.TestCase):
"prevouts_hash": b"509abdfafcc75265037f1ce6a4658ac9ecadd7b82378c3fbaeb48ab437ff6898",
"sequence_hash": b"2b13f671cd1a9aa04c1e250eef74a316d7d2b049360d20604514ddc2dfacfd23",
"outputs_hash": b"4f01b8785e80779290aa86c16b24952f9b7f8bc09da44e68f760ab1920ab8f2a",
"preimage_hash": b"d0b92233e185a69f320f18bfacff7e5dcc5f0ed02af2f3ecf59359853e105e59",
"preimage_hash": b"16b24c5d599107efb41cbc6cb0127094878bab1e0d33d734cfccce58e07b3386",
},
]
@ -175,7 +175,7 @@ class TestZcashZip143(unittest.TestCase):
self.assertEqual(hexlify(get_tx_hash(zip143.h_sequence)), v["sequence_hash"])
self.assertEqual(hexlify(get_tx_hash(zip143.h_outputs)), v["outputs_hash"])
self.assertEqual(
hexlify(zip143.hash143_preimage_hash(txi, unhexlify(i["pubkeyhash"]))),
hexlify(zip143.hash143_preimage_hash(txi, [unhexlify(i["pubkey"])], 1)),
v["preimage_hash"],
)

@ -25,7 +25,7 @@ class TestZcashZip243(unittest.TestCase):
"702c35a67cd7364d3fab552fb349e35c15c50250453fd18f7b855992632e2c76",
4025613248,
],
"pubkeyhash": "4d9cafb657677f2321fc538e367767dbdf551539",
"pubkey": "03c6d9cc725bb7e19c026df03bf693ee1171371a8eaf25f04b7a58f6befabcd38c",
"script_type": InputScriptType.SPENDADDRESS,
"sequence": 1999822371,
}
@ -40,7 +40,7 @@ class TestZcashZip243(unittest.TestCase):
"prevouts_hash": b"bd4318eecf841a0cf01c2be532cf4bc3303e881e2aface159f1882f153152688",
"sequence_hash": b"9ac6a31952ff626bf5a0a30d3d8ac63a0d4298d33d7bc38854bfa5860695e30a",
"outputs_hash": b"d0cadf116b4441f5e1e17814908dee509ec262a79f3c88f7f3389e8200658992",
"preimage_hash": b"53a12bca557c27defa366c2b4c0e46ede01f81ef3dd3aa3750db62a5505c1d06",
"preimage_hash": b"f8772c6ecf9d903698fb8c51cd7b99605af298478989945936935da65e064695",
},
{
"expiry": 231041495,
@ -51,7 +51,7 @@ class TestZcashZip243(unittest.TestCase):
"76647d2be4c2cd6b3d17d6870971d7a098baf72c6f6f1214cf1faae488bd7de2",
1547817817,
],
"pubkeyhash": "9f5d230603ce57a0e8b31a8c9b6c983ad5b00cd5",
"pubkey": "03c6d9cc725bb7e19c026df03bf693ee1171371a8eaf25f04b7a58f6befabcd38c",
"script_type": InputScriptType.SPENDADDRESS,
"sequence": 3973122135,
},
@ -61,7 +61,7 @@ class TestZcashZip243(unittest.TestCase):
"cccc0df65a04943ad5cbc13f295f000fe056c40b2d88f27dc34cfeb803be3483",
3053054889,
],
"pubkeyhash": "b5e71ef1df5ed3a2589607ca58ed19634f07fb4f",
"pubkey": "02c651a011009e2c7e7b3ed2068857ca0a47cba35b73e06c32e3c06ef3aa67621d",
"script_type": InputScriptType.SPENDADDRESS,
"sequence": 3932380530,
},
@ -77,7 +77,7 @@ class TestZcashZip243(unittest.TestCase):
"prevouts_hash": b"8e286c6c0dde3119271c9c1398ef46614b0253c502b00a3691cec2e9047da35b",
"sequence_hash": b"58477fd9ecd5faf3e08159e0ab5fdaab66cab364d081498ddcef41de0af3624e",
"outputs_hash": b"c518797fc6f2c08fc22aa3f66122047b360e1db4df5c3feb28573c00cdf45fa1",
"preimage_hash": b"d1bc60986cc5c4d57f91002e48459a50f72bdb96b8f5889cf8f467a7d968b97c",
"preimage_hash": b"0eb47dc51d89cc52378fc182242f78ebd3609544a365d2270c23b4052f301025",
},
{
"expiry": 186996458,
@ -89,7 +89,7 @@ class TestZcashZip243(unittest.TestCase):
1290359941,
],
"script_type": InputScriptType.SPENDADDRESS,
"pubkeyhash": "0873d1baed6c8696e4bd2b26755692b4d8050086",
"pubkey": "03c6d9cc725bb7e19c026df03bf693ee1171371a8eaf25f04b7a58f6befabcd38c",
"sequence": 1230917966,
}
],
@ -101,7 +101,7 @@ class TestZcashZip243(unittest.TestCase):
"prevouts_hash": b"445bc6328cd33b3c86259953dd674bded341ff1e1104dc21856919e9761036dd",
"sequence_hash": b"42e1d5c2636f165afaa954afa6d7a50779eb145e947bf668f1a40dd771c711fc",
"outputs_hash": b"869eda84eecf7257f9979a4848bbf52f4969a5736594ab7ba41452e7bb906824",
"preimage_hash": b"7536cdb202a30bf09c45e1a2f775c4efd41b9e67557b62abe12b64d367a2316e",
"preimage_hash": b"7f6b5439a64b20faf6f9f9460bc75c333c4799e9b04c80c26a79b8e801b8b6e1",
},
{
"expiry": 254788522,
@ -113,7 +113,7 @@ class TestZcashZip243(unittest.TestCase):
1517971891,
],
"script_type": InputScriptType.SPENDADDRESS,
"pubkeyhash": "80b6c35a9b2efd77dbfd5d5d3bb1fd03ff40f182",
"pubkey": "03c6d9cc725bb7e19c026df03bf693ee1171371a8eaf25f04b7a58f6befabcd38c",
"sequence": 3833577708,
},
{
@ -123,7 +123,7 @@ class TestZcashZip243(unittest.TestCase):
687648622,
],
"script_type": InputScriptType.SPENDADDRESS,
"pubkeyhash": "fb8c27a442afe0f0b39a3875823c4893fe8f8550",
"pubkey": "02c651a011009e2c7e7b3ed2068857ca0a47cba35b73e06c32e3c06ef3aa67621d",
"sequence": 4190617831,
},
],
@ -137,7 +137,7 @@ class TestZcashZip243(unittest.TestCase):
"prevouts_hash": b"509abdfafcc75265037f1ce6a4658ac9ecadd7b82378c3fbaeb48ab437ff6898",
"sequence_hash": b"2b13f671cd1a9aa04c1e250eef74a316d7d2b049360d20604514ddc2dfacfd23",
"outputs_hash": b"4f01b8785e80779290aa86c16b24952f9b7f8bc09da44e68f760ab1920ab8f2a",
"preimage_hash": b"df1359c0aacc05e88ae6bbecfc54fef50bd31f21f543c49f95a321dd835263be",
"preimage_hash": b"46152b79ebeba4089d05724e33d4a5e6d6ea9e3a2fe777af6644318ba93a1ca0",
},
# "Test vector 3" from https://github.com/zcash/zips/blob/master/zip-0243.rst
{
@ -150,7 +150,7 @@ class TestZcashZip243(unittest.TestCase):
1,
],
"script_type": InputScriptType.SPENDADDRESS,
"pubkeyhash": "507173527b4c3318a2aecd793bf1cfed705950cf",
"pubkey": "03c6d9cc725bb7e19c026df03bf693ee1171371a8eaf25f04b7a58f6befabcd38c",
"sequence": 0xfffffffe,
}
],
@ -171,7 +171,7 @@ class TestZcashZip243(unittest.TestCase):
"prevouts_hash": b"fae31b8dec7b0b77e2c8d6b6eb0e7e4e55abc6574c26dd44464d9408a8e33f11",
"sequence_hash": b"6c80d37f12d89b6f17ff198723e7db1247c4811d1a695d74d930f99e98418790",
"outputs_hash": b"d2b04118469b7810a0d1cc59568320aad25a84f407ecac40b4f605a4e6868454",
"preimage_hash": b"f3148f80dfab5e573d5edfe7a850f5fd39234f80b5429d3a57edcc11e34c585b",
"preimage_hash": b"6c210ce6417539d4aa9546f6184e33ca89224ac4559d2a9c4cf090b646692bd9",
},
]
@ -208,7 +208,7 @@ class TestZcashZip243(unittest.TestCase):
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_outputs)), v["outputs_hash"])
self.assertEqual(hexlify(zip243.hash143_preimage_hash(txi, unhexlify(i["pubkeyhash"]))), v["preimage_hash"])
self.assertEqual(hexlify(zip243.hash143_preimage_hash(txi, [unhexlify(i["pubkey"])], 1)), v["preimage_hash"])
if __name__ == "__main__":

Loading…
Cancel
Save