Merge branch 'release/2020-06'

pull/1058/head
Tomas Susanka 4 years ago
commit 56fe5adcfc

@ -44,7 +44,7 @@
"3": 1537743641,
"4": 1991772603
},
"extra_data": false,
"extra_data": true,
"timestamp": false,
"confidential_assets": null
}

@ -519,13 +519,21 @@ STATIC mp_obj_t mod_trezorcrypto_monero_inv256_modm(size_t n_args,
assert_scalar(args[1 + off]);
// bn_prime = curve order, little endian encoded
bignum256 bn_prime = {.val = {0x1cf5d3ed, 0x20498c69, 0x2f79cd65, 0x37be77a8,
0x14, 0x0, 0x0, 0x0, 0x1000}};
bignum256 bn_prime = {.val = {0x1cf5d3ed, 0x9318d2, 0x1de73596, 0x1df3bd45,
0x14d, 0x0, 0x0, 0x0, 0x100000}};
bignum256 bn_x;
bignum256modm bm_x;
uint8_t raw_x[32];
memcpy(bm_x, MP_OBJ_C_SCALAR(args[1 + off]), sizeof(bignum256modm));
contract256_modm(raw_x, bm_x);
bn_read_le(raw_x, &bn_x);
memcpy(&bn_x.val, MP_OBJ_C_SCALAR(args[1 + off]), sizeof(bignum256modm));
bn_inverse(&bn_x, &bn_prime);
memcpy(MP_OBJ_SCALAR(res), bn_x.val, sizeof(bignum256modm));
bn_write_le(&bn_x, raw_x);
expand_raw256_modm(bm_x, raw_x);
memcpy(MP_OBJ_SCALAR(res), bm_x, sizeof(bignum256modm));
return res;
}

@ -84,7 +84,6 @@ class Bitcoin:
# amounts
self.total_in = 0 # sum of input amounts
self.bip143_in = 0 # sum of segwit 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)
@ -178,26 +177,15 @@ class Bitcoin:
if not addresses.validate_full_path(txi.address_n, self.coin, txi.script_type):
await helpers.confirm_foreign_address(txi.address_n)
if input_is_segwit(txi):
await self.process_segwit_input(txi)
elif input_is_nonsegwit(txi):
await self.process_nonsegwit_input(txi)
else:
if txi.script_type not in helpers.INTERNAL_INPUT_SCRIPT_TYPES:
raise wire.DataError("Wrong input script type")
async def process_segwit_input(self, txi: TxInputType) -> None:
await self.process_bip143_input(txi)
prev_amount = await self.get_prevtx_output_value(txi.prev_hash, txi.prev_index)
async def process_nonsegwit_input(self, txi: TxInputType) -> None:
self.total_in += await self.get_prevtx_output_value(
txi.prev_hash, txi.prev_index
)
if txi.amount is not None and prev_amount != txi.amount:
raise wire.DataError("Invalid amount specified")
async def process_bip143_input(self, txi: TxInputType) -> None:
if not txi.amount:
raise wire.DataError("Expected input with amount")
self.bip143_in += txi.amount
self.total_in += txi.amount
self.total_in += prev_amount
async def confirm_output(self, txo: TxOutputType, script_pubkey: bytes) -> None:
if self.change_out == 0 and self.output_is_change(txo):
@ -229,13 +217,12 @@ class Bitcoin:
self.write_tx_input(self.serialized_tx, txi, script_sig)
def sign_bip143_input(self, txi: TxInputType) -> Tuple[bytes, bytes]:
if txi.amount is None:
raise wire.DataError("Expected input with amount")
self.wallet_path.check_input(txi)
self.multisig_fingerprint.check_input(txi)
if txi.amount > self.bip143_in:
raise wire.ProcessError("Transaction has changed during signing")
self.bip143_in -= txi.amount
node = self.keychain.derive(txi.address_n)
public_key = node.public_key()
hash143_hash = self.hash143_preimage_hash(

@ -4,7 +4,6 @@ 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
@ -19,17 +18,6 @@ _SIGHASH_FORKID = const(0x40)
class Bitcoinlike(Bitcoin):
async def process_segwit_input(self, txi: TxInputType) -> None:
if not self.coin.segwit:
raise wire.DataError("Segwit not enabled on this coin")
await super().process_segwit_input(txi)
async def process_nonsegwit_input(self, txi: TxInputType) -> None:
if self.coin.force_bip143:
await self.process_bip143_input(txi)
else:
await super().process_nonsegwit_input(txi)
async def sign_nonsegwit_bip143_input(self, i_sign: int) -> None:
txi = await helpers.request_tx_input(self.tx_req, i_sign, self.coin)
@ -83,11 +71,11 @@ class Bitcoinlike(Bitcoin):
await super().write_prev_tx_footer(w, tx, prev_hash)
if self.coin.extra_data:
ofs = 0
while ofs < tx.extra_data_len:
size = min(1024, tx.extra_data_len - ofs)
offset = 0
while offset < tx.extra_data_len:
size = min(1024, tx.extra_data_len - offset)
data = await helpers.request_tx_extra_data(
self.tx_req, ofs, size, prev_hash
self.tx_req, offset, size, prev_hash
)
writers.write_bytes_unchecked(w, data)
ofs += len(data)
offset += len(data)

@ -199,6 +199,13 @@ def sanitize_sign_tx(tx: SignTx, coin: CoinInfo) -> SignTx:
raise wire.DataError("Timestamp must be set.")
elif not coin.timestamp and tx.timestamp:
raise wire.DataError("Timestamp not enabled on this coin.")
if coin.overwintered and tx.version_group_id is None:
raise wire.DataError("Version group ID must be set.")
elif not coin.overwintered:
if tx.version_group_id is not None:
raise wire.DataError("Version group ID not enabled on this coin.")
if tx.branch_id is not None:
raise wire.DataError("Branch ID not enabled on this coin.")
return tx
@ -219,6 +226,13 @@ def sanitize_tx_meta(tx: TransactionType, coin: CoinInfo) -> TransactionType:
raise wire.DataError("Timestamp must be set.")
elif not coin.timestamp and tx.timestamp:
raise wire.DataError("Timestamp not enabled on this coin.")
if coin.overwintered and tx.version_group_id is None:
raise wire.DataError("Version group ID must be set.")
elif not coin.overwintered:
if tx.version_group_id is not None:
raise wire.DataError("Version group ID not enabled on this coin.")
if tx.branch_id is not None:
raise wire.DataError("Branch ID not enabled on this coin.")
return tx
@ -228,6 +242,8 @@ def sanitize_tx_input(tx: TransactionType, coin: CoinInfo) -> TxInputType:
txi.script_type = InputScriptType.SPENDADDRESS
if txi.sequence is None:
txi.sequence = 0xFFFFFFFF
if txi.prev_index is None:
raise wire.DataError("Missing prev_index field.")
if txi.prev_hash is None or len(txi.prev_hash) != TX_HASH_SIZE:
raise wire.DataError("Provided prev_hash is invalid.")
if txi.multisig and txi.script_type not in MULTISIG_INPUT_SCRIPT_TYPES:
@ -239,8 +255,6 @@ def sanitize_tx_input(tx: TransactionType, coin: CoinInfo) -> TxInputType:
if txi.script_type in SEGWIT_INPUT_SCRIPT_TYPES:
if not coin.segwit:
raise wire.DataError("Segwit not enabled on this coin")
if txi.amount is None:
raise wire.DataError("Segwit input without amount")
return txi
@ -250,8 +264,12 @@ def sanitize_tx_output(tx: TransactionType, coin: CoinInfo) -> TxOutputType:
raise wire.DataError("Multisig field provided but not expected.")
if txo.address_n and txo.script_type not in CHANGE_OUTPUT_SCRIPT_TYPES:
raise wire.DataError("Output's address_n provided but not expected.")
if txo.amount is None:
raise wire.DataError("Missing amount field.")
if txo.script_type == OutputScriptType.PAYTOOPRETURN:
# op_return output
if txo.op_return_data is None:
raise wire.DataError("OP_RETURN output without op_return_data")
if txo.amount != 0:
raise wire.DataError("OP_RETURN output with non-zero amount")
if txo.address or txo.address_n or txo.multisig:
@ -270,4 +288,8 @@ def sanitize_tx_output(tx: TransactionType, coin: CoinInfo) -> TxOutputType:
def sanitize_tx_binoutput(tx: TransactionType, coin: CoinInfo) -> TxOutputBinType:
txo_bin = tx.bin_outputs[0]
if txo_bin.amount is None:
raise wire.DataError("Missing amount field.")
if txo_bin.script_pubkey is None:
raise wire.DataError("Missing script_pubkey field.")
return txo_bin

@ -52,10 +52,8 @@ class Overwintered(Bitcoinlike):
self.write_tx_footer(self.serialized_tx, self.tx)
if self.tx.version == 3:
write_uint32(self.serialized_tx, self.tx.expiry) # expiryHeight
write_bitcoin_varint(self.serialized_tx, 0) # nJoinSplit
elif self.tx.version == 4:
write_uint32(self.serialized_tx, self.tx.expiry) # expiryHeight
write_uint64(self.serialized_tx, 0) # valueBalance
write_bitcoin_varint(self.serialized_tx, 0) # nShieldedSpend
write_bitcoin_varint(self.serialized_tx, 0) # nShieldedOutput
@ -65,9 +63,6 @@ class Overwintered(Bitcoinlike):
await helpers.request_tx_finish(self.tx_req)
async def process_nonsegwit_input(self, txi: TxInputType) -> None:
await self.process_bip143_input(txi)
async def sign_nonsegwit_input(self, i_sign: int) -> None:
await self.sign_nonsegwit_bip143_input(i_sign)
@ -78,6 +73,10 @@ class Overwintered(Bitcoinlike):
write_uint32(w, tx.version | OVERWINTERED)
write_uint32(w, tx.version_group_id) # nVersionGroupId
def write_tx_footer(self, w: Writer, tx: Union[SignTx, TransactionType]) -> None:
write_uint32(w, tx.lock_time)
write_uint32(w, tx.expiry) # expiryHeight
# ZIP-0143 / ZIP-0243
# ===

@ -940,7 +940,7 @@ def by_name(name: str) -> CoinInfo:
decred=False,
negative_fee=True,
curve_name='secp256k1',
extra_data=False,
extra_data=True,
timestamp=False,
overwintered=True,
confidential_assets=None,

@ -4,11 +4,12 @@ from trezor.utils import chunks
from trezor.crypto import bip39
from trezor.messages.SignTx import SignTx
from trezor.messages.TxInputType import TxInputType
from trezor.messages.TxOutputBinType import TxOutputBinType
from trezor.messages.TxOutputType import TxOutputType
from trezor.messages.TxRequest import TxRequest
from trezor.messages.TxAck import TxAck
from trezor.messages.TransactionType import TransactionType
from trezor.messages.RequestType import TXINPUT, TXOUTPUT, TXFINISHED
from trezor.messages.RequestType import TXINPUT, TXMETA, TXOUTPUT, TXFINISHED
from trezor.messages.TxRequestDetailsType import TxRequestDetailsType
from trezor.messages.TxRequestSerializedType import TxRequestSerializedType
from trezor.messages import InputScriptType
@ -42,6 +43,17 @@ class TestSignSegwitTxNativeP2WPKH(unittest.TestCase):
sequence=0xffffffff,
multisig=None,
)
ptx1 = TransactionType(version=1, lock_time=0, inputs_cnt=1, outputs_cnt=2, extra_data_len=0)
pinp1 = TxInputType(script_sig=unhexlify('160014d16b8c0680c61fc6ed2e407455715055e41052f5'),
prev_hash=unhexlify('20912f98ea3ed849042efed0fdac8cb4fc301961c5988cba56902d8ffb61c337'),
prev_index=0,
script_type=None,
sequence=4294967295)
pout1 = TxOutputBinType(script_pubkey=unhexlify('00140099a7ecbd938ed1839f5f6bf6d50933c6db9d5c'),
amount=12300000)
pout2 = TxOutputBinType(script_pubkey=unhexlify('a91458b53ea7f832e8f096e896b8713a8c6df0e892ca87'),
amount=111145789)
out1 = TxOutputType(
address='2N4Q5FhU2497BryFfUgbqkAJE87aKHUhXMp',
amount=5000000,
@ -68,6 +80,18 @@ class TestSignSegwitTxNativeP2WPKH(unittest.TestCase):
helpers.UiConfirmForeignAddress(address_n=inp1.address_n),
True,
TxRequest(request_type=TXMETA, details=TxRequestDetailsType(request_index=None, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=ptx1),
TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(inputs=[pinp1])),
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(bin_outputs=[pout1])),
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=1, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(bin_outputs=[pout2])),
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(outputs=[out1])),
@ -144,6 +168,17 @@ class TestSignSegwitTxNativeP2WPKH(unittest.TestCase):
sequence=0xffffffff,
multisig=None,
)
ptx1 = TransactionType(version=1, lock_time=0, inputs_cnt=1, outputs_cnt=2, extra_data_len=0)
pinp1 = TxInputType(script_sig=unhexlify('160014d16b8c0680c61fc6ed2e407455715055e41052f5'),
prev_hash=unhexlify('20912f98ea3ed849042efed0fdac8cb4fc301961c5988cba56902d8ffb61c337'),
prev_index=0,
script_type=None,
sequence=4294967295)
pout1 = TxOutputBinType(script_pubkey=unhexlify('00140099a7ecbd938ed1839f5f6bf6d50933c6db9d5c'),
amount=12300000)
pout2 = TxOutputBinType(script_pubkey=unhexlify('a91458b53ea7f832e8f096e896b8713a8c6df0e892ca87'),
amount=111145789)
out1 = TxOutputType(
address='2N4Q5FhU2497BryFfUgbqkAJE87aKHUhXMp',
amount=5000000,
@ -170,6 +205,18 @@ class TestSignSegwitTxNativeP2WPKH(unittest.TestCase):
helpers.UiConfirmForeignAddress(address_n=inp1.address_n),
True,
TxRequest(request_type=TXMETA, details=TxRequestDetailsType(request_index=None, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=ptx1),
TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(inputs=[pinp1])),
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(bin_outputs=[pout1])),
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=1, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(bin_outputs=[pout2])),
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(outputs=[out1])),
@ -243,6 +290,17 @@ class TestSignSegwitTxNativeP2WPKH(unittest.TestCase):
sequence=0xffffffff,
multisig=None,
)
ptx1 = TransactionType(version=1, lock_time=0, inputs_cnt=1, outputs_cnt=2, extra_data_len=0)
pinp1 = TxInputType(script_sig=unhexlify('160014d16b8c0680c61fc6ed2e407455715055e41052f5'),
prev_hash=unhexlify('20912f98ea3ed849042efed0fdac8cb4fc301961c5988cba56902d8ffb61c337'),
prev_index=0,
script_type=None,
sequence=4294967295)
pout1 = TxOutputBinType(script_pubkey=unhexlify('00140099a7ecbd938ed1839f5f6bf6d50933c6db9d5c'),
amount=12300000)
pout2 = TxOutputBinType(script_pubkey=unhexlify('a91458b53ea7f832e8f096e896b8713a8c6df0e892ca87'),
amount=111145789)
out1 = TxOutputType(
address='TB1Q694CCP5QCC0UDMFWGP692U2S2HJPQ5H407URTU', # Error: should be lower case
script_type=OutputScriptType.PAYTOADDRESS,
@ -262,6 +320,18 @@ class TestSignSegwitTxNativeP2WPKH(unittest.TestCase):
helpers.UiConfirmForeignAddress(address_n=inp1.address_n),
True,
TxRequest(request_type=TXMETA, details=TxRequestDetailsType(request_index=None, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=ptx1),
TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(inputs=[pinp1])),
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(bin_outputs=[pout1])),
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=1, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(bin_outputs=[pout2])),
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(outputs=[out1])),
None

@ -4,11 +4,12 @@ from trezor.utils import chunks
from trezor.crypto import bip39
from trezor.messages.SignTx import SignTx
from trezor.messages.TxInputType import TxInputType
from trezor.messages.TxOutputBinType import TxOutputBinType
from trezor.messages.TxOutputType import TxOutputType
from trezor.messages.TxRequest import TxRequest
from trezor.messages.TxAck import TxAck
from trezor.messages.TransactionType import TransactionType
from trezor.messages.RequestType import TXINPUT, TXOUTPUT, TXFINISHED
from trezor.messages.RequestType import TXINPUT, TXMETA, TXOUTPUT, TXFINISHED
from trezor.messages.TxRequestDetailsType import TxRequestDetailsType
from trezor.messages.TxRequestSerializedType import TxRequestSerializedType
from trezor.messages import InputScriptType
@ -43,6 +44,17 @@ class TestSignSegwitTxNativeP2WPKH_GRS(unittest.TestCase):
sequence=0xfffffffe,
multisig=None,
)
ptx1 = TransactionType(version=1, lock_time=650645, inputs_cnt=1, outputs_cnt=2, extra_data_len=0)
pinp1 = TxInputType(script_sig=unhexlify('483045022100d9615361c044e91f6dd7bb4455f3ad686cd5a663d7800bb74c448b2706500ccb022026bed24b81a501e8398411c5a9a793741d9bfe39617d51c363dde0a84f44f4f9012102659a6eefcc72d6f2eff92e57095388b17db0b06034946ecd44120e5e7a830ff4'),
prev_hash=unhexlify('1c92508b38239e5c10b23fb46dcf765ee2f3a95b835edbf0943ec21b21711160'),
prev_index=1,
script_type=None,
sequence=4294967293)
pout1 = TxOutputBinType(script_pubkey=unhexlify('0014b31dc2a236505a6cb9201fa0411ca38a254a7bf1'),
amount=12300000)
pout2 = TxOutputBinType(script_pubkey=unhexlify('76a91438cc090e4a4b2e458c33fe35af1c5c0094699ac288ac'),
amount=9887699777)
out1 = TxOutputType(
address='2N4Q5FhU2497BryFfUgbqkAJE87aKDv3V3e',
amount=5000000,
@ -66,6 +78,18 @@ class TestSignSegwitTxNativeP2WPKH_GRS(unittest.TestCase):
TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(inputs=[inp1])),
TxRequest(request_type=TXMETA, details=TxRequestDetailsType(request_index=None, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=ptx1),
TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(inputs=[pinp1])),
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(bin_outputs=[pout1])),
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=1, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(bin_outputs=[pout2])),
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(outputs=[out1])),
@ -144,6 +168,17 @@ class TestSignSegwitTxNativeP2WPKH_GRS(unittest.TestCase):
sequence=0xfffffffe,
multisig=None,
)
ptx1 = TransactionType(version=1, lock_time=650645, inputs_cnt=1, outputs_cnt=2, extra_data_len=0)
pinp1 = TxInputType(script_sig=unhexlify('483045022100d9615361c044e91f6dd7bb4455f3ad686cd5a663d7800bb74c448b2706500ccb022026bed24b81a501e8398411c5a9a793741d9bfe39617d51c363dde0a84f44f4f9012102659a6eefcc72d6f2eff92e57095388b17db0b06034946ecd44120e5e7a830ff4'),
prev_hash=unhexlify('1c92508b38239e5c10b23fb46dcf765ee2f3a95b835edbf0943ec21b21711160'),
prev_index=1,
script_type=None,
sequence=4294967293)
pout1 = TxOutputBinType(script_pubkey=unhexlify('0014b31dc2a236505a6cb9201fa0411ca38a254a7bf1'),
amount=12300000)
pout2 = TxOutputBinType(script_pubkey=unhexlify('76a91438cc090e4a4b2e458c33fe35af1c5c0094699ac288ac'),
amount=9887699777)
out1 = TxOutputType(
address='2N4Q5FhU2497BryFfUgbqkAJE87aKDv3V3e',
amount=5000000,
@ -167,6 +202,18 @@ class TestSignSegwitTxNativeP2WPKH_GRS(unittest.TestCase):
TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(inputs=[inp1])),
TxRequest(request_type=TXMETA, details=TxRequestDetailsType(request_index=None, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=ptx1),
TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(inputs=[pinp1])),
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(bin_outputs=[pout1])),
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=1, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(bin_outputs=[pout2])),
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(outputs=[out1])),

@ -5,10 +5,11 @@ from trezor.crypto import bip39
from trezor.messages.SignTx import SignTx
from trezor.messages.TxInputType import TxInputType
from trezor.messages.TxOutputType import TxOutputType
from trezor.messages.TxOutputBinType import TxOutputBinType
from trezor.messages.TxRequest import TxRequest
from trezor.messages.TxAck import TxAck
from trezor.messages.TransactionType import TransactionType
from trezor.messages.RequestType import TXINPUT, TXOUTPUT, TXFINISHED
from trezor.messages.RequestType import TXINPUT, TXMETA, TXOUTPUT, TXFINISHED
from trezor.messages.TxRequestDetailsType import TxRequestDetailsType
from trezor.messages.TxRequestSerializedType import TxRequestSerializedType
from trezor.messages import InputScriptType
@ -42,6 +43,17 @@ class TestSignSegwitTxP2WPKHInP2SH(unittest.TestCase):
sequence=0xffffffff,
multisig=None,
)
ptx1 = TransactionType(version=1, lock_time=0, inputs_cnt=1, outputs_cnt=2, extra_data_len=0)
pinp1 = TxInputType(script_sig=unhexlify('4730440220548e087d0426b20b8a571b03b9e05829f7558b80c53c12143e342f56ab29e51d02205b68cb7fb223981d4c999725ac1485a982c4259c4f50b8280f137878c232998a012102794a25b254a268e59a5869da57fbae2fadc6727cb3309321dab409b12b2fa17c'),
prev_hash=unhexlify('802cabf0843b945eabe136d7fc7c89f41021658abf56cba000acbce88c41143a'),
prev_index=0,
script_type=None,
sequence=4294967295)
pout1 = TxOutputBinType(script_pubkey=unhexlify('a91458b53ea7f832e8f096e896b8713a8c6df0e892ca87'),
amount=123456789)
pout2 = TxOutputBinType(script_pubkey=unhexlify('76a914b84bacdcd8f4cc59274a5bfb73f804ca10f7fd1488ac'),
amount=865519308)
out1 = TxOutputType(
address='mhRx1CeVfaayqRwq5zgRQmD7W5aWBfD5mC',
amount=12300000,
@ -65,6 +77,18 @@ class TestSignSegwitTxP2WPKHInP2SH(unittest.TestCase):
TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(inputs=[inp1])),
TxRequest(request_type=TXMETA, details=TxRequestDetailsType(request_index=None, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=ptx1),
TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(inputs=[pinp1])),
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(bin_outputs=[pout1])),
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=1, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(bin_outputs=[pout2])),
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(outputs=[out1])),
@ -140,6 +164,17 @@ class TestSignSegwitTxP2WPKHInP2SH(unittest.TestCase):
sequence=0xffffffff,
multisig=None,
)
ptx1 = TransactionType(version=1, lock_time=0, inputs_cnt=1, outputs_cnt=2, extra_data_len=0)
pinp1 = TxInputType(script_sig=unhexlify('4730440220548e087d0426b20b8a571b03b9e05829f7558b80c53c12143e342f56ab29e51d02205b68cb7fb223981d4c999725ac1485a982c4259c4f50b8280f137878c232998a012102794a25b254a268e59a5869da57fbae2fadc6727cb3309321dab409b12b2fa17c'),
prev_hash=unhexlify('802cabf0843b945eabe136d7fc7c89f41021658abf56cba000acbce88c41143a'),
prev_index=0,
script_type=None,
sequence=4294967295)
pout1 = TxOutputBinType(script_pubkey=unhexlify('a91458b53ea7f832e8f096e896b8713a8c6df0e892ca87'),
amount=123456789)
pout2 = TxOutputBinType(script_pubkey=unhexlify('76a914b84bacdcd8f4cc59274a5bfb73f804ca10f7fd1488ac'),
amount=865519308)
out1 = TxOutputType(
address='mhRx1CeVfaayqRwq5zgRQmD7W5aWBfD5mC',
amount=12300000,
@ -163,6 +198,18 @@ class TestSignSegwitTxP2WPKHInP2SH(unittest.TestCase):
TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(inputs=[inp1])),
TxRequest(request_type=TXMETA, details=TxRequestDetailsType(request_index=None, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=ptx1),
TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(inputs=[pinp1])),
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(bin_outputs=[pout1])),
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=1, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(bin_outputs=[pout2])),
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(outputs=[out1])),
@ -232,8 +279,6 @@ class TestSignSegwitTxP2WPKHInP2SH(unittest.TestCase):
with self.assertRaises(StopIteration):
signer.send(None)
# see https://github.com/trezor/trezor-mcu/commit/6b615ce40567cc0da0b3b38ff668916aaae9dd4b#commitcomment-25505919
# for the rational behind this attack
def test_send_p2wpkh_in_p2sh_attack_amount(self):
coin = coins.by_name('Testnet')
@ -249,6 +294,17 @@ class TestSignSegwitTxP2WPKHInP2SH(unittest.TestCase):
sequence=0xffffffff,
multisig=None,
)
ptx1 = TransactionType(version=1, lock_time=0, inputs_cnt=1, outputs_cnt=2, extra_data_len=0)
pinp1 = TxInputType(script_sig=unhexlify('4730440220548e087d0426b20b8a571b03b9e05829f7558b80c53c12143e342f56ab29e51d02205b68cb7fb223981d4c999725ac1485a982c4259c4f50b8280f137878c232998a012102794a25b254a268e59a5869da57fbae2fadc6727cb3309321dab409b12b2fa17c'),
prev_hash=unhexlify('802cabf0843b945eabe136d7fc7c89f41021658abf56cba000acbce88c41143a'),
prev_index=0,
script_type=None,
sequence=4294967295)
pout1 = TxOutputBinType(script_pubkey=unhexlify('a91458b53ea7f832e8f096e896b8713a8c6df0e892ca87'),
amount=123456789)
pout2 = TxOutputBinType(script_pubkey=unhexlify('76a914b84bacdcd8f4cc59274a5bfb73f804ca10f7fd1488ac'),
amount=865519308)
inpattack = TxInputType(
# 49'/1'/0'/1/0" - 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX
address_n=[49 | 0x80000000, 1 | 0x80000000, 0 | 0x80000000, 1, 0],
@ -282,58 +338,19 @@ class TestSignSegwitTxP2WPKHInP2SH(unittest.TestCase):
TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(inputs=[inpattack])),
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(outputs=[out1])),
helpers.UiConfirmOutput(out1, coin),
True,
TxRequest(request_type=TXMETA, details=TxRequestDetailsType(request_index=None, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=ptx1),
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=1, tx_hash=None), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(outputs=[out2])),
TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(inputs=[pinp1])),
helpers.UiConfirmTotal(8, 0, coin),
True,
TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None),
serialized=TxRequestSerializedType(
# returned serialized header
serialized_tx=unhexlify(
'01000000000101'),
)),
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(bin_outputs=[pout1])),
TxAck(tx=TransactionType(inputs=[inp1])),
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=1, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(bin_outputs=[pout2])),
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None),
serialized=TxRequestSerializedType(
# returned serialized inpattack
serialized_tx=unhexlify(
'37c361fb8f2d9056ba8c98c5611930fcb48cacfdd0fe2e0449d83eea982f91200000000017160014d16b8c0680c61fc6ed2e407455715055e41052f5ffffffff02'),
)),
# the out has to be cloned not to send the same object which was modified
TxAck(tx=TransactionType(outputs=[TxOutputType(**out1.__dict__)])),
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=1, tx_hash=None),
serialized=TxRequestSerializedType(
# returned serialized out1
serialized_tx=unhexlify(
'08000000000000001976a91414fdede0ddc3be652a0ce1afbc1b509a55b6b94888ac'),
signature_index=None,
signature=None,
)),
TxAck(tx=TransactionType(outputs=[TxOutputType(**out2.__dict__)])),
# segwit
TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None),
serialized=TxRequestSerializedType(
# returned serialized out2
serialized_tx=unhexlify(
'010000000000000017a91458b53ea7f832e8f096e896b8713a8c6df0e892ca87'),
signature_index=None,
signature=None,
)),
TxAck(tx=TransactionType(inputs=[inp1])),
TxRequest(request_type=TXFINISHED, details=TxRequestDetailsType())
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=EMPTY_SERIALIZED),
]
ns = get_namespaces_for_coin(coin)
@ -343,7 +360,7 @@ class TestSignSegwitTxP2WPKHInP2SH(unittest.TestCase):
messages_count = int(len(messages) / 2)
for request, response in chunks(messages, 2):
if i == messages_count - 1: # last message should throw wire.Error
self.assertRaises(wire.ProcessError, signer.send, request)
self.assertRaises(wire.DataError, signer.send, request)
else:
self.assertEqual(signer.send(request), response)
i += 1

@ -4,11 +4,12 @@ from trezor.utils import chunks
from trezor.crypto import bip39
from trezor.messages.SignTx import SignTx
from trezor.messages.TxInputType import TxInputType
from trezor.messages.TxOutputBinType import TxOutputBinType
from trezor.messages.TxOutputType import TxOutputType
from trezor.messages.TxRequest import TxRequest
from trezor.messages.TxAck import TxAck
from trezor.messages.TransactionType import TransactionType
from trezor.messages.RequestType import TXINPUT, TXOUTPUT, TXFINISHED
from trezor.messages.RequestType import TXINPUT, TXMETA, TXOUTPUT, TXFINISHED
from trezor.messages.TxRequestDetailsType import TxRequestDetailsType
from trezor.messages.TxRequestSerializedType import TxRequestSerializedType
from trezor.messages import InputScriptType
@ -43,6 +44,17 @@ class TestSignSegwitTxP2WPKHInP2SH_GRS(unittest.TestCase):
sequence=0xfffffffe,
multisig=None,
)
ptx1 = TransactionType(version=1, lock_time=650749, inputs_cnt=1, outputs_cnt=2, extra_data_len=0)
pinp1 = TxInputType(script_sig=unhexlify('47304402201f8f57f708144c3a11da322546cb37bd385aa825d940c37e8016f0efd6ec3e9402202a41bc02c29e4f3f13efd4bededbcd4308a6393279111d614ee1f7635cf3e65701210371546a36bdf6bc82087301b3f6e759736dc8790150673d2e7e2715d2ad72f3a4'),
prev_hash=unhexlify('4f2f857f39ed1afe05542d058fb0be865a387446e32fc876d086203f483f61d1'),
prev_index=1,
script_type=None,
sequence=4294967294)
pout1 = TxOutputBinType(script_pubkey=unhexlify('a91458b53ea7f832e8f096e896b8713a8c6df0e892ca87'),
amount=123456789)
pout2 = TxOutputBinType(script_pubkey=unhexlify('76a91435528b20e9a793cf2c3a1cf9cff1f2127ad377da88ac'),
amount=9764242764)
out1 = TxOutputType(
address='mvbu1Gdy8SUjTenqerxUaZyYjmvedc787y',
amount=12300000,
@ -66,6 +78,18 @@ class TestSignSegwitTxP2WPKHInP2SH_GRS(unittest.TestCase):
TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(inputs=[inp1])),
TxRequest(request_type=TXMETA, details=TxRequestDetailsType(request_index=None, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=ptx1),
TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(inputs=[pinp1])),
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(bin_outputs=[pout1])),
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=1, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(bin_outputs=[pout2])),
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(outputs=[out1])),
@ -144,6 +168,17 @@ class TestSignSegwitTxP2WPKHInP2SH_GRS(unittest.TestCase):
sequence=0xfffffffe,
multisig=None,
)
ptx1 = TransactionType(version=1, lock_time=650749, inputs_cnt=1, outputs_cnt=2, extra_data_len=0)
pinp1 = TxInputType(script_sig=unhexlify('47304402201f8f57f708144c3a11da322546cb37bd385aa825d940c37e8016f0efd6ec3e9402202a41bc02c29e4f3f13efd4bededbcd4308a6393279111d614ee1f7635cf3e65701210371546a36bdf6bc82087301b3f6e759736dc8790150673d2e7e2715d2ad72f3a4'),
prev_hash=unhexlify('4f2f857f39ed1afe05542d058fb0be865a387446e32fc876d086203f483f61d1'),
prev_index=1,
script_type=None,
sequence=4294967294)
pout1 = TxOutputBinType(script_pubkey=unhexlify('a91458b53ea7f832e8f096e896b8713a8c6df0e892ca87'),
amount=123456789)
pout2 = TxOutputBinType(script_pubkey=unhexlify('76a91435528b20e9a793cf2c3a1cf9cff1f2127ad377da88ac'),
amount=9764242764)
out1 = TxOutputType(
address='mvbu1Gdy8SUjTenqerxUaZyYjmvedc787y',
amount=12300000,
@ -167,6 +202,18 @@ class TestSignSegwitTxP2WPKHInP2SH_GRS(unittest.TestCase):
TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(inputs=[inp1])),
TxRequest(request_type=TXMETA, details=TxRequestDetailsType(request_index=None, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=ptx1),
TxRequest(request_type=TXINPUT, details=TxRequestDetailsType(request_index=0, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(inputs=[pinp1])),
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(bin_outputs=[pout1])),
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=1, tx_hash=inp1.prev_hash), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(bin_outputs=[pout2])),
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=0, tx_hash=None), serialized=EMPTY_SERIALIZED),
TxAck(tx=TransactionType(outputs=[out1])),

@ -46,6 +46,9 @@ typedef uint32_t b58_almostmaxint_t;
static const b58_almostmaxint_t b58_almostmaxint_mask =
((((b58_maxint_t)1) << b58_almostmaxint_bits) - 1);
// Decodes a null-terminated Base58 string `b58` to binary and writes the result
// at the end of the buffer `bin` of size `*binszp`. On success `*binszp` is set
// to the number of valid bytes at the end of the buffer.
bool b58tobin(void *bin, size_t *binszp, const char *b58) {
size_t binsz = *binszp;
@ -108,20 +111,18 @@ bool b58tobin(void *bin, size_t *binszp, const char *b58) {
}
}
// Count canonical base58 byte count
// locate the most significant byte
binu = bin;
for (i = 0; i < binsz; ++i) {
if (binu[i]) {
if (zerocount > i) {
/* result too large */
return false;
}
if (binu[i]) break;
}
break;
}
--*binszp;
// prepend the correct number of null-bytes
if (zerocount > i) {
/* result too large */
return false;
}
*binszp += zerocount;
*binszp = binsz - i + zerocount;
return true;
}

File diff suppressed because it is too large Load Diff

@ -28,141 +28,145 @@
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "options.h"
// bignum256 are 256 bits stored as 8*30 bit + 1*16 bit
// val[0] are lowest 30 bits, val[8] highest 16 bits
#define BN_LIMBS 9
#define BN_BITS_PER_LIMB 29
#define BN_BASE (1u << BN_BITS_PER_LIMB)
#define BN_LIMB_MASK ((1u << BN_BITS_PER_LIMB) - 1)
#define BN_EXTRA_BITS (32 - BN_BITS_PER_LIMB)
#define BN_BITS_LAST_LIMB (256 - (BN_LIMBS - 1) * BN_BITS_PER_LIMB)
// Represents the number sum([val[i] * 2**(29*i) for i in range(9))
typedef struct {
uint32_t val[9];
uint32_t val[BN_LIMBS];
} bignum256;
// read 4 big endian bytes into uint32
uint32_t read_be(const uint8_t *data);
static inline uint32_t read_be(const uint8_t *data) {
return (((uint32_t)data[0]) << 24) | (((uint32_t)data[1]) << 16) |
(((uint32_t)data[2]) << 8) | (((uint32_t)data[3]));
}
// write 4 big endian bytes
void write_be(uint8_t *data, uint32_t x);
static inline void write_be(uint8_t *data, uint32_t x) {
data[0] = x >> 24;
data[1] = x >> 16;
data[2] = x >> 8;
data[3] = x;
}
// read 4 little endian bytes into uint32
uint32_t read_le(const uint8_t *data);
static inline uint32_t read_le(const uint8_t *data) {
return (((uint32_t)data[3]) << 24) | (((uint32_t)data[2]) << 16) |
(((uint32_t)data[1]) << 8) | (((uint32_t)data[0]));
}
// write 4 little endian bytes
void write_le(uint8_t *data, uint32_t x);
static inline void write_le(uint8_t *data, uint32_t x) {
data[3] = x >> 24;
data[2] = x >> 16;
data[1] = x >> 8;
data[0] = x;
}
void bn_read_be(const uint8_t *in_number, bignum256 *out_number);
void bn_write_be(const bignum256 *in_number, uint8_t *out_number);
void bn_read_le(const uint8_t *in_number, bignum256 *out_number);
void bn_write_le(const bignum256 *in_number, uint8_t *out_number);
void bn_read_uint32(uint32_t in_number, bignum256 *out_number);
void bn_read_uint64(uint64_t in_number, bignum256 *out_number);
static inline uint32_t bn_write_uint32(const bignum256 *in_number) {
return in_number->val[0] | (in_number->val[1] << 30);
}
static inline uint64_t bn_write_uint64(const bignum256 *in_number) {
uint64_t tmp;
tmp = in_number->val[2];
tmp <<= 30;
tmp |= in_number->val[1];
tmp <<= 30;
tmp |= in_number->val[0];
return tmp;
}
// copies number a to b
static inline void bn_copy(const bignum256 *a, bignum256 *b) { *b = *a; }
int bn_bitcount(const bignum256 *a);
unsigned int bn_digitcount(const bignum256 *a);
void bn_zero(bignum256 *a);
int bn_is_zero(const bignum256 *a);
void bn_one(bignum256 *a);
static inline int bn_is_even(const bignum256 *a) {
return (a->val[0] & 1) == 0;
}
static inline int bn_is_odd(const bignum256 *a) { return (a->val[0] & 1) == 1; }
int bn_is_less(const bignum256 *a, const bignum256 *b);
int bn_is_equal(const bignum256 *a, const bignum256 *b);
void bn_cmov(bignum256 *res, int cond, const bignum256 *truecase,
int bn_bitcount(const bignum256 *x);
unsigned int bn_digitcount(const bignum256 *x);
void bn_zero(bignum256 *x);
void bn_one(bignum256 *x);
int bn_is_zero(const bignum256 *x);
int bn_is_one(const bignum256 *x);
int bn_is_less(const bignum256 *x, const bignum256 *y);
int bn_is_equal(const bignum256 *x, const bignum256 *y);
void bn_cmov(bignum256 *res, volatile uint32_t cond, const bignum256 *truecase,
const bignum256 *falsecase);
void bn_lshift(bignum256 *a);
void bn_rshift(bignum256 *a);
void bn_setbit(bignum256 *a, uint8_t bit);
void bn_clearbit(bignum256 *a, uint8_t bit);
uint32_t bn_testbit(bignum256 *a, uint8_t bit);
void bn_xor(bignum256 *a, const bignum256 *b, const bignum256 *c);
void bn_cnegate(volatile uint32_t cond, bignum256 *x, const bignum256 *prime);
void bn_lshift(bignum256 *x);
void bn_rshift(bignum256 *x);
void bn_setbit(bignum256 *x, uint16_t i);
void bn_clearbit(bignum256 *x, uint16_t i);
uint32_t bn_testbit(const bignum256 *x, uint16_t i);
void bn_xor(bignum256 *res, const bignum256 *x, const bignum256 *y);
void bn_mult_half(bignum256 *x, const bignum256 *prime);
void bn_mult_k(bignum256 *x, uint8_t k, const bignum256 *prime);
void bn_mod(bignum256 *x, const bignum256 *prime);
void bn_multiply(const bignum256 *k, bignum256 *x, const bignum256 *prime);
void bn_fast_mod_old(bignum256 *x, const bignum256 *prime);
void bn_fast_mod(bignum256 *x, const bignum256 *prime);
void bn_power_mod(const bignum256 *x, const bignum256 *e,
const bignum256 *prime, bignum256 *res);
void bn_sqrt(bignum256 *x, const bignum256 *prime);
uint32_t inverse_mod_power_two(uint32_t a, uint32_t n);
void bn_divide_base(bignum256 *x, const bignum256 *prime);
void bn_inverse_slow(bignum256 *x, const bignum256 *prime);
void bn_inverse_fast_1(bignum256 *x, const bignum256 *prime);
void bn_inverse_fast_2(bignum256 *x, const bignum256 *prime);
void bn_inverse_fast_3(bignum256 *x, const bignum256 *prime);
void bn_inverse_old(bignum256 *x, const bignum256 *prime);
void bn_normalize(bignum256 *x);
void bn_add(bignum256 *x, const bignum256 *y);
void bn_addmod(bignum256 *x, const bignum256 *y, const bignum256 *prime);
void bn_addi(bignum256 *x, uint32_t y);
void bn_subi(bignum256 *x, uint32_t y, const bignum256 *prime);
void bn_subtractmod(const bignum256 *x, const bignum256 *y, bignum256 *res,
const bignum256 *prime);
void bn_subtract(const bignum256 *x, const bignum256 *y, bignum256 *res);
void bn_long_division(bignum256 *x, uint32_t d, bignum256 *q, uint32_t *r);
void bn_divmod58(bignum256 *x, uint32_t *r);
void bn_divmod1000(bignum256 *x, uint32_t *r);
void bn_inverse(bignum256 *x, const bignum256 *prime);
size_t bn_format(const bignum256 *amount, const char *prefix,
const char *suffix, unsigned int decimals, int exponent,
bool trailing, char *output, size_t output_length);
void bn_normalize(bignum256 *a);
void bn_add(bignum256 *a, const bignum256 *b);
void bn_addmod(bignum256 *a, const bignum256 *b, const bignum256 *prime);
void bn_addi(bignum256 *a, uint32_t b);
void bn_subi(bignum256 *a, uint32_t b, const bignum256 *prime);
void bn_subtractmod(const bignum256 *a, const bignum256 *b, bignum256 *res,
const bignum256 *prime);
// Returns (uint32_t) in_number
// Assumes in_number < 2**32
// Assumes in_number is normalized
static inline uint32_t bn_write_uint32(const bignum256 *in_number) {
return in_number->val[0] | (in_number->val[1] << BN_BITS_PER_LIMB);
}
void bn_subtract(const bignum256 *a, const bignum256 *b, bignum256 *res);
// Returns (uint64_t) in_number
// Assumes in_number < 2**64
// Assumes in_number is normalized
static inline uint64_t bn_write_uint64(const bignum256 *in_number) {
uint64_t acc;
acc = in_number->val[2];
acc <<= BN_BITS_PER_LIMB;
acc |= in_number->val[1];
acc <<= BN_BITS_PER_LIMB;
acc |= in_number->val[0];
return acc;
}
void bn_divmod58(bignum256 *a, uint32_t *r);
// y = x
static inline void bn_copy(const bignum256 *x, bignum256 *y) { *y = *x; }
void bn_divmod1000(bignum256 *a, uint32_t *r);
// Returns x % 2 == 0
static inline int bn_is_even(const bignum256 *x) {
return (x->val[0] & 1) == 0;
}
size_t bn_format(const bignum256 *amnt, const char *prefix, const char *suffix,
unsigned int decimals, int exponent, bool trailing, char *out,
size_t outlen);
// Returns x % 2 == 0
static inline int bn_is_odd(const bignum256 *x) { return (x->val[0] & 1) == 1; }
static inline size_t bn_format_uint64(uint64_t amount, const char *prefix,
const char *suffix, unsigned int decimals,
int exponent, bool trailing, char *out,
size_t outlen) {
bignum256 amnt;
bn_read_uint64(amount, &amnt);
int exponent, bool trailing, char *output,
size_t output_length) {
bignum256 bn_amount;
bn_read_uint64(amount, &bn_amount);
return bn_format(&amnt, prefix, suffix, decimals, exponent, trailing, out,
outlen);
return bn_format(&bn_amount, prefix, suffix, decimals, exponent, trailing,
output, output_length);
}
#if USE_BN_PRINT
void bn_print(const bignum256 *a);
void bn_print_raw(const bignum256 *a);
void bn_print(const bignum256 *x);
void bn_print_raw(const bignum256 *x);
#endif
#endif

@ -61,6 +61,7 @@ void point_add(const ecdsa_curve *curve, const curve_point *cp1,
return;
}
// lambda = (y2 - y1) / (x2 - x1)
bn_subtractmod(&(cp2->x), &(cp1->x), &inv, &curve->prime);
bn_inverse(&inv, &curve->prime);
bn_subtractmod(&(cp2->y), &(cp1->y), &lambda, &curve->prime);
@ -101,6 +102,8 @@ void point_double(const ecdsa_curve *curve, curve_point *cp) {
// lambda = (3 x^2 + a) / (2 y)
lambda = cp->y;
bn_mult_k(&lambda, 2, &curve->prime);
bn_fast_mod(&lambda, &curve->prime);
bn_mod(&lambda, &curve->prime);
bn_inverse(&lambda, &curve->prime);
xr = cp->x;
@ -162,22 +165,6 @@ int point_is_negative_of(const curve_point *p, const curve_point *q) {
return !bn_is_equal(&(p->y), &(q->y));
}
// Negate a (modulo prime) if cond is 0xffffffff, keep it if cond is 0.
// The timing of this function does not depend on cond.
void conditional_negate(uint32_t cond, bignum256 *a, const bignum256 *prime) {
int j = 0;
uint32_t tmp = 1;
assert(a->val[8] < 0x20000);
for (j = 0; j < 8; j++) {
tmp += 0x3fffffff + 2 * prime->val[j] - a->val[j];
a->val[j] = ((tmp & 0x3fffffff) & cond) | (a->val[j] & ~cond);
tmp >>= 30;
}
tmp += 0x3fffffff + 2 * prime->val[j] - a->val[j];
a->val[j] = ((tmp & 0x3fffffff) & cond) | (a->val[j] & ~cond);
assert(a->val[8] < 0x20000);
}
typedef struct jacobian_curve_point {
bignum256 x, y, z;
} jacobian_curve_point;
@ -187,9 +174,9 @@ static void generate_k_random(bignum256 *k, const bignum256 *prime) {
do {
int i = 0;
for (i = 0; i < 8; i++) {
k->val[i] = random32() & 0x3FFFFFFF;
k->val[i] = random32() & ((1u << BN_BITS_PER_LIMB) - 1);
}
k->val[8] = random32() & 0xFFFF;
k->val[8] = random32() & ((1u << BN_BITS_LAST_LIMB) - 1);
// check that k is in range and not zero.
} while (bn_is_zero(k) || !bn_is_less(k, prime));
}
@ -443,12 +430,12 @@ void point_multiply(const ecdsa_curve *curve, const bignum256 *k,
uint32_t is_non_zero = 0;
for (j = 0; j < 8; j++) {
is_non_zero |= k->val[j];
tmp += 0x3fffffff + k->val[j] - (curve->order.val[j] & is_even);
a.val[j] = tmp & 0x3fffffff;
tmp >>= 30;
tmp += (BN_BASE - 1) + k->val[j] - (curve->order.val[j] & is_even);
a.val[j] = tmp & (BN_BASE - 1);
tmp >>= BN_BITS_PER_LIMB;
}
is_non_zero |= k->val[j];
a.val[j] = tmp + 0xffff + k->val[j] - (curve->order.val[j] & is_even);
a.val[j] = tmp + 0xffffff + k->val[j] - (curve->order.val[j] & is_even);
assert((a.val[0] & 1) != 0);
// special case 0*p: just return zero. We don't care about constant time.
@ -490,7 +477,7 @@ void point_multiply(const ecdsa_curve *curve, const bignum256 *k,
// since a is odd.
aptr = &a.val[8];
abits = *aptr;
ashift = 12;
ashift = 256 - (BN_BITS_PER_LIMB * 8) - 4;
bits = abits >> ashift;
sign = (bits >> 4) - 1;
bits ^= sign;
@ -513,7 +500,7 @@ void point_multiply(const ecdsa_curve *curve, const bignum256 *k,
// leaks no private information to a side-channel.
bits = abits << (-ashift);
abits = *(--aptr);
ashift += 30;
ashift += BN_BITS_PER_LIMB;
bits |= abits >> ashift;
} else {
bits = abits >> ashift;
@ -525,13 +512,13 @@ void point_multiply(const ecdsa_curve *curve, const bignum256 *k,
// negate last result to make signs of this round and the
// last round equal.
conditional_negate(sign ^ nsign, &jres.z, prime);
bn_cnegate((sign ^ nsign) & 1, &jres.z, prime);
// add odd factor
point_jacobian_add(&pmult[bits >> 1], &jres, curve);
sign = nsign;
}
conditional_negate(sign, &jres.z, prime);
bn_cnegate(sign & 1, &jres.z, prime);
jacobian_to_curve(&jres, res, prime);
memzero(&a, sizeof(a));
memzero(&jres, sizeof(jres));
@ -560,12 +547,12 @@ void scalar_multiply(const ecdsa_curve *curve, const bignum256 *k,
uint32_t is_non_zero = 0;
for (j = 0; j < 8; j++) {
is_non_zero |= k->val[j];
tmp += 0x3fffffff + k->val[j] - (curve->order.val[j] & is_even);
a.val[j] = tmp & 0x3fffffff;
tmp >>= 30;
tmp += (BN_BASE - 1) + k->val[j] - (curve->order.val[j] & is_even);
a.val[j] = tmp & (BN_BASE - 1);
tmp >>= BN_BITS_PER_LIMB;
}
is_non_zero |= k->val[j];
a.val[j] = tmp + 0xffff + k->val[j] - (curve->order.val[j] & is_even);
a.val[j] = tmp + 0xffffff + k->val[j] - (curve->order.val[j] & is_even);
assert((a.val[0] & 1) != 0);
// special case 0*G: just return zero. We don't care about constant time.
@ -603,7 +590,8 @@ void scalar_multiply(const ecdsa_curve *curve, const bignum256 *k,
// shift a by 4 places.
for (j = 0; j < 8; j++) {
a.val[j] = (a.val[j] >> 4) | ((a.val[j + 1] & 0xf) << 26);
a.val[j] =
(a.val[j] >> 4) | ((a.val[j + 1] & 0xf) << (BN_BITS_PER_LIMB - 4));
}
a.val[j] >>= 4;
// a = old(a)>>(4*i)
@ -614,12 +602,12 @@ void scalar_multiply(const ecdsa_curve *curve, const bignum256 *k,
lowbits &= 15;
// negate last result to make signs of this round and the
// last round equal.
conditional_negate((lowbits & 1) - 1, &jres.y, prime);
bn_cnegate(~lowbits & 1, &jres.y, prime);
// add odd factor
point_jacobian_add(&curve->cp[i][lowbits >> 1], &jres, curve);
}
conditional_negate(((a.val[0] >> 4) & 1) - 1, &jres.y, prime);
bn_cnegate(~(a.val[0] >> 4) & 1, &jres.y, prime);
jacobian_to_curve(&jres, res, prime);
memzero(&a, sizeof(a));
memzero(&jres, sizeof(jres));

@ -102,6 +102,8 @@ bool decode_block(const char* block, size_t size, char* res)
uint64_t order = 1;
for (size_t i = size - 1; i < size; --i)
{
if (block[i] & 0x80)
return false; // Invalid symbol
int digit = reverse_alphabet(block[i]);
if (digit < 0)
return false; // Invalid symbol

@ -24,30 +24,31 @@
#include "nist256p1.h"
const ecdsa_curve nist256p1 = {
/* .prime */ {/*.val =*/{0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3f, 0x0, 0x0,
0x1000, 0x3fffc000, 0xffff}},
/* .prime */ {/*.val =*/{0x1fffffff, 0x1fffffff, 0x1fffffff, 0x000001ff,
0x00000000, 0x00000000, 0x00040000, 0x1fe00000,
0xffffff}},
/* G */
{/*.x =*/{/*.val =*/{0x1898c296, 0x1284e517, 0x1eb33a0f, 0xdf604b,
0x2440f277, 0x339b958e, 0x4247f8b, 0x347cb84b,
0x6b17}},
/*.y =*/{/*.val =*/{0x37bf51f5, 0x2ed901a0, 0x3315ecec, 0x338cd5da,
0xf9e162b, 0x1fad29f0, 0x27f9b8ee, 0x10b8bf86,
0x4fe3}}},
{/*.x =*/{/*.val =*/{0x1898c296, 0x0509ca2e, 0x1acce83d, 0x06fb025b,
0x040f2770, 0x1372b1d2, 0x091fe2f3, 0x1e5c2588,
0x6b17d1}},
/*.y =*/{/*.val =*/{0x17bf51f5, 0x1db20341, 0x0c57b3b2, 0x1c66aed6,
0x19e162bc, 0x15a53e07, 0x1e6e3b9f, 0x1c5fc34f,
0x4fe342}}},
/* order */
{/*.val =*/{0x3c632551, 0xee72b0b, 0x3179e84f, 0x39beab69, 0x3fffffbc,
0x3fffffff, 0xfff, 0x3fffc000, 0xffff}},
{/*.val =*/{0x1c632551, 0x1dce5617, 0x05e7a13c, 0x0df55b4e, 0x1ffffbce,
0x1fffffff, 0x0003ffff, 0x1fe00000, 0xffffff}},
/* order_half */
{/*.val =*/{0x3e3192a8, 0x27739585, 0x38bcf427, 0x1cdf55b4, 0x3fffffde,
0x3fffffff, 0x7ff, 0x3fffe000, 0x7fff}},
{/*.val =*/{0x1e3192a8, 0x0ee72b0b, 0x02f3d09e, 0x06faada7, 0x1ffffde7,
0x1fffffff, 0x0001ffff, 0x1ff00000, 0x7fffff}},
/* a */ -3,
/* b */
{/*.val =*/{0x27d2604b, 0x2f38f0f8, 0x53b0f63, 0x741ac33, 0x1886bc65,
0x2ef555da, 0x293e7b3e, 0xd762a8e, 0x5ac6}}
{/*.val =*/{0x07d2604b, 0x1e71e1f1, 0x14ec3d8e, 0x1a0d6198, 0x086bc651,
0x1eaabb4c, 0x0f9ecfae, 0x1b154752, 0x005ac635}}
#if USE_PRECOMPUTED_CP
,

File diff suppressed because it is too large Load Diff

@ -24,24 +24,25 @@
#include "secp256k1.h"
const ecdsa_curve secp256k1 = {
/* .prime */ {/*.val =*/{0x3ffffc2f, 0x3ffffffb, 0x3fffffff, 0x3fffffff,
0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff,
0xffff}},
/* .prime */ {/*.val =*/{0x1ffffc2f, 0x1ffffff7, 0x1fffffff, 0x1fffffff,
0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff,
0xffffff}},
/* G */
{/*.x =*/{/*.val =*/{0x16f81798, 0x27ca056c, 0x1ce28d95, 0x26ff36cb,
0x70b0702, 0x18a573a, 0xbbac55a, 0x199fbe77, 0x79be}},
/*.y =*/{/*.val =*/{0x3b10d4b8, 0x311f423f, 0x28554199, 0x5ed1229,
0x1108a8fd, 0x13eff038, 0x3c4655da, 0x369dc9a8,
0x483a}}},
{/*.x =*/{/*.val =*/{0x16f81798, 0x0f940ad8, 0x138a3656, 0x17f9b65b,
0x10b07029, 0x114ae743, 0x0eb15681, 0x0fdf3b97,
0x79be66}},
/*.y =*/{/*.val =*/{0x1b10d4b8, 0x023e847f, 0x01550667, 0x0f68914d,
0x108a8fd1, 0x1dfe0708, 0x11957693, 0x0ee4d478,
0x483ada}}},
/* order */
{/*.val =*/{0x10364141, 0x3f497a33, 0x348a03bb, 0x2bb739ab, 0x3ffffeba,
0x3fffffff, 0x3fffffff, 0x3fffffff, 0xffff}},
{/*.val =*/{0x10364141, 0x1e92f466, 0x12280eef, 0x1db9cd5e, 0x1fffebaa,
0x1fffffff, 0x1fffffff, 0x1fffffff, 0xffffff}},
/* order_half */
{/*.val =*/{0x281b20a0, 0x3fa4bd19, 0x3a4501dd, 0x15db9cd5, 0x3fffff5d,
0x3fffffff, 0x3fffffff, 0x3fffffff, 0x7fff}},
{/*.val =*/{0x081b20a0, 0x1f497a33, 0x09140777, 0x0edce6af, 0x1ffff5d5,
0x1fffffff, 0x1fffffff, 0x1fffffff, 0x7fffff}},
/* a */ 0,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -131,8 +131,8 @@ START_TEST(test_bignum_read_be) {
bn_read_be(input, &a);
bignum256 b = {{0x286d8bd5, 0x380c7c17, 0x3c6a2ec1, 0x2d787ef5, 0x14437cd3,
0x25a043f8, 0x1dd5263f, 0x33a162c3, 0x0000c55e}};
bignum256 b = {{0x086d8bd5, 0x1018f82f, 0x11a8bb07, 0x0bc3f7af, 0x0437cd3b,
0x14087f0a, 0x15498fe5, 0x10b161bb, 0xc55ece}};
for (int i = 0; i < 9; i++) {
ck_assert_int_eq(a.val[i], b.val[i]);
@ -141,8 +141,8 @@ START_TEST(test_bignum_read_be) {
END_TEST
START_TEST(test_bignum_write_be) {
bignum256 a = {{0x286d8bd5, 0x380c7c17, 0x3c6a2ec1, 0x2d787ef5, 0x14437cd3,
0x25a043f8, 0x1dd5263f, 0x33a162c3, 0x0000c55e}};
bignum256 a = {{0x086d8bd5, 0x1018f82f, 0x11a8bb07, 0x0bc3f7af, 0x0437cd3b,
0x14087f0a, 0x15498fe5, 0x10b161bb, 0xc55ece}};
uint8_t tmp[32];
bn_write_be(&a, tmp);
@ -156,10 +156,10 @@ START_TEST(test_bignum_write_be) {
END_TEST
START_TEST(test_bignum_is_equal) {
bignum256 a = {{0x286d8bd5, 0x380c7c17, 0x3c6a2ec1, 0x2d787ef5, 0x14437cd3,
0x25a043f8, 0x1dd5263f, 0x33a162c3, 0x0000c55e}};
bignum256 b = {{0x286d8bd5, 0x380c7c17, 0x3c6a2ec1, 0x2d787ef5, 0x14437cd3,
0x25a043f8, 0x1dd5263f, 0x33a162c3, 0x0000c55e}};
bignum256 a = {{0x086d8bd5, 0x1018f82f, 0x11a8bb07, 0x0bc3f7af, 0x0437cd3b,
0x14087f0a, 0x15498fe5, 0x10b161bb, 0xc55ece}};
bignum256 b = {{0x086d8bd5, 0x1018f82f, 0x11a8bb07, 0x0bc3f7af, 0x0437cd3b,
0x14087f0a, 0x15498fe5, 0x10b161bb, 0xc55ece}};
bignum256 c = {{
0,
}};
@ -339,6 +339,13 @@ END_TEST
START_TEST(test_bignum_write_uint32) {
bignum256 a;
// lowest 29 bits set
bn_read_be(
fromhex(
"000000000000000000000000000000000000000000000000000000001fffffff"),
&a);
ck_assert_int_eq(bn_write_uint32(&a), 0x1fffffff);
// lowest 30 bits set
bn_read_be(
fromhex(
@ -637,8 +644,8 @@ START_TEST(test_bignum_format) {
"0000000000000000000000000000000000000000000000000000000000000000"),
&a);
r = bn_format(&a, NULL, NULL, 18, 0, false, buf, sizeof(buf));
ck_assert_int_eq(r, 3);
ck_assert_str_eq(buf, "0.0");
ck_assert_int_eq(r, 1);
ck_assert_str_eq(buf, "0");
bn_read_be(
fromhex(
@ -757,8 +764,8 @@ START_TEST(test_bignum_format) {
"0000000000000000000000000000000000000000000000000000000000989680"),
&a);
r = bn_format(&a, NULL, NULL, 7, 0, false, buf, sizeof(buf));
ck_assert_int_eq(r, 3);
ck_assert_str_eq(buf, "1.0");
ck_assert_int_eq(r, 1);
ck_assert_str_eq(buf, "1");
bn_read_be(
fromhex(
@ -805,10 +812,10 @@ START_TEST(test_bignum_format) {
"fffffffffffffffffffffffffffffffffffffffffffffffffffffffffe3bbb00"),
&a);
r = bn_format(&a, NULL, NULL, 8, 0, false, buf, sizeof(buf));
ck_assert_int_eq(r, 72);
ck_assert_int_eq(r, 70);
ck_assert_str_eq(buf,
"11579208923731619542357098500868790785326998466564056403945"
"75840079131.0");
"75840079131");
bn_read_be(
fromhex(
@ -825,9 +832,9 @@ START_TEST(test_bignum_format) {
"fffffffffffffffffffffffffffffffffffffffffffffffff7e52fe5afe40000"),
&a);
r = bn_format(&a, NULL, NULL, 18, 0, false, buf, sizeof(buf));
ck_assert_int_eq(r, 62);
ck_assert_int_eq(r, 60);
ck_assert_str_eq(
buf, "115792089237316195423570985008687907853269984665640564039457.0");
buf, "115792089237316195423570985008687907853269984665640564039457");
bn_read_be(
fromhex(
@ -875,7 +882,69 @@ START_TEST(test_bignum_format) {
memset(buf, 'a', sizeof(buf));
r = bn_format(&a, "prefix", "suffix", 10, 0, false, buf, 30);
ck_assert_int_eq(r, 0);
ck_assert_str_eq(buf, "prefix198552.9216486895suffix");
ck_assert_str_eq(buf, "");
}
END_TEST
START_TEST(test_bignum_sqrt) {
uint32_t quadratic_residua[] = {
1, 2, 4, 8, 9, 11, 15, 16, 17, 18, 19, 21, 22, 25, 29,
30, 31, 32, 34, 35, 36, 38, 39, 42, 43, 44, 47, 49, 50, 58,
59, 60, 61, 62, 64, 65, 67, 68, 69, 70, 71, 72, 76, 78, 81,
83, 84, 86, 88, 91, 94, 98, 99, 100, 103, 107, 111, 115, 116, 118,
120, 121, 122, 123, 124, 127, 128, 130, 131, 134, 135, 136, 137, 138, 139,
140, 142, 144, 149, 152, 153, 156, 159, 161, 162, 165, 166, 167, 168, 169,
171, 172, 176, 181, 182, 185, 187, 188, 189, 191, 193, 196, 197, 198, 200,
205, 206, 209, 214, 219, 222, 223, 225, 229, 230, 231, 232, 233, 236, 237,
239, 240, 242, 244, 246, 248, 254, 255, 256, 259, 260, 261, 262, 265, 267,
268, 269, 270, 272, 274, 275, 276, 277, 278, 279, 280, 281, 284, 285, 287,
288, 289, 291, 293, 298, 299, 303, 304, 306, 311, 312, 315, 318, 319, 322,
323, 324, 327, 330, 331, 332, 334, 336, 337, 338, 339, 341, 342, 344, 349,
351, 352, 353, 357, 359, 361, 362, 364, 365, 370, 371, 373, 374, 375, 376,
378, 379, 382, 383, 385, 386, 387, 389, 392, 394, 395, 396, 399, 400, 409,
410, 412, 418, 421, 423, 425, 428, 429, 431, 435, 438, 439, 441, 443, 444,
445, 446, 450, 453, 458, 460, 461, 462, 463, 464, 465, 466, 467, 471, 472,
473, 474, 475, 478, 479, 480, 481, 484, 485, 487, 488, 489, 492, 493, 496,
503, 505, 508, 510, 511, 512, 517, 518, 519, 520, 521, 522, 523, 524, 525,
527, 529, 530, 531, 533, 534, 536, 537, 538, 539, 540, 541, 544, 545, 547,
548, 549, 550, 551, 552, 553, 554, 556, 557, 558, 560, 562, 563, 565, 568,
570, 571, 574, 576, 578, 582, 585, 586, 587, 589, 595, 596, 597, 598, 599,
603, 606, 607, 608, 609, 612, 613, 619, 621, 622, 623, 624, 625, 630, 633,
636, 638, 639, 644, 645, 646, 648, 649, 651, 653, 654, 660, 662, 663, 664,
665, 668, 671, 672, 673, 674, 676, 678, 679, 681, 682, 684, 688, 689, 698,
702, 704, 705, 706, 707, 714, 715, 718, 722, 723, 724, 725, 728, 729, 730,
731, 733, 735, 737, 740, 741, 742, 746, 747, 748, 750, 751, 752, 753, 755,
756, 758, 759, 761, 763, 764, 766, 769, 770, 771, 772, 774, 775, 778, 781,
784, 785, 788, 789, 790, 791, 792, 797, 798, 799, 800, 813, 815, 817, 818,
819, 820, 823, 824, 833, 836, 841, 842, 846, 849, 850, 851, 856, 857, 858,
862, 865, 870, 875, 876, 878, 882, 885, 886, 887, 888, 890, 891, 892, 893,
895, 899, 900, 903, 906, 907, 911, 913, 915, 916, 919, 920, 921, 922, 924,
926, 927, 928, 930, 931, 932, 934, 937, 939, 942, 943, 944, 946, 948, 949,
950, 951, 953, 956, 958, 960, 961, 962, 963, 968, 970, 971, 974, 975, 976,
977, 978, 984, 986, 987, 992, 995, 999};
bignum256 a, b;
bn_zero(&a);
b = a;
bn_sqrt(&b, &secp256k1.prime);
ck_assert_int_eq(bn_is_equal(&a, &b), 1);
bn_one(&a);
b = a;
bn_sqrt(&b, &secp256k1.prime);
ck_assert_int_eq(bn_is_equal(&a, &b), 1);
// test some quadratic residua
for (size_t i = 0; i < sizeof(quadratic_residua) / sizeof(*quadratic_residua);
i++) {
bn_read_uint32(quadratic_residua[i], &a);
b = a;
bn_sqrt(&b, &secp256k1.prime);
bn_multiply(&b, &b, &secp256k1.prime);
bn_mod(&b, &secp256k1.prime);
ck_assert_int_eq(bn_is_equal(&a, &b), 1);
}
}
END_TEST
@ -1102,12 +1171,16 @@ START_TEST(test_bignum_divmod) {
uint32_t r;
int i;
bignum256 a = {{0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff,
0x3fffffff, 0x3fffffff, 0x3fffffff, 0xffff}};
bignum256 a;
uint32_t ar[] = {15, 14, 55, 29, 44, 24, 53, 49, 18, 55, 2, 28, 5, 4, 12,
43, 18, 37, 28, 14, 30, 46, 12, 11, 17, 10, 10, 13, 24, 45,
4, 33, 44, 42, 2, 46, 34, 43, 45, 28, 21, 18, 13, 17};
bn_read_be(
fromhex(
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
&a);
i = 0;
while (!bn_is_zero(&a) && i < 44) {
bn_divmod58(&a, &r);
@ -1116,12 +1189,15 @@ START_TEST(test_bignum_divmod) {
}
ck_assert_int_eq(i, 44);
bignum256 b = {{0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff,
0x3fffffff, 0x3fffffff, 0x3fffffff, 0xffff}};
bignum256 b;
uint32_t br[] = {935, 639, 129, 913, 7, 584, 457, 39, 564,
640, 665, 984, 269, 853, 907, 687, 8, 985,
570, 423, 195, 316, 237, 89, 792, 115};
bn_read_be(
fromhex(
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
&b);
i = 0;
while (!bn_is_zero(&b) && i < 26) {
bn_divmod1000(&b, &r);
@ -5904,7 +5980,8 @@ static void test_codepoints_curve(const ecdsa_curve *curve) {
for (i = 0; i < 64; i++) {
for (j = 0; j < 8; j++) {
bn_zero(&a);
a.val[(4 * i) / 30] = (uint32_t)(2 * j + 1) << (4 * i % 30);
a.val[(4 * i) / BN_BITS_PER_LIMB] = (uint32_t)(2 * j + 1)
<< (4 * i % BN_BITS_PER_LIMB);
bn_normalize(&a);
// note that this is not a trivial test. We add 64 curve
// points in the table to get that particular curve point.
@ -8670,6 +8747,7 @@ Suite *test_suite(void) {
tcase_add_test(tc, test_bignum_is_less);
tcase_add_test(tc, test_bignum_format);
tcase_add_test(tc, test_bignum_format_uint64);
tcase_add_test(tc, test_bignum_sqrt);
suite_add_tcase(s, tc);
tc = tcase_create("base32");

@ -80,14 +80,29 @@ random_iters = int(os.environ.get("ITERS", 1))
DIR = os.path.abspath(os.path.dirname(__file__))
lib = c.cdll.LoadLibrary(os.path.join(DIR, "libtrezor-crypto.so"))
BIGNUM = c.c_uint32 * 9
class curve_info(c.Structure):
_fields_ = [("bip32_name", c.c_char_p), ("params", c.c_void_p)]
lib.get_curve_by_name.restype = c.POINTER(curve_info)
class curve_point(c.Structure):
_fields_ = [("x", BIGNUM), ("y", BIGNUM)]
BIGNUM = c.c_uint32 * 9
class ecdsa_curve(c.Structure):
_fields_ = [
("prime", BIGNUM),
("G", curve_point),
("order", BIGNUM),
("order_half", BIGNUM),
("a", c.c_int),
("b", BIGNUM),
]
lib.get_curve_by_name.restype = c.POINTER(curve_info)
class Random(random.Random):
@ -106,15 +121,15 @@ def int2bn(x, bn_type=BIGNUM):
b = bn_type()
b._int = x
for i in range(len(b)):
b[i] = x % (1 << 30)
x = x >> 30
b[i] = x % (1 << 29)
x = x >> 29
return b
def bn2int(b):
x = 0
for i in range(len(b)):
x += b[i] << (30 * i)
x += b[i] << (29 * i)
return x
@ -130,7 +145,7 @@ def curve(request):
curve_ptr = lib.get_curve_by_name(bytes(name, "ascii")).contents.params
assert curve_ptr, "curve {} not found".format(name)
curve_obj = curves[name]
curve_obj.ptr = c.c_void_p(curve_ptr)
curve_obj.ptr = c.cast(curve_ptr, c.POINTER(ecdsa_curve))
curve_obj.p = curve_obj.curve.p() # shorthand
return curve_obj
@ -148,176 +163,6 @@ def point(request):
return curve_obj
def test_inverse(curve, r):
x = r.randrange(1, curve.p)
y = int2bn(x)
lib.bn_inverse(y, int2bn(curve.p))
y = bn2int(y)
y_ = ecdsa.numbertheory.inverse_mod(x, curve.p)
assert y == y_
def test_is_less(curve, r):
x = r.randrange(0, curve.p)
y = r.randrange(0, curve.p)
x_ = int2bn(x)
y_ = int2bn(y)
res = lib.bn_is_less(x_, y_)
assert res == (x < y)
res = lib.bn_is_less(y_, x_)
assert res == (y < x)
def test_is_equal(curve, r):
x = r.randrange(0, curve.p)
y = r.randrange(0, curve.p)
x_ = int2bn(x)
y_ = int2bn(y)
assert lib.bn_is_equal(x_, y_) == (x == y)
assert lib.bn_is_equal(x_, x_) == 1
assert lib.bn_is_equal(y_, y_) == 1
def test_is_zero(curve, r):
x = r.randrange(0, curve.p)
assert lib.bn_is_zero(int2bn(x)) == (not x)
def test_simple_comparisons():
assert lib.bn_is_zero(int2bn(0)) == 1
assert lib.bn_is_zero(int2bn(1)) == 0
assert lib.bn_is_less(int2bn(0), int2bn(0)) == 0
assert lib.bn_is_less(int2bn(1), int2bn(0)) == 0
assert lib.bn_is_less(int2bn(0), int2bn(1)) == 1
assert lib.bn_is_equal(int2bn(0), int2bn(0)) == 1
assert lib.bn_is_equal(int2bn(1), int2bn(0)) == 0
assert lib.bn_is_equal(int2bn(0), int2bn(1)) == 0
def test_mult_half(curve, r):
x = r.randrange(0, 2 * curve.p)
y = int2bn(x)
lib.bn_mult_half(y, int2bn(curve.p))
y = bn2int(y)
if y >= curve.p:
y -= curve.p
half = ecdsa.numbertheory.inverse_mod(2, curve.p)
assert y == (x * half) % curve.p
def test_subtractmod(curve, r):
x = r.randrange(0, 2 ** 256)
y = r.randrange(0, 2 ** 256)
z = int2bn(0)
lib.bn_subtractmod(int2bn(x), int2bn(y), z, int2bn(curve.p))
z = bn2int(z)
z_ = x + 2 * curve.p - y
assert z == z_
def test_subtract2(r):
x = r.randrange(0, 2 ** 256)
y = r.randrange(0, 2 ** 256)
x, y = max(x, y), min(x, y)
z = int2bn(0)
lib.bn_subtract(int2bn(x), int2bn(y), z)
z = bn2int(z)
z_ = x - y
assert z == z_
def test_add(curve, r):
x = r.randrange(0, 2 ** 256)
y = r.randrange(0, 2 ** 256)
z_ = x + y
z = int2bn(x)
lib.bn_add(z, int2bn(y))
z = bn2int(z)
assert z == z_
def test_addmod(curve, r):
x = r.randrange(0, 2 ** 256)
y = r.randrange(0, 2 ** 256)
z_ = (x + y) % curve.p
z = int2bn(x)
lib.bn_addmod(z, int2bn(y), int2bn(curve.p))
z = bn2int(z)
if z >= curve.p:
z = z - curve.p
assert z == z_
def test_multiply(curve, r):
k = r.randrange(0, 2 * curve.p)
x = r.randrange(0, 2 * curve.p)
z = (k * x) % curve.p
k = int2bn(k)
z_ = int2bn(x)
p_ = int2bn(curve.p)
lib.bn_multiply(k, z_, p_)
z_ = bn2int(z_)
assert z_ < 2 * curve.p
if z_ >= curve.p:
z_ = z_ - curve.p
assert z_ == z
def test_multiply1(curve, r):
k = r.randrange(0, 2 * curve.p)
x = r.randrange(0, 2 * curve.p)
kx = k * x
res = int2bn(0, bn_type=(c.c_uint32 * 18))
lib.bn_multiply_long(int2bn(k), int2bn(x), res)
res = bn2int(res)
assert res == kx
def test_multiply2(curve, r):
x = int2bn(0)
s = r.randrange(0, 2 ** 526)
res = int2bn(s, bn_type=(c.c_uint32 * 18))
prime = int2bn(curve.p)
lib.bn_multiply_reduce(x, res, prime)
x = bn2int(x) % curve.p
x_ = s % curve.p
assert x == x_
def test_fast_mod(curve, r):
x = r.randrange(0, 128 * curve.p)
y = int2bn(x)
lib.bn_fast_mod(y, int2bn(curve.p))
y = bn2int(y)
assert y < 2 * curve.p
if y >= curve.p:
y -= curve.p
assert x % curve.p == y
def test_mod(curve, r):
x = r.randrange(0, 2 * curve.p)
y = int2bn(x)
lib.bn_mod(y, int2bn(curve.p))
assert bn2int(y) == x % curve.p
def test_mod_specific(curve):
p = curve.p
for x in [0, 1, 2, p - 2, p - 1, p, p + 1, p + 2, 2 * p - 2, 2 * p - 1]:
y = int2bn(x)
lib.bn_mod(y, int2bn(curve.p))
assert bn2int(y) == x % p
POINT = BIGNUM * 2
@ -340,6 +185,16 @@ def from_JACOBIAN(p):
return (bn2int(p[0]), bn2int(p[1]), bn2int(p[2]))
def test_curve_parameters(curve):
assert curve.curve.p() == bn2int(curve.ptr.contents.prime)
assert curve.generator.x() == bn2int(curve.ptr.contents.G.x)
assert curve.generator.y() == bn2int(curve.ptr.contents.G.y)
assert curve.order == bn2int(curve.ptr.contents.order)
assert curve.order // 2 == bn2int(curve.ptr.contents.order_half)
assert curve.curve.a() == curve.ptr.contents.a
assert curve.curve.b() == bn2int(curve.ptr.contents.b)
def test_point_multiply(curve, r):
p = r.randpoint(curve)
k = r.randrange(0, 2 ** 256)
@ -385,15 +240,6 @@ def test_point_to_jacobian(curve, r):
assert q == (p.x(), p.y())
def test_cond_negate(curve, r):
x = r.randrange(0, curve.p)
a = int2bn(x)
lib.conditional_negate(0, a, int2bn(curve.p))
assert bn2int(a) == x
lib.conditional_negate(-1, a, int2bn(curve.p))
assert bn2int(a) == 2 * curve.p - x
def test_jacobian_add(curve, r):
p1 = r.randpoint(curve)
p2 = r.randpoint(curve)

@ -39,7 +39,8 @@ int main(int argc, char **argv) {
curve_point checkresult;
bignum256 a;
bn_zero(&a);
a.val[(4 * i) / 30] = ((uint32_t)2 * j + 1) << ((4 * i) % 30);
a.val[(4 * i) / BN_BITS_PER_LIMB] = ((uint32_t)2 * j + 1)
<< ((4 * i) % BN_BITS_PER_LIMB);
bn_normalize(&a);
point_multiply(curve, &a, &curve->G, &checkresult);
assert(point_is_equal(&checkresult, &ng));

@ -68,7 +68,7 @@ static uint8_t hash_prevouts[32], hash_sequence[32], hash_outputs[32];
static uint8_t decred_hash_prefix[32];
#endif
static uint8_t hash_check[32];
static uint64_t to_spend, authorized_bip143_in, spending, change_spend;
static uint64_t to_spend, spending, change_spend;
static uint32_t version = 1;
static uint32_t lock_time = 0;
static uint32_t expiry = 0;
@ -489,6 +489,28 @@ void signing_init(const SignTx *msg, const CoinInfo *_coin,
memcpy(&root, _root, sizeof(HDNode));
version = msg->version;
lock_time = msg->lock_time;
if (coin->overwintered && !msg->has_version_group_id) {
fsm_sendFailure(FailureType_Failure_DataError,
_("Version group ID must be set."));
signing_abort();
return;
}
if (!coin->overwintered) {
if (msg->has_version_group_id) {
fsm_sendFailure(FailureType_Failure_DataError,
_("Version group ID not enabled on this coin."));
signing_abort();
return;
}
if (msg->has_branch_id) {
fsm_sendFailure(FailureType_Failure_DataError,
_("Branch ID not enabled on this coin."));
signing_abort();
return;
}
}
#if !BITCOIN_ONLY
expiry = (coin->decred || coin->overwintered) ? msg->expiry : 0;
timestamp = coin->timestamp ? msg->timestamp : 0;
@ -529,7 +551,6 @@ void signing_init(const SignTx *msg, const CoinInfo *_coin,
to_spend = 0;
spending = 0;
change_spend = 0;
authorized_bip143_in = 0;
memzero(&input, sizeof(TxInputType));
memzero(&resp, sizeof(TxRequest));
@ -653,17 +674,6 @@ static bool signing_validate_input(const TxInputType *txinput) {
return false;
}
#if !BITCOIN_ONLY
if (coin->force_bip143 || coin->overwintered) {
if (!txinput->has_amount) {
fsm_sendFailure(FailureType_Failure_DataError,
_("Expected input with amount"));
signing_abort();
return false;
}
}
#endif
if (is_segwit_input_script_type(txinput)) {
if (!coin->has_segwit) {
fsm_sendFailure(FailureType_Failure_DataError,
@ -671,12 +681,6 @@ static bool signing_validate_input(const TxInputType *txinput) {
signing_abort();
return false;
}
if (!txinput->has_amount) {
fsm_sendFailure(FailureType_Failure_DataError,
_("Segwit input without amount"));
signing_abort();
return false;
}
}
return true;
@ -1138,19 +1142,18 @@ static bool signing_sign_segwit_input(TxInputType *txinput) {
uint8_t hash[32] = {0};
if (is_segwit_input_script_type(txinput)) {
if (!compile_input_script_sig(txinput)) {
fsm_sendFailure(FailureType_Failure_ProcessError,
_("Failed to compile input"));
if (!txinput->has_amount) {
fsm_sendFailure(FailureType_Failure_DataError,
_("Segwit input without amount"));
signing_abort();
return false;
}
if (txinput->amount > authorized_bip143_in) {
fsm_sendFailure(FailureType_Failure_DataError,
_("Transaction has changed during signing"));
if (!compile_input_script_sig(txinput)) {
fsm_sendFailure(FailureType_Failure_ProcessError,
_("Failed to compile input"));
signing_abort();
return false;
}
authorized_bip143_in -= txinput->amount;
signing_hash_bip143(txinput, hash);
@ -1259,9 +1262,10 @@ void signing_txack(TransactionType *tx) {
}
#endif
memcpy(&input, tx->inputs, sizeof(TxInputType));
if (tx->inputs[0].script_type == InputScriptType_SPENDMULTISIG ||
tx->inputs[0].script_type == InputScriptType_SPENDADDRESS) {
memcpy(&input, tx->inputs, sizeof(TxInputType));
#if !ENABLE_SEGWIT_NONSEGWIT_MIXING
// don't mix segwit and non-segwit inputs
if (idx1 > 0 && to.is_segwit == true) {
@ -1273,30 +1277,12 @@ void signing_txack(TransactionType *tx) {
}
#endif
#if !BITCOIN_ONLY
if (coin->force_bip143 || coin->overwintered) {
if (to_spend + tx->inputs[0].amount < to_spend) {
fsm_sendFailure(FailureType_Failure_DataError, _("Value overflow"));
signing_abort();
return;
}
to_spend += tx->inputs[0].amount;
authorized_bip143_in += tx->inputs[0].amount;
phase1_request_next_input();
} else
#endif
{
if (!coin->force_bip143 && !coin->overwintered) {
// remember the first non-segwit input -- this is the first input
// we need to sign during phase2
if (next_nonsegwit_input == 0xffffffff) next_nonsegwit_input = idx1;
send_req_2_prev_meta();
}
} else if (is_segwit_input_script_type(&tx->inputs[0])) {
if (to_spend + tx->inputs[0].amount < to_spend) {
fsm_sendFailure(FailureType_Failure_DataError, _("Value overflow"));
signing_abort();
return;
}
if (!to.is_segwit) {
tx_weight += TXSIZE_SEGWIT_OVERHEAD + to.inputs_len;
}
@ -1314,15 +1300,13 @@ void signing_txack(TransactionType *tx) {
#else
to.is_segwit = true;
#endif
to_spend += tx->inputs[0].amount;
authorized_bip143_in += tx->inputs[0].amount;
phase1_request_next_input();
} else {
fsm_sendFailure(FailureType_Failure_DataError,
_("Wrong input script type"));
signing_abort();
return;
}
send_req_2_prev_meta();
return;
case STAGE_REQUEST_2_PREV_META:
if (tx->outputs_cnt <= input.prev_index) {
@ -1355,6 +1339,26 @@ void signing_txack(TransactionType *tx) {
signing_abort();
return;
}
if (coin->overwintered && !tx->has_version_group_id) {
fsm_sendFailure(FailureType_Failure_DataError,
_("Version group ID must be set."));
signing_abort();
return;
}
if (!coin->overwintered) {
if (tx->has_version_group_id) {
fsm_sendFailure(FailureType_Failure_DataError,
_("Version group ID not enabled on this coin."));
signing_abort();
return;
}
if (tx->has_branch_id) {
fsm_sendFailure(FailureType_Failure_DataError,
_("Branch ID not enabled on this coin."));
signing_abort();
return;
}
}
if (tx->inputs_cnt + tx->outputs_cnt < tx->inputs_cnt) {
fsm_sendFailure(FailureType_Failure_DataError, _("Value overflow"));
signing_abort();
@ -1412,6 +1416,12 @@ void signing_txack(TransactionType *tx) {
return;
}
if (idx2 == input.prev_index) {
if (input.has_amount && input.amount != tx->bin_outputs[0].amount) {
fsm_sendFailure(FailureType_Failure_DataError,
_("Invalid amount specified"));
signing_abort();
return;
}
if (to_spend + tx->bin_outputs[0].amount < to_spend) {
fsm_sendFailure(FailureType_Failure_DataError, _("Value overflow"));
signing_abort();
@ -1596,13 +1606,12 @@ void signing_txack(TransactionType *tx) {
signing_abort();
return;
}
if (tx->inputs[0].amount > authorized_bip143_in) {
if (!tx->inputs[0].has_amount) {
fsm_sendFailure(FailureType_Failure_DataError,
_("Transaction has changed during signing"));
_("Expected input with amount"));
signing_abort();
return;
}
authorized_bip143_in -= tx->inputs[0].amount;
uint8_t hash[32] = {0};
#if !BITCOIN_ONLY

@ -711,8 +711,7 @@ uint32_t tx_serialize_footer_hash(TxStruct *tx) {
#if !BITCOIN_ONLY
if (tx->overwintered) {
hasher_Update(&(tx->hasher), (const uint8_t *)&(tx->expiry), 4);
hasher_Update(&(tx->hasher), (const uint8_t *)"\x00", 1); // nJoinSplit
return 9;
return 8;
}
if (tx->is_decred) {
hasher_Update(&(tx->hasher), (const uint8_t *)&(tx->expiry), 4);

@ -1022,7 +1022,13 @@ class TestMsgSigntx:
@pytest.mark.parametrize(
"field, value",
(("extra_data", b"hello world"), ("expiry", 9), ("timestamp", 42)),
(
("extra_data", b"hello world"),
("expiry", 9),
("timestamp", 42),
("version_group_id", 69),
("branch_id", 13),
),
)
@pytest.mark.skip_ui
def test_prevtx_forbidden_fields(self, client, field, value):
@ -1045,7 +1051,10 @@ class TestMsgSigntx:
client, "Bitcoin", [inp0], [out1], prev_txes={TXHASH_157041: prev_tx}
)
@pytest.mark.parametrize("field, value", (("expiry", 9), ("timestamp", 42)))
@pytest.mark.parametrize(
"field, value",
(("expiry", 9), ("timestamp", 42), ("version_group_id", 69), ("branch_id", 13)),
)
@pytest.mark.skip_ui
def test_signtx_forbidden_fields(self, client, field, value):
inp0 = proto.TxInputType(
@ -1167,5 +1176,5 @@ class TestMsgSigntx:
TrezorFailure, match="Multisig field provided but not expected."
):
btc.sign_tx(
client, "Testnet", [inp1], [out1, out2], prev_txes=TxCache("Testnet")
client, "Testnet", [inp1], [out1, out2], prev_txes=TX_CACHE_TESTNET
)

@ -21,7 +21,7 @@ from trezorlib.exceptions import TrezorFailure
from trezorlib.tools import H_, parse_path
from ..tx_cache import TxCache
from .signtx import request_finished, request_input, request_output
from .signtx import request_finished, request_input, request_meta, request_output
B = proto.ButtonRequestType
TX_API = TxCache("Bcash")
@ -65,6 +65,9 @@ class TestMsgSigntxBch:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_bc37c2),
request_input(0, TXHASH_bc37c2),
request_output(0, TXHASH_bc37c2),
request_output(0),
request_output(1),
proto.ButtonRequest(code=B.ConfirmOutput),
@ -110,7 +113,15 @@ class TestMsgSigntxBch:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_502e85),
request_input(0, TXHASH_502e85),
request_output(0, TXHASH_502e85),
request_output(1, TXHASH_502e85),
request_input(1),
request_meta(TXHASH_502e85),
request_input(0, TXHASH_502e85),
request_output(0, TXHASH_502e85),
request_output(1, TXHASH_502e85),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
proto.ButtonRequest(code=B.SignTx),
@ -155,7 +166,15 @@ class TestMsgSigntxBch:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_502e85),
request_input(0, TXHASH_502e85),
request_output(0, TXHASH_502e85),
request_output(1, TXHASH_502e85),
request_input(1),
request_meta(TXHASH_502e85),
request_input(0, TXHASH_502e85),
request_output(0, TXHASH_502e85),
request_output(1, TXHASH_502e85),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
proto.ButtonRequest(code=B.SignTx),
@ -174,81 +193,6 @@ class TestMsgSigntxBch:
== "01000000022c06cf6f215c5cbfd7caa8e71b1b32630cabf1f816a4432815b037b277852e50000000006a47304402207a2a955f1cb3dc5f03f2c82934f55654882af4e852e5159639f6349e9386ec4002205fb8419dce4e648eae8f67bc4e369adfb130a87d2ea2d668f8144213b12bb457412103174c61e9c5362507e8061e28d2c0ce3d4df4e73f3535ae0b12f37809e0f92d2dffffffff2c06cf6f215c5cbfd7caa8e71b1b32630cabf1f816a4432815b037b277852e50010000006a473044022062151cf960b71823bbe68c7ed2c2a93ad1b9706a30255fddb02fcbe056d8c26102207bad1f0872bc5f0cfaf22e45c925c35d6c1466e303163b75cb7688038f1a5541412102595caf9aeb6ffdd0e82b150739a83297358b9a77564de382671056ad9e5b8c58ffffffff0170861d00000000001976a91434e9cec317896e818619ab7dc99d2305216ff4af88ac00000000"
)
def test_attack_amount(self, client):
inp1 = proto.TxInputType(
address_n=parse_path("44'/145'/0'/1/0"),
# bitcoincash:qzc5q87w069lzg7g3gzx0c8dz83mn7l02scej5aluw
amount=300,
prev_hash=TXHASH_502e85,
prev_index=0,
script_type=proto.InputScriptType.SPENDADDRESS,
)
inp2 = proto.TxInputType(
address_n=parse_path("44'/145'/0'/0/1"),
# bitcoincash:qr23ajjfd9wd73l87j642puf8cad20lfmqdgwvpat4
amount=70,
prev_hash=TXHASH_502e85,
prev_index=1,
script_type=proto.InputScriptType.SPENDADDRESS,
)
out1 = proto.TxOutputType(
address="bitcoincash:qq6wnnkrz7ykaqvxrx4hmjvayvzjzml54uyk76arx4",
amount=200,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
# test if passes without modifications
with client:
client.set_expected_responses(
[
request_input(0),
request_input(1),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
proto.ButtonRequest(code=B.SignTx),
request_input(0),
request_input(1),
request_output(0),
request_finished(),
]
)
btc.sign_tx(client, "Bcash", [inp1, inp2], [out1], prev_txes=TX_API)
run_attack = True
def attack_processor(msg):
nonlocal run_attack
if run_attack and msg.tx.inputs and msg.tx.inputs[0] == inp1:
# 300 is lowered to 280 at the first run
# the user confirms 280 but the transaction
# is spending 300 => larger fee without the user knowing
msg.tx.inputs[0].amount = 280
run_attack = False
return msg
# now fails
client.set_filter(proto.TxAck, attack_processor)
with client:
client.set_expected_responses(
[
request_input(0),
request_input(1),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
proto.ButtonRequest(code=B.SignTx),
request_input(0),
request_input(1),
proto.Failure(),
]
)
with pytest.raises(
TrezorFailure, match="Transaction has changed during signing"
):
btc.sign_tx(client, "Bcash", [inp1, inp2], [out1], prev_txes=TX_API)
def test_attack_change_input(self, client):
inp1 = proto.TxInputType(
address_n=parse_path("44'/145'/10'/0/0"),
@ -287,6 +231,9 @@ class TestMsgSigntxBch:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_bc37c2),
request_input(0, TXHASH_bc37c2),
request_output(0, TXHASH_bc37c2),
request_output(0),
request_output(1),
proto.ButtonRequest(code=B.ConfirmOutput),
@ -353,6 +300,10 @@ class TestMsgSigntxBch:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_f68caf),
request_input(0, TXHASH_f68caf),
request_output(0, TXHASH_f68caf),
request_output(1, TXHASH_f68caf),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
proto.ButtonRequest(code=B.SignTx),
@ -410,6 +361,9 @@ class TestMsgSigntxBch:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_8b6db9),
request_input(0, TXHASH_8b6db9),
request_output(0, TXHASH_8b6db9),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
request_output(1),
@ -444,6 +398,9 @@ class TestMsgSigntxBch:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_8b6db9),
request_input(0, TXHASH_8b6db9),
request_output(0, TXHASH_8b6db9),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
request_output(1),

@ -18,10 +18,10 @@ import pytest
from trezorlib import btc, messages as proto
from trezorlib.exceptions import TrezorFailure
from trezorlib.tools import H_, parse_path
from trezorlib.tools import H_, btc_hash, parse_path
from ..tx_cache import TxCache
from .signtx import request_finished, request_input, request_output
from .signtx import request_finished, request_input, request_meta, request_output
B = proto.ButtonRequestType
TX_API = TxCache("Bgold")
@ -32,12 +32,6 @@ TXHASH_25526b = bytes.fromhex(
TXHASH_db77c2 = bytes.fromhex(
"db77c2461b840e6edbe7f9280043184a98e020d9795c1b65cb7cef2551a8fb18"
)
TXHASH_e5040e = bytes.fromhex(
"e5040e1bc1ae7667ffb9e5248e90b2fb93cd9150234151ce90e14ab2f5933bcd"
)
TXHASH_65b811 = bytes.fromhex(
"65b811d3eca0fe6915d9f2d77c86c5a7f19bf66b1b1253c2c51cb4ae5f0c017b"
)
# All data taken from T1
@ -46,7 +40,7 @@ class TestMsgSigntxBitcoinGold:
def test_send_bitcoin_gold_change(self, client):
inp1 = proto.TxInputType(
address_n=parse_path("44'/156'/0'/0/0"),
amount=1995344,
amount=1252382934,
prev_hash=TXHASH_25526b,
prev_index=0,
script_type=proto.InputScriptType.SPENDADDRESS,
@ -58,13 +52,17 @@ class TestMsgSigntxBitcoinGold:
)
out2 = proto.TxOutputType(
address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe",
amount=73452,
amount=1252382934 - 1896050 - 1000,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
with client:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_25526b),
request_input(0, TXHASH_25526b),
request_output(0, TXHASH_25526b),
request_output(1, TXHASH_25526b),
request_output(0),
request_output(1),
proto.ButtonRequest(code=B.ConfirmOutput),
@ -80,14 +78,14 @@ class TestMsgSigntxBitcoinGold:
)
assert (
serialized_tx.hex()
== "010000000185c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b5225000000006b483045022100963904da0731b71ce468afd45366dd80fbff566ec0d39c1161ab85d17459c7ca02202f5c24a7a7272d98b14a3f5bc000c7cde8ac0eb773f20f4c3131518186cc98854121023bd0ec4022d12d0106c5b7308a25572953ba1951f576f691354a7b147ee0cc1fffffffff0272ee1c00000000001976a9141c82b9c11f193ad82413caadc0955730572b50ae88acec1e0100000000001976a914ea5f904d195079a350b534db4446433b3cec222e88ac00000000"
btc_hash(serialized_tx)[::-1].hex()
== "39a0716c361610724c7c40916baa20808cbdd7538b6c38689ce80cb73e7f51d1"
)
def test_send_bitcoin_gold_nochange(self, client):
inp1 = proto.TxInputType(
address_n=parse_path("44'/156'/0'/1/0"),
amount=1896050,
amount=1252382934,
prev_hash=TXHASH_25526b,
prev_index=0,
script_type=proto.InputScriptType.SPENDADDRESS,
@ -95,21 +93,29 @@ class TestMsgSigntxBitcoinGold:
inp2 = proto.TxInputType(
address_n=parse_path("44'/156'/0'/0/1"),
# 1LRspCZNFJcbuNKQkXgHMDucctFRQya5a3
amount=73452,
amount=38448607,
prev_hash=TXHASH_db77c2,
prev_index=1,
prev_index=0,
script_type=proto.InputScriptType.SPENDADDRESS,
)
out1 = proto.TxOutputType(
address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe",
amount=1934960,
amount=1252382934 + 38448607 - 1000,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
with client:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_25526b),
request_input(0, TXHASH_25526b),
request_output(0, TXHASH_25526b),
request_output(1, TXHASH_25526b),
request_input(1),
request_meta(TXHASH_db77c2),
request_input(0, TXHASH_db77c2),
request_input(1, TXHASH_db77c2),
request_output(0, TXHASH_db77c2),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
proto.ButtonRequest(code=B.SignTx),
@ -124,14 +130,14 @@ class TestMsgSigntxBitcoinGold:
)
assert (
serialized_tx.hex()
== "010000000285c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b5225000000006b483045022100928852076c9fab160c07564cd54691af1cbc37fb28f0b7bee7299c7925ef62f0022058856387afecc6508f2f04ecdfd292a13026a5b2107ebdd2cc789bdf8820d552412102a6c3998d0d4e5197ff41aab5c53580253b3b91f583f4c31f7624be7dc83ce15fffffffff18fba85125ef7ccb651b5c79d920e0984a18430028f9e7db6e0e841b46c277db010000006b483045022100faa2f4f01cc95e680349a093923aae0aa2ea01429873555aa8a84bf630ef33a002204c3f4bf567e2d20540c0f71dc278481d6ccb6b95acda2a2f87ce521c79d6b872412102d54a7e5733b1635e5e9442943f48179b1700206b2d1925250ba10f1c86878be8ffffffff0170861d00000000001976a914ea5f904d195079a350b534db4446433b3cec222e88ac00000000"
btc_hash(serialized_tx)[::-1].hex()
== "ac9d452b900eb747d3137e1f3044bb0f46efaeb6e0fc8c27b02d1d08d238a904"
)
def test_attack_change_input(self, client):
inp1 = proto.TxInputType(
address_n=parse_path("44'/156'/11'/0/0"),
amount=1995344,
amount=1252382934,
prev_hash=TXHASH_25526b,
prev_index=0,
script_type=proto.InputScriptType.SPENDADDRESS,
@ -143,7 +149,7 @@ class TestMsgSigntxBitcoinGold:
)
out2 = proto.TxOutputType(
address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe",
amount=73452,
amount=1252382934 - 1896050 - 1000,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
@ -165,6 +171,10 @@ class TestMsgSigntxBitcoinGold:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_25526b),
request_input(0, TXHASH_25526b),
request_output(0, TXHASH_25526b),
request_output(1, TXHASH_25526b),
request_output(0),
request_output(1),
proto.ButtonRequest(code=B.ConfirmOutput),
@ -194,7 +204,7 @@ class TestMsgSigntxBitcoinGold:
address_n=parse_path("48'/156'/3'/0/0"),
multisig=getmultisig(0, 0),
# 33Ju286QvonBz5N1V754ZekQv4GLJqcc5R
amount=48490,
amount=1252382934,
prev_hash=TXHASH_25526b,
prev_index=0,
script_type=proto.InputScriptType.SPENDMULTISIG,
@ -208,12 +218,16 @@ class TestMsgSigntxBitcoinGold:
address_n=parse_path("48'/156'/3'/1/0"),
multisig=getmultisig(1, 0),
script_type=proto.OutputScriptType.PAYTOMULTISIG,
amount=24000,
amount=1252382934 - 24000 - 1000,
)
with client:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_25526b),
request_input(0, TXHASH_25526b),
request_output(0, TXHASH_25526b),
request_output(1, TXHASH_25526b),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
request_output(1),
@ -230,13 +244,13 @@ class TestMsgSigntxBitcoinGold:
assert (
signatures[0].hex()
== "3045022100d954f341ddd3ec96e4bc6cdb90f2df9b2032723f85e4a0187346dd743130bfca0220105ce08b795c70dc09a55569d7874bff684a877219ec2fc37c88cdffe12f332c"
== "30440220271c46ef3d7c37bd499804128623da3aa0014f3b4447dd39c4573b23c4537f6902205329167b9eb48427af62b04bf5138295f4c38613f6ba955934d15c499bff0d8a"
)
inp1 = proto.TxInputType(
address_n=parse_path("48'/156'/1'/0/0"),
multisig=getmultisig(0, 0, [b"", b"", signatures[0]]),
amount=48490,
amount=1252382934,
prev_hash=TXHASH_25526b,
prev_index=0,
script_type=proto.InputScriptType.SPENDMULTISIG,
@ -247,6 +261,10 @@ class TestMsgSigntxBitcoinGold:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_25526b),
request_input(0, TXHASH_25526b),
request_output(0, TXHASH_25526b),
request_output(1, TXHASH_25526b),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
request_output(1),
@ -263,17 +281,17 @@ class TestMsgSigntxBitcoinGold:
assert (
signatures[0].hex()
== "30440220614f9a18695365a2edba0d930404a77cae970d3430ad86c5b5239a96fd54bf84022030bc76a322e3b2b1c987622b5eb6da23ac1e6c905ee9b3b6405a4e4edd5bbb87"
== "3045022100bdf8c4bd14217c183612c7e8f79691f6479bcb35aa403f77d70182f58633ac6e02205b10a79b7894bb40248a120c8fcb7096a46950593e4c5b48a20bc5ebe53d85fa"
)
assert (
serialized_tx.hex()
== "010000000185c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b522500000000fdfd00004730440220614f9a18695365a2edba0d930404a77cae970d3430ad86c5b5239a96fd54bf84022030bc76a322e3b2b1c987622b5eb6da23ac1e6c905ee9b3b6405a4e4edd5bbb8741483045022100d954f341ddd3ec96e4bc6cdb90f2df9b2032723f85e4a0187346dd743130bfca0220105ce08b795c70dc09a55569d7874bff684a877219ec2fc37c88cdffe12f332c414c695221035a8db79c0ef57a202664a3da60ca41e8865c6d86ed0aafc03f8e75173341b58021037fba152d8fca660cc49973d8bc9421ff49a75b44ea200873d70d3990f763ed4c210348cbcbd93e069416e0d5db93e86b5698852d9fd54502ad0bed9722fa83f90e4b53aeffffffff02c05d0000000000001976a914ea5f904d195079a350b534db4446433b3cec222e88acc05d00000000000017a914623c803f7fb654dac8dda7786fbf9bc38cd867f48700000000"
btc_hash(serialized_tx)[::-1].hex()
== "b45ba21b69e1e1c6ad79f5408fe70d92fb861742d239cb6a952213f60c253e40"
)
def test_send_p2sh(self, client):
inp1 = proto.TxInputType(
address_n=parse_path("49'/156'/0'/1/0"),
amount=123456789,
amount=1252382934,
prev_hash=TXHASH_25526b,
prev_index=0,
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
@ -286,12 +304,16 @@ class TestMsgSigntxBitcoinGold:
out2 = proto.TxOutputType(
address="GZFLExxrvWFuFT1xRzhfwQWSE2bPDedBfn",
script_type=proto.OutputScriptType.PAYTOADDRESS,
amount=123456789 - 11000 - 12300000,
amount=1252382934 - 11000 - 12300000,
)
with client:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_25526b),
request_input(0, TXHASH_25526b),
request_output(0, TXHASH_25526b),
request_output(1, TXHASH_25526b),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
request_output(1),
@ -309,14 +331,14 @@ class TestMsgSigntxBitcoinGold:
)
assert (
serialized_tx.hex()
== "0100000000010185c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b52250000000017160014b5355d001e720d8f4513da00ff2bba4dcf9d39fcffffffff02e0aebb00000000001976a914ea5f904d195079a350b534db4446433b3cec222e88ac3df39f06000000001976a914a8f757819ec6779409f45788f7b4a0e8f51ec50488ac02473044022073fcbf2876f073f78923ab427f14de5b2a0fbeb313a9b2b650b3567061f242a702202f45fc22c501108ff6222afe3aca7da9d8c7dc860f9cda335bef31fa184e7bef412102ecea08b559fc5abd009acf77cfae13fa8a3b1933e3e031956c65c12cec8ca3e300000000"
btc_hash(serialized_tx)[::-1].hex()
== "d5732fc8a594ae3b7ba695d7b276b2186f8572b0eb157120e0ba35d3511c6060"
)
def test_send_p2sh_witness_change(self, client):
inp1 = proto.TxInputType(
address_n=parse_path("49'/156'/0'/1/0"),
amount=123456789,
amount=1252382934,
prev_hash=TXHASH_25526b,
prev_index=0,
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
@ -329,12 +351,16 @@ class TestMsgSigntxBitcoinGold:
out2 = proto.TxOutputType(
address_n=parse_path("49'/156'/0'/1/0"),
script_type=proto.OutputScriptType.PAYTOP2SHWITNESS,
amount=123456789 - 11000 - 12300000,
amount=1252382934 - 11000 - 12300000,
)
with client:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_25526b),
request_input(0, TXHASH_25526b),
request_output(0, TXHASH_25526b),
request_output(1, TXHASH_25526b),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
request_output(1),
@ -351,8 +377,8 @@ class TestMsgSigntxBitcoinGold:
)
assert (
serialized_tx.hex()
== "0100000000010185c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b52250000000017160014b5355d001e720d8f4513da00ff2bba4dcf9d39fcffffffff02e0aebb00000000001976a914ea5f904d195079a350b534db4446433b3cec222e88ac3df39f060000000017a9140cd03822b799a452c106d1b3771844a067b17f118702483045022100d79b33384c686d8dd40ad5f84f46691d30994992c1cb42e934c2a625d86cb2f902206859805a9a98ba140b71a9d4b9a6b8df94a9424f9c40f3bd804149fd6e278d63412102ecea08b559fc5abd009acf77cfae13fa8a3b1933e3e031956c65c12cec8ca3e300000000"
btc_hash(serialized_tx)[::-1].hex()
== "eed4ef86a408602e35ae416591f349847db38cdaddef1429a9bb0e39520d100d"
)
@pytest.mark.multisig
@ -370,15 +396,15 @@ class TestMsgSigntxBitcoinGold:
inp1 = proto.TxInputType(
address_n=parse_path("49'/156'/1'/1/0"),
prev_hash=TXHASH_25526b,
prev_index=1,
prev_index=0,
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
multisig=multisig,
amount=1610436,
amount=1252382934,
)
out1 = proto.TxOutputType(
address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe",
amount=1605000,
amount=1252382934 - 1000,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
@ -386,6 +412,10 @@ class TestMsgSigntxBitcoinGold:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_25526b),
request_input(0, TXHASH_25526b),
request_output(0, TXHASH_25526b),
request_output(1, TXHASH_25526b),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
proto.ButtonRequest(code=B.SignTx),
@ -405,6 +435,10 @@ class TestMsgSigntxBitcoinGold:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_25526b),
request_input(0, TXHASH_25526b),
request_output(0, TXHASH_25526b),
request_output(1, TXHASH_25526b),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
proto.ButtonRequest(code=B.SignTx),
@ -419,30 +453,30 @@ class TestMsgSigntxBitcoinGold:
)
assert (
serialized_tx.hex()
== "0100000000010185c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b52250100000023220020ea9ec48498c451286c2ebaf9e19255e2873b0fb517d67b2f2005298c7e437829ffffffff01887d1800000000001976a914ea5f904d195079a350b534db4446433b3cec222e88ac0400473044022077cb8b2a534f79328810ca8c330539ae9ffa086c359ddb7da11026557b04eef202201d95be0dd1da0aa01720953e52d5dabffd19a998d1490c13a21b8e52e4ead2e041483045022100e41cbd6a501ba8fe6f65554420e23e950d35af0da9b052da54a087463b0717ca02206c695c8d1f74f9535b5d89a2fd1f9326a0ef20e5400137f1e1daeee992b62b594169522103279aea0b253b144d1b2bb8532280001a996dcddd04f86e5e13df1355032cbc1321032c6465c956c0879663fa8be974c912d229c179a5cdedeb29611a1bec1f951eb22103494480a4b72101cbd2eadac8e18c7a3a7589a7f576bf46b8971c38c51e5eceeb53ae00000000"
btc_hash(serialized_tx)[::-1].hex()
== "efa5b21916ac7ea5316c38b2d7d5520d80cbe563c58304f956ea6ddb241001d1"
)
def test_send_mixed_inputs(self, client):
# First is non-segwit, second is segwit.
inp1 = proto.TxInputType(
address_n=parse_path("44'/156'/0'/0/0"),
amount=31000000,
prev_hash=TXHASH_e5040e,
address_n=parse_path("44'/156'/11'/0/0"),
amount=38448607,
prev_hash=TXHASH_db77c2,
prev_index=0,
script_type=proto.InputScriptType.SPENDADDRESS,
)
inp2 = proto.TxInputType(
address_n=parse_path("84'/156'/0'/1/0"),
amount=7289000,
prev_hash=TXHASH_65b811,
prev_index=1,
script_type=proto.InputScriptType.SPENDWITNESS,
address_n=parse_path("49'/156'/0'/1/0"),
amount=1252382934,
prev_hash=TXHASH_25526b,
prev_index=0,
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
)
out1 = proto.TxOutputType(
address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe",
amount=31000000 + 7289000 - 1000,
amount=38448607 + 1252382934 - 1000,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
@ -452,6 +486,6 @@ class TestMsgSigntxBitcoinGold:
)
assert (
serialized_tx.hex()
== "01000000000102cd3b93f5b24ae190ce5141235091cd93fbb2908e24e5b9ff6776aec11b0e04e5000000006a473044022061e94392fa4c0a4bf510bf713c23a37c6c5f6f4dbe5c116e86cff23a93c578e9022026661d2ffb1102d07b7c1631270152441fa171d91108b75a7b9a2cc36ca7db6c4121023bd0ec4022d12d0106c5b7308a25572953ba1951f576f691354a7b147ee0cc1fffffffff7b010c5faeb41cc5c253121b6bf69bf1a7c5867cd7f2d91569fea0ecd311b8650100000000ffffffff01803a4802000000001976a914ea5f904d195079a350b534db4446433b3cec222e88ac0002483045022100e39d9bff8350b9ba20cb2ed88e82d7568a83184616acdc16bd1adb4005c5a471022066ff36084e896a69a91a0fad01721f20f2bb42b41e20be35e72fc3729ac7ace74121030b75ccac9add5f82a4c61fe34e791a2f2eda61b544bce4f6fa3d403bb0de748400000000"
btc_hash(serialized_tx)[::-1].hex()
== "2c64109fba890657e37f0782efda29bbc277dfd521658f185d302ddffcacffd2"
)

@ -23,6 +23,7 @@ from ..tx_cache import TxCache
B = proto.ButtonRequestType
TX_API = TxCache("Groestlcoin")
TX_API_TESTNET = TxCache("Groestlcoin Testnet")
TXHASH_cb74c8 = bytes.fromhex(
"cb74c8478c5814742c87cffdb4a21231869888f8042fb07a90e015a9db1f9d4a"
@ -101,7 +102,12 @@ class TestMsgSigntxGRS:
)
details = proto.SignTx(lock_time=650756)
_, serialized_tx = btc.sign_tx(
client, "Groestlcoin Testnet", [inp1], [out1, out2], details=details
client,
"Groestlcoin Testnet",
[inp1],
[out1, out2],
details=details,
prev_txes=TX_API_TESTNET,
)
assert (
serialized_tx.hex()
@ -130,7 +136,12 @@ class TestMsgSigntxGRS:
)
details = proto.SignTx(lock_time=650756)
_, serialized_tx = btc.sign_tx(
client, "Groestlcoin Testnet", [inp1], [out1, out2], details=details
client,
"Groestlcoin Testnet",
[inp1],
[out1, out2],
details=details,
prev_txes=TX_API_TESTNET,
)
assert (
serialized_tx.hex()
@ -158,7 +169,12 @@ class TestMsgSigntxGRS:
)
details = proto.SignTx(lock_time=650713)
_, serialized_tx = btc.sign_tx(
client, "Groestlcoin Testnet", [inp1], [out1, out2], details=details
client,
"Groestlcoin Testnet",
[inp1],
[out1, out2],
details=details,
prev_txes=TX_API_TESTNET,
)
assert (
serialized_tx.hex()
@ -186,7 +202,12 @@ class TestMsgSigntxGRS:
)
details = proto.SignTx(lock_time=650713)
_, serialized_tx = btc.sign_tx(
client, "Groestlcoin Testnet", [inp1], [out1, out2], details=details
client,
"Groestlcoin Testnet",
[inp1],
[out1, out2],
details=details,
prev_txes=TX_API_TESTNET,
)
assert (
serialized_tx.hex()

@ -20,7 +20,13 @@ from trezorlib import btc, messages as proto
from trezorlib.tools import parse_path
from ..tx_cache import TxCache
from .signtx import request_finished, request_input, request_output
from .signtx import (
request_extra_data,
request_finished,
request_input,
request_meta,
request_output,
)
B = proto.ButtonRequestType
TX_API = TxCache("Komodo")
@ -54,22 +60,24 @@ class TestMsgSigntxKomodo:
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
trezor_core = client.features.model != "1"
with client:
er = [
request_input(0),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
]
if client.features.model != "1": # extra screen for lock_time
er += [proto.ButtonRequest(code=B.SignTx)]
er += [
proto.ButtonRequest(code=B.SignTx),
request_input(0),
request_output(0),
request_finished(),
]
client.set_expected_responses(er)
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_2807c),
request_input(0, TXHASH_2807c),
request_output(0, TXHASH_2807c),
request_extra_data(0, 11, TXHASH_2807c),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
(trezor_core, proto.ButtonRequest(code=B.SignTx)),
proto.ButtonRequest(code=B.SignTx),
request_input(0),
request_output(0),
request_finished(),
]
)
details = proto.SignTx(
version=4,
@ -112,24 +120,27 @@ class TestMsgSigntxKomodo:
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
trezor_core = client.features.model != "1"
with client:
er = [
request_input(0),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
request_output(1),
proto.ButtonRequest(code=B.ConfirmOutput),
]
if client.features.model != "1": # extra screen for lock_time
er += [proto.ButtonRequest(code=B.SignTx)]
er += [
proto.ButtonRequest(code=B.SignTx),
request_input(0),
request_output(0),
request_output(1),
request_finished(),
]
client.set_expected_responses(er)
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_7b28bd),
request_input(0, TXHASH_7b28bd),
request_output(0, TXHASH_7b28bd),
request_extra_data(0, 11, TXHASH_7b28bd),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
request_output(1),
proto.ButtonRequest(code=B.ConfirmOutput),
(trezor_core, proto.ButtonRequest(code=B.SignTx)),
proto.ButtonRequest(code=B.SignTx),
request_input(0),
request_output(0),
request_output(1),
request_finished(),
]
)
details = proto.SignTx(
version=4,

@ -142,7 +142,7 @@ def test_segwit_non_segwit_segwit_inputs(client):
)
inp3 = messages.TxInputType(
address_n=parse_path("84'/1'/0'/0/0"),
amount=123123,
amount=1603000,
prev_hash=TXHASH_31bc1c,
prev_index=0,
script_type=messages.InputScriptType.SPENDWITNESS,
@ -169,11 +169,11 @@ def test_segwit_non_segwit_segwit_inputs(client):
)
assert (
signatures[2].hex()
== "30450221008aa7c6ea2b017701145c8b062e05c35259d271ea3009229776b9ef6e17a823da022004a11059927dcc21ff3f0e9441e36e91b4e0db879d102ea6a26f84a8a5d6d35c"
== "3045022100f2d398ac6bc702cfa4f7eb3d2579a233f1d7c920c45a14329a741db6c24fde8f02203b1f6aed5671eece8ba5b5c05ec0330a43c0914b8ff606945cb8cf9e164ec88f"
)
assert (
serialized_tx.hex()
== "010000000001037b010c5faeb41cc5c253121b6bf69bf1a7c5867cd7f2d91569fea0ecd311b8650100000000ffffffffcd3b93f5b24ae190ce5141235091cd93fbb2908e24e5b9ff6776aec11b0e04e5000000006a4730440220566602a3794e29a5082feb2efd9ce0299455d0c4a31f76d4abafdcc0fed1cde502200ae36cb0563cf4792fd8a10026ec7c94028ca61a5b6903108af3343278ad29bb0121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0ffffffffe5918f661488bb7f0a7d04fc1dad61b5d0bad5167a05b3a637e36ace881cbc310000000000ffffffff01803a480200000000160014a579388225827d9f2fe9014add644487808c695d02473044022001187697b2ae95206eb18751701b6a3efd4c2da89cc9d8f0365e8ede7582c8ff0220282a2c127da57e82aecf0f421f7b8d5781205232b3429dd25d2b85aa1e48b741012103505647c017ff2156eb6da20fae72173d3b681a1d0a629f95f49e884db300689f00024830450221008aa7c6ea2b017701145c8b062e05c35259d271ea3009229776b9ef6e17a823da022004a11059927dcc21ff3f0e9441e36e91b4e0db879d102ea6a26f84a8a5d6d35c012103adc58245cf28406af0ef5cc24b8afba7f1be6c72f279b642d85c48798685f86200000000"
== "010000000001037b010c5faeb41cc5c253121b6bf69bf1a7c5867cd7f2d91569fea0ecd311b8650100000000ffffffffcd3b93f5b24ae190ce5141235091cd93fbb2908e24e5b9ff6776aec11b0e04e5000000006a4730440220566602a3794e29a5082feb2efd9ce0299455d0c4a31f76d4abafdcc0fed1cde502200ae36cb0563cf4792fd8a10026ec7c94028ca61a5b6903108af3343278ad29bb0121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0ffffffffe5918f661488bb7f0a7d04fc1dad61b5d0bad5167a05b3a637e36ace881cbc310000000000ffffffff01803a480200000000160014a579388225827d9f2fe9014add644487808c695d02473044022001187697b2ae95206eb18751701b6a3efd4c2da89cc9d8f0365e8ede7582c8ff0220282a2c127da57e82aecf0f421f7b8d5781205232b3429dd25d2b85aa1e48b741012103505647c017ff2156eb6da20fae72173d3b681a1d0a629f95f49e884db300689f0002483045022100f2d398ac6bc702cfa4f7eb3d2579a233f1d7c920c45a14329a741db6c24fde8f02203b1f6aed5671eece8ba5b5c05ec0330a43c0914b8ff606945cb8cf9e164ec88f012103adc58245cf28406af0ef5cc24b8afba7f1be6c72f279b642d85c48798685f86200000000"
)
@ -195,10 +195,7 @@ def test_non_segwit_segwit_non_segwit_inputs(client):
script_type=messages.InputScriptType.SPENDWITNESS,
)
inp3 = messages.TxInputType(
address_n=parse_path("44'/1'/1'/0/0"),
amount=1,
prev_hash=TXHASH_2bac7a,
prev_index=0,
address_n=parse_path("44'/1'/1'/0/0"), prev_hash=TXHASH_2bac7a, prev_index=0,
)
out1 = messages.TxOutputType(
address="tb1q54un3q39sf7e7tlfq99d6ezys7qgc62a6rxllc",

@ -100,13 +100,13 @@ def test_invalid_prev_hash_attack(client, prev_hash):
# prepare input with a valid prev-hash
inp1 = messages.TxInputType(
address_n=tools.parse_path("m/44h/0h/0h/0/0"),
amount=123456789,
prev_hash=b"\x00" * 32,
amount=100000000,
prev_hash=TXHASH_157041,
prev_index=0,
script_type=messages.InputScriptType.SPENDP2SHWITNESS,
)
out1 = messages.TxOutputType(
address="mhRx1CeVfaayqRwq5zgRQmD7W5aWBfD5mC",
address="1MJ2tj2ThBE62zXbBYA5ZaN3fdve5CPAz1",
amount=12300000,
script_type=messages.OutputScriptType.PAYTOADDRESS,
)
@ -130,7 +130,7 @@ def test_invalid_prev_hash_attack(client, prev_hash):
with client, pytest.raises(TrezorFailure) as e:
client.set_filter(messages.TxAck, attack_filter)
btc.sign_tx(client, "Testnet", [inp1], [out1])
btc.sign_tx(client, "Bitcoin", [inp1], [out1], prev_txes=TxCache("Bitcoin"))
# check that injection was performed
assert counter == 0

@ -21,7 +21,7 @@ from trezorlib.exceptions import TrezorFailure
from trezorlib.tools import H_, parse_path
from ..tx_cache import TxCache
from .signtx import request_finished, request_input, request_output
from .signtx import request_finished, request_input, request_meta, request_output
B = proto.ButtonRequestType
TX_API = TxCache("Testnet")
@ -32,6 +32,12 @@ TXHASH_20912f = bytes.fromhex(
TXHASH_9c3192 = bytes.fromhex(
"9c31922be756c06d02167656465c8dc83bb553bf386a3f478ae65b5c021002be"
)
TXHASH_dee13c = bytes.fromhex(
"dee13c469e7ab28108a1ce470d74cb40896d9bb459951bdf590ca6a495293a02"
)
TXHASH_e5040e = bytes.fromhex(
"e5040e1bc1ae7667ffb9e5248e90b2fb93cd9150234151ce90e14ab2f5933bcd"
)
class TestMsgSigntxSegwit:
@ -58,6 +64,10 @@ class TestMsgSigntxSegwit:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_20912f),
request_input(0, TXHASH_20912f),
request_output(0, TXHASH_20912f),
request_output(1, TXHASH_20912f),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
request_output(1),
@ -102,6 +112,10 @@ class TestMsgSigntxSegwit:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_20912f),
request_input(0, TXHASH_20912f),
request_output(0, TXHASH_20912f),
request_output(1, TXHASH_20912f),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
request_output(1),
@ -128,7 +142,7 @@ class TestMsgSigntxSegwit:
inp1 = proto.TxInputType(
address_n=parse_path("m/49'/1'/0'/0/0"),
amount=2 ** 32 + 1,
prev_hash=b"\xff" * 32,
prev_hash=TXHASH_dee13c,
prev_index=0,
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
)
@ -141,6 +155,8 @@ class TestMsgSigntxSegwit:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_dee13c),
request_output(0, TXHASH_dee13c),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
proto.ButtonRequest(code=B.SignTx),
@ -150,10 +166,12 @@ class TestMsgSigntxSegwit:
request_finished(),
]
)
_, serialized_tx = btc.sign_tx(client, "Testnet", [inp1], [out1])
_, serialized_tx = btc.sign_tx(
client, "Testnet", [inp1], [out1], prev_txes=TX_API
)
assert (
serialized_tx.hex()
== "01000000000101ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000171600140099a7ecbd938ed1839f5f6bf6d50933c6db9d5cffffffff01010000000100000017a914097c569095163e84475d07aa95a1f736df895b7b8702483045022100cb9d3aa7a8064702e6b61c20c7fb9cb672c69d3786cf5efef8ad6d90136ca7d8022065119ff6c6e6e6960e6508fc5360359bb269bb25ef8d90019decaa0a050cc45a0121033add1f0e8e3c3136f7428dd4a4de1057380bd311f5b0856e2269170b4ffa65bf00000000"
== "01000000000101023a2995a4a60c59df1b9559b49b6d8940cb740d47cea10881b27a9e463ce1de00000000171600140099a7ecbd938ed1839f5f6bf6d50933c6db9d5cffffffff01010000000100000017a914097c569095163e84475d07aa95a1f736df895b7b8702483045022100965aa8897c7cd5f0bff830481ed5259bf662ed0415ab497a6a152a3c335eb0a1022060acbbbada909b6575ac6f19382a6bdf4cab2fa1c5421aa66677806f380ddb870121033add1f0e8e3c3136f7428dd4a4de1057380bd311f5b0856e2269170b4ffa65bf00000000"
)
@pytest.mark.multisig
@ -188,6 +206,10 @@ class TestMsgSigntxSegwit:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_9c3192),
request_input(0, TXHASH_9c3192),
request_output(0, TXHASH_9c3192),
request_output(1, TXHASH_9c3192),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
proto.ButtonRequest(code=B.SignTx),
@ -207,6 +229,10 @@ class TestMsgSigntxSegwit:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_9c3192),
request_input(0, TXHASH_9c3192),
request_output(0, TXHASH_9c3192),
request_output(1, TXHASH_9c3192),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
proto.ButtonRequest(code=B.SignTx),
@ -250,6 +276,10 @@ class TestMsgSigntxSegwit:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_20912f),
request_input(0, TXHASH_20912f),
request_output(0, TXHASH_20912f),
request_output(1, TXHASH_20912f),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
request_output(1),
@ -288,6 +318,10 @@ class TestMsgSigntxSegwit:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_20912f),
request_input(0, TXHASH_20912f),
request_output(0, TXHASH_20912f),
request_output(1, TXHASH_20912f),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
request_output(1),
@ -305,3 +339,82 @@ class TestMsgSigntxSegwit:
assert exc.value.message.endswith(
"Transaction has changed during signing"
)
def test_attack_mixed_inputs(self, client):
TRUE_AMOUNT = 123456789
FAKE_AMOUNT = 123
inp1 = proto.TxInputType(
address_n=parse_path("44'/1'/0'/0/0"),
amount=31000000,
prev_hash=TXHASH_e5040e,
prev_index=0,
script_type=proto.InputScriptType.SPENDADDRESS,
sequence=0xFFFFFFFD,
)
inp2 = proto.TxInputType(
address_n=parse_path("49'/1'/0'/1/0"),
amount=TRUE_AMOUNT,
prev_hash=TXHASH_20912f,
prev_index=0,
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
sequence=0xFFFFFFFD,
)
out1 = proto.TxOutputType(
address="mhRx1CeVfaayqRwq5zgRQmD7W5aWBfD5mC",
amount=30998000,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
expected_responses = [
request_input(0),
request_meta(TXHASH_e5040e),
request_input(0, TXHASH_e5040e),
request_output(0, TXHASH_e5040e),
request_output(1, TXHASH_e5040e),
request_input(1),
request_meta(TXHASH_20912f),
request_input(0, TXHASH_20912f),
request_output(0, TXHASH_20912f),
request_output(1, TXHASH_20912f),
request_output(0),
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
proto.ButtonRequest(code=proto.ButtonRequestType.FeeOverThreshold),
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
request_input(0),
request_input(1),
request_output(0),
request_input(1),
request_output(0),
request_input(1),
request_finished(),
]
if client.features.model == "1":
# T1 asks for first input for witness again
expected_responses.insert(-2, request_input(0))
with client:
# Sign unmodified transaction.
# "Fee over threshold" warning is displayed - fee is the whole TRUE_AMOUNT
client.set_expected_responses(expected_responses)
btc.sign_tx(
client, "Testnet", [inp1, inp2], [out1], prev_txes=TX_API,
)
# In Phase 1 make the user confirm a lower value of the segwit input.
inp2.amount = FAKE_AMOUNT
if client.features.model == "1":
# T1 fails as soon as it encounters the fake amount.
expected_responses = expected_responses[:9] + [proto.Failure()]
else:
expected_responses = expected_responses[:10] + [proto.Failure()]
with pytest.raises(TrezorFailure) as e, client:
client.set_expected_responses(expected_responses)
btc.sign_tx(
client, "Testnet", [inp1, inp2], [out1], prev_txes=TX_API,
)
assert e.value.failure.message.endswith("Invalid amount specified")

@ -21,7 +21,7 @@ from trezorlib.tools import H_, parse_path
from ..bip32 import deserialize
from ..tx_cache import TxCache
from .signtx import request_finished, request_input, request_output
from .signtx import request_finished, request_input, request_meta, request_output
B = proto.ButtonRequestType
TX_API = TxCache("Testnet")
@ -79,6 +79,10 @@ class TestMsgSigntxSegwitNative:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_20912f),
request_input(0, TXHASH_20912f),
request_output(0, TXHASH_20912f),
request_output(1, TXHASH_20912f),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
request_output(1),
@ -123,6 +127,10 @@ class TestMsgSigntxSegwitNative:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_20912f),
request_input(0, TXHASH_20912f),
request_output(0, TXHASH_20912f),
request_output(1, TXHASH_20912f),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
request_output(1),
@ -165,6 +173,10 @@ class TestMsgSigntxSegwitNative:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_091446),
request_input(0, TXHASH_091446),
request_output(0, TXHASH_091446),
request_output(1, TXHASH_091446),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
request_output(1),
@ -208,6 +220,10 @@ class TestMsgSigntxSegwitNative:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_091446),
request_input(0, TXHASH_091446),
request_output(0, TXHASH_091446),
request_output(1, TXHASH_091446),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
request_output(1),
@ -266,7 +282,15 @@ class TestMsgSigntxSegwitNative:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_091446),
request_input(0, TXHASH_091446),
request_output(0, TXHASH_091446),
request_output(1, TXHASH_091446),
request_input(1),
request_meta(TXHASH_65b811),
request_input(0, TXHASH_65b811),
request_output(0, TXHASH_65b811),
request_output(1, TXHASH_65b811),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
request_output(1),
@ -327,6 +351,10 @@ class TestMsgSigntxSegwitNative:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_9c3192),
request_input(0, TXHASH_9c3192),
request_output(0, TXHASH_9c3192),
request_output(1, TXHASH_9c3192),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
proto.ButtonRequest(code=B.SignTx),
@ -346,6 +374,10 @@ class TestMsgSigntxSegwitNative:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_9c3192),
request_input(0, TXHASH_9c3192),
request_output(0, TXHASH_9c3192),
request_output(1, TXHASH_9c3192),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
proto.ButtonRequest(code=B.SignTx),
@ -398,6 +430,9 @@ class TestMsgSigntxSegwitNative:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_f41cbe),
request_input(0, TXHASH_f41cbe),
request_output(0, TXHASH_f41cbe),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
proto.ButtonRequest(code=B.SignTx),
@ -417,6 +452,9 @@ class TestMsgSigntxSegwitNative:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_f41cbe),
request_input(0, TXHASH_f41cbe),
request_output(0, TXHASH_f41cbe),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
proto.ButtonRequest(code=B.SignTx),
@ -476,6 +514,9 @@ class TestMsgSigntxSegwitNative:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_c93480),
request_input(0, TXHASH_c93480),
request_output(0, TXHASH_c93480),
request_output(0),
proto.ButtonRequest(code=B.SignTx),
request_input(0),
@ -495,6 +536,9 @@ class TestMsgSigntxSegwitNative:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_c93480),
request_input(0, TXHASH_c93480),
request_output(0, TXHASH_c93480),
request_output(0),
proto.ButtonRequest(code=B.SignTx),
request_input(0),
@ -553,6 +597,9 @@ class TestMsgSigntxSegwitNative:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_31bc1c),
request_input(0, TXHASH_31bc1c),
request_output(0, TXHASH_31bc1c),
request_output(0),
proto.ButtonRequest(code=B.SignTx),
request_input(0),
@ -572,6 +619,9 @@ class TestMsgSigntxSegwitNative:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_31bc1c),
request_input(0, TXHASH_31bc1c),
request_output(0, TXHASH_31bc1c),
request_output(0),
proto.ButtonRequest(code=B.SignTx),
request_input(0),
@ -645,7 +695,14 @@ class TestMsgSigntxSegwitNative:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_091446),
request_input(0, TXHASH_091446),
request_output(0, TXHASH_091446),
request_output(1, TXHASH_091446),
request_input(1),
request_meta(TXHASH_a345b8),
request_input(0, TXHASH_a345b8),
request_output(0, TXHASH_a345b8),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
request_output(1),

@ -17,10 +17,17 @@
import pytest
from trezorlib import btc, messages as proto
from trezorlib.exceptions import TrezorFailure
from trezorlib.tools import parse_path
from ..tx_cache import TxCache
from .signtx import request_finished, request_input, request_output
from .signtx import (
request_extra_data,
request_finished,
request_input,
request_meta,
request_output,
)
B = proto.ButtonRequestType
TX_API = TxCache("Zcash Testnet")
@ -58,6 +65,11 @@ class TestMsgSigntxZcash:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_aaf51e),
request_input(0, TXHASH_aaf51e),
request_output(0, TXHASH_aaf51e),
request_output(1, TXHASH_aaf51e),
request_extra_data(0, 1, TXHASH_aaf51e),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
proto.ButtonRequest(code=B.SignTx),
@ -107,6 +119,12 @@ class TestMsgSigntxZcash:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_e38206),
request_input(0, TXHASH_e38206),
request_input(1, TXHASH_e38206),
request_output(0, TXHASH_e38206),
request_output(1, TXHASH_e38206),
request_extra_data(0, 1, TXHASH_e38206),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
proto.ButtonRequest(code=B.SignTx),
@ -133,3 +151,29 @@ class TestMsgSigntxZcash:
serialized_tx.hex()
== "0400008085202f890168039326c180fa7b1e999392e25a3ec6a8aec83c11b787ddb1746922020682e3000000006b483045022100f28298891f48706697a6f898ac18e39ce2c7cebe547b585d51cc22d80b1b21a602201a807b8a18544832d95d1e3ada82c0617bc6d97d3f24d1fb4801ac396647aa880121030e669acac1f280d1ddf441cd2ba5e97417bf2689e4bbec86df4f831bf9f7ffd0ffffffff016c9be111000000001976a9145b157a678a10021243307e4bb58f36375aa80e1088ac00000000000000000000000000000000000000"
)
@pytest.mark.skip_ui
def test_version_group_id_missing(self, client):
inp1 = proto.TxInputType(
# tmQoJ3PTXgQLaRRZZYT6xk8XtjRbr2kCqwu
address_n=parse_path("m/44h/1h/0h/0/0"),
amount=300000000,
prev_hash=TXHASH_e38206,
prev_index=0,
)
out1 = proto.TxOutputType(
address="tmJ1xYxP8XNTtCoDgvdmQPSrxh5qZJgy65Z",
amount=300000000 - 1940,
script_type=proto.OutputScriptType.PAYTOADDRESS,
)
details = proto.SignTx(version=4)
with pytest.raises(TrezorFailure, match="Version group ID must be set."):
btc.sign_tx(
client,
"Zcash Testnet",
[inp1],
[out1],
details=details,
prev_txes=TX_API,
)

@ -293,6 +293,10 @@ class TestMultisig:
client.set_expected_responses(
[
request_input(0),
request_meta(TXHASH_fbbff7),
request_input(0, TXHASH_fbbff7),
request_output(0, TXHASH_fbbff7),
request_output(1, TXHASH_fbbff7),
request_output(0),
proto.ButtonRequest(code=B.ConfirmOutput),
request_output(1),
@ -307,7 +311,11 @@ class TestMultisig:
with pytest.raises(TrezorFailure) as exc:
btc.sign_tx(
client, "Testnet", [input_real], [output_payee, output_change]
client,
"Testnet",
[input_real],
[output_payee, output_change],
prev_txes=TxCache("Testnet"),
)
# must not produce this tx:
# 01000000000101396e2c107427f9eaece56a37539983adb8efd52b067c3d4567805fc8f3f7bffb01000000171600147a876a07b366f79000b441335f2907f777a0280bffffffff02e8030000000000001976a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac703a0f000000000017a914a1261837f1b40e84346b1504ffe294e402965f2687024830450221009ff835e861be4e36ca1f2b6224aee2f253dfb9f456b13e4b1724bb4aaff4c9c802205e10679c2ead85743119f468cba5661f68b7da84dd2d477a7215fef98516f1f9012102af12ddd0d55e4fa2fcd084148eaf5b0b641320d0431d63d1e9a90f3cbd0d540700000000

@ -0,0 +1,22 @@
{
"bin_outputs": [
{
"amount": 1896050,
"script_pubkey": "76a914b1401fce7e8bf123c88a0467e0ed11e3b9fbef5488ac"
},
{
"amount": 73452,
"script_pubkey": "76a914d51eca49695cdf47e7f4b55507893e3ad53fe9d888ac"
}
],
"inputs": [
{
"prev_hash": "bc37c28dfb467d2ecb50261387bf752a3977d7e5337915071bb4151e6b711a78",
"prev_index": 0,
"script_sig": "473044022061aee4f17abe044d5df8c52c9ffd3b84e5a29743517e488b20ecf1ae0b3e4d3a02206bb84c55e407f3b684ff8d9bea0a3409cfd865795a19d10b3d3c31f12795c34a412103a020b36130021a0f037c1d1a02042e325c0cb666d6478c1afdcd9d913b9ef080",
"sequence": 4294967295
}
],
"lock_time": 0,
"version": 1
}

@ -0,0 +1,18 @@
{
"bin_outputs": [
{
"amount": 48490,
"script_pubkey": "a91411c1566006ab2b8e8c8d981055b090ecdefa977187"
}
],
"inputs": [
{
"prev_hash": "5f72ec264d961dfdd460a9cc22743c795127b129d40be8087244d93b3f7eee11",
"prev_index": 0,
"script_sig": "00483045022100e87e3ae6ac22ccbaa8a5800b2bbd81aad9ff56e0fc6993953635fd9ee85e49f102204922bebd2ebdb4f80099c22dd9cb8f99961df8b768cc3cb834cffe1cf11777d14147304402206d134d84bbb865b48b901eb22dc1b653a0c2a1614035a6fe30885620edca4f280220256aeaa7efdc7449faaebf4f022a281b8c1ac8335e2292e13e9244baeb04787f414c69522102c5b28669799aba9cd3b6e3fadd9f15009c82a00b3bbf070741de4666b898ee0c21033b8b5f77354be75eba4c98cf4a32d471a827261228aa2ed7d32c67eec7e150562103cfe16448d9d112d5b965dbe338eec6221006a386727512c3a1f704d4604c494653ae",
"sequence": 4294967294
}
],
"lock_time": 0,
"version": 1
}

@ -0,0 +1,18 @@
{
"bin_outputs": [
{
"amount": 1995344,
"script_pubkey": "76a914de701ce12e576395c863e9377c76dd7efe0c55c188ac"
}
],
"inputs": [
{
"prev_hash": "8d566ad80d5f1d3887d3acddb35b980641919e6efa7c3a3a78413e56f95ea516",
"prev_index": 1,
"script_sig": "483045022100860b4c43649f86ee603c13791646af4736c50b532e1fc905c53d73ddd3754f3902206a301113f27b0d10622b333eb914751eed8af7f5534e0e4ee01176668674f259412102e227a30cc2aa732090af6667086b1665cbe6dbde71aab95ada5a518a4c2fdb6e",
"sequence": 4294967295
}
],
"lock_time": 0,
"version": 1
}

@ -0,0 +1,22 @@
{
"bin_outputs": [
{
"amount": 24000,
"script_pubkey": "76a91400741952f6a6eab5394f366db5cc5a54b0c2429f88ac"
},
{
"amount": 24000,
"script_pubkey": "a914756c06d7e77de3950a6124f026d8e1a2464b3ecf87"
}
],
"inputs": [
{
"prev_hash": "8b6db9b8ba24235d86b053ea2ccb484fc32b96f89c3c39f98d86f90db16076a0",
"prev_index": 0,
"script_sig": "00483045022100f1153636371ba1f84389460e1265a8fa296569bc18e117c31f4e8f0fc0650c01022022932cc84766ff0c0f65ed9633ad311ae90d4c8fe71f5e1890b1e8f74dd516fa41483045022100bcb1a7134a13025a06052546ee1c6ac3640a0abd2d130190ed13ed7fcb43e9cd02207c381478e2ee123c850425bfbf6d3c691230eb37e333832cb32a1ed3f2cd9e85414c69522102fcf63419c319ce1a42d69120a3599d6da8c5dd4caf2888220eccde5a1ff7c5d021036d7d5ef79370b7fabe2c058698a20219e97fc70868e65ecdd6b37cc18e8a88bd2103505dc649dab8cd1655a4c0daf0ec5f955881c9d7011478ea881fac11cab1e49953ae",
"sequence": 4294967295
}
],
"lock_time": 0,
"version": 1
}

@ -0,0 +1,22 @@
{
"bin_outputs": [
{
"amount": 1252382934,
"script_pubkey": "76a9140cb60a52559620e5de9a297612d49f55f7fd14ea88ac"
},
{
"amount": 0,
"script_pubkey": "6a24aa21a9eddb3ac2bba12721c8db157ba6b522196093d3a27a8083591a2b785a230a1d254f"
}
],
"inputs": [
{
"prev_hash": "0000000000000000000000000000000000000000000000000000000000000000",
"prev_index": 4294967295,
"script_sig": "03b4e407005a2d4e4f4d50212068747470733a2f2f6769746875622e636f6d2f6a6f7368756179616275742f7a2d6e6f6d70",
"sequence": 4294967295
}
],
"lock_time": 0,
"version": 1
}

@ -0,0 +1,24 @@
{
"bin_outputs": [
{
"amount": 38448607,
"script_pubkey": "76a914b79bbff2766286a99129642d70912c6a4223c62b88ac"
}
],
"inputs": [
{
"prev_hash": "52fb172f86926a89a16edf55bc9baec3929149b7cd2d2389be3c7d08d744d300",
"prev_index": 1,
"script_sig": "4830450221008bff524a092086372a19b924f41fa7fa2a5523bf42a4801b9503fcdfff2094e8022000f223a032bd0d7fee31d5663cd5cf86b82533bda6871366d519a68deae1042341210222c6760cc54de6fd7f2a40207a13137d497c7cdb472376523700d8ea88275a96",
"sequence": 4294967295
},
{
"prev_hash": "371eb4feaa4085b378bb825f3c1b457867c24211ee838584b1adac226bba654b",
"prev_index": 0,
"script_sig": "47304402206aee1d853479782029755dd3c360dbd963e6390da12ddf2c2c38314692510385022040c9c01253a77bc33ac11ce0e8c187ab4f2d78346c0b222a87b1f00fea6b212941210222c6760cc54de6fd7f2a40207a13137d497c7cdb472376523700d8ea88275a96",
"sequence": 4294967295
}
],
"lock_time": 0,
"version": 1
}

@ -0,0 +1,22 @@
{
"bin_outputs": [
{
"amount": 123456789,
"script_pubkey": "a91458b53ea7f832e8f096e896b8713a8c6df0e892ca87"
},
{
"amount": 9764242764,
"script_pubkey": "76a91435528b20e9a793cf2c3a1cf9cff1f2127ad377da88ac"
}
],
"inputs": [
{
"prev_hash": "4f2f857f39ed1afe05542d058fb0be865a387446e32fc876d086203f483f61d1",
"prev_index": 1,
"script_sig": "47304402201f8f57f708144c3a11da322546cb37bd385aa825d940c37e8016f0efd6ec3e9402202a41bc02c29e4f3f13efd4bededbcd4308a6393279111d614ee1f7635cf3e65701210371546a36bdf6bc82087301b3f6e759736dc8790150673d2e7e2715d2ad72f3a4",
"sequence": 4294967294
}
],
"lock_time": 650749,
"version": 1
}

@ -0,0 +1,22 @@
{
"bin_outputs": [
{
"amount": 12300000,
"script_pubkey": "0014b31dc2a236505a6cb9201fa0411ca38a254a7bf1"
},
{
"amount": 9887699777,
"script_pubkey": "76a91438cc090e4a4b2e458c33fe35af1c5c0094699ac288ac"
}
],
"inputs": [
{
"prev_hash": "1c92508b38239e5c10b23fb46dcf765ee2f3a95b835edbf0943ec21b21711160",
"prev_index": 1,
"script_sig": "483045022100d9615361c044e91f6dd7bb4455f3ad686cd5a663d7800bb74c448b2706500ccb022026bed24b81a501e8398411c5a9a793741d9bfe39617d51c363dde0a84f44f4f9012102659a6eefcc72d6f2eff92e57095388b17db0b06034946ecd44120e5e7a830ff4",
"sequence": 4294967293
}
],
"lock_time": 650645,
"version": 1
}

@ -0,0 +1,21 @@
{
"bin_outputs": [
{
"amount": 1099980000,
"script_pubkey": "76a91400178fa0b6fc253a3a402ee2cadd8a7bfec08f6388ac"
}
],
"branch_id": 1991772603,
"inputs": [
{
"prev_hash": "340d478f0c5750057d5f5028db8c10993578849e63f5cf8500e33ddefcd5334f",
"prev_index": 0,
"script_sig": "483045022100d29433faed373d23883ace59acda117a67d6e8e3e99bc767b96a183a840b4aec0220258baef0d63360324f2a455299b2695ae2fa727a5969a25a604c22086e36c6e9012102a87aef7b1a8f676e452d6240767699719cd58b0261c822472c25df146938bca5",
"sequence": 4294967295
}
],
"extra_data": "0000000000000000000000",
"lock_time": 0,
"version": 4,
"version_group_id": 2301567109
}

@ -0,0 +1,21 @@
{
"bin_outputs": [
{
"amount": 1099970000,
"script_pubkey": "76a91400178fa0b6fc253a3a402ee2cadd8a7bfec08f6388ac"
}
],
"branch_id": 1991772603,
"inputs": [
{
"prev_hash": "2807c5b126ec8e2b078cab0f12e4c8b4ce1d7724905f8ebef8dca26b0c8e0f1d",
"prev_index": 0,
"script_sig": "4730440220158c970ca2fc6bcc33026eb5366f0342f63b35d178f7efb334b1df78fe90b67202207bc4ff69f67cf843b08564a5adc77bf5593e28ab4d5104911824ac13fe885d8f012102a87aef7b1a8f676e452d6240767699719cd58b0261c822472c25df146938bca5",
"sequence": 4294967295
}
],
"extra_data": "0000000000000000000000",
"lock_time": 1563046072,
"version": 4,
"version_group_id": 2301567109
}

@ -0,0 +1,22 @@
{
"bin_outputs": [
{
"amount": 12300000,
"script_pubkey": "00140099a7ecbd938ed1839f5f6bf6d50933c6db9d5c"
},
{
"amount": 111145789,
"script_pubkey": "a91458b53ea7f832e8f096e896b8713a8c6df0e892ca87"
}
],
"inputs": [
{
"prev_hash": "20912f98ea3ed849042efed0fdac8cb4fc301961c5988cba56902d8ffb61c337",
"prev_index": 0,
"script_sig": "160014d16b8c0680c61fc6ed2e407455715055e41052f5",
"sequence": 4294967295
}
],
"lock_time": 0,
"version": 1
}

@ -0,0 +1,22 @@
{
"bin_outputs": [
{
"amount": 123456789,
"script_pubkey": "a91458b53ea7f832e8f096e896b8713a8c6df0e892ca87"
},
{
"amount": 865519308,
"script_pubkey": "76a914b84bacdcd8f4cc59274a5bfb73f804ca10f7fd1488ac"
}
],
"inputs": [
{
"prev_hash": "802cabf0843b945eabe136d7fc7c89f41021658abf56cba000acbce88c41143a",
"prev_index": 0,
"script_sig": "4730440220548e087d0426b20b8a571b03b9e05829f7558b80c53c12143e342f56ab29e51d02205b68cb7fb223981d4c999725ac1485a982c4259c4f50b8280f137878c232998a012102794a25b254a268e59a5869da57fbae2fadc6727cb3309321dab409b12b2fa17c",
"sequence": 4294967295
}
],
"lock_time": 0,
"version": 1
}

@ -0,0 +1,18 @@
{
"bin_outputs": [
{
"amount": 1603000,
"script_pubkey": "a914a8655acf68f785125561158b0f4db9b5d004404787"
}
],
"inputs": [
{
"prev_hash": "c9348040bbc2024e12dcb4a0b4806b0398646b91acf314da028c3f03dd0179fc",
"prev_index": 0,
"script_sig": "",
"sequence": 4294967295
}
],
"lock_time": 0,
"version": 1
}

@ -0,0 +1,22 @@
{
"bin_outputs": [
{
"amount": 5000000,
"script_pubkey": "a9147a55d61848e77ca266e79a39bfc85c580a6426c987"
},
{
"amount": 7289000,
"script_pubkey": "0014d16b8c0680c61fc6ed2e407455715055e41052f5"
}
],
"inputs": [
{
"prev_hash": "09144602765ce3dd8f4329445b20e3684e948709c5cdcaf12da3bb079c99448a",
"prev_index": 0,
"script_sig": "",
"sequence": 4294967295
}
],
"lock_time": 0,
"version": 1
}

@ -0,0 +1,22 @@
{
"bin_outputs": [
{
"amount": 11924164,
"script_pubkey": "76a914b6fc54e2f7c490ba20c686f532bfb02230656dbf88ac"
},
{
"amount": 1610436,
"script_pubkey": "a91463ff81a0110ab929bd1d44befa32b081839bbece87"
}
],
"inputs": [
{
"prev_hash": "fbbf0824193fc4e4bb410276345cc235d530563d0da63ecc8d0fecf483c01e5e",
"prev_index": 1,
"script_sig": "47304402206d881393370f90ed0d74121b840794c62701a3fb98f2b14c45cbdc3869f7085802201a884b10eb1a5af026635d266e9b4514a9639b78d0a25cf7ebc579bca254fc7301210307c080981397c49589f3a8eb61e58d654ed1c2aa2fe049149c9757e4ba2a6ba8",
"sequence": 4294967295
}
],
"lock_time": 0,
"version": 1
}

@ -0,0 +1,18 @@
{
"bin_outputs": [
{
"amount": 100,
"script_pubkey": "002008b681071cd896cd879102bce735080758ad48ad45a05505939e55f115391991"
}
],
"inputs": [
{
"prev_hash": "5a67c3318c1636e192924c30ca849dec057892acdce5931b504dc453248d681e",
"prev_index": 0,
"script_sig": "",
"sequence": 4294967293
}
],
"lock_time": 1583125,
"version": 2
}

@ -0,0 +1,18 @@
{
"bin_outputs": [
{
"amount": 1604000,
"script_pubkey": "00201e8dda334f11171190b3da72e526d441491464769679a319a2f011da5ad312a1"
}
],
"inputs": [
{
"prev_hash": "f41cbedd8becee05a830f418d13aa665125464547db5c7a6cd28f21639fe1228",
"prev_index": 0,
"script_sig": "",
"sequence": 4294967295
}
],
"lock_time": 0,
"version": 1
}

@ -0,0 +1,9 @@
{
"bin_outputs": [
{
"amount": 4294967297,
"script_pubkey": "4d7920686f76657263726166742069732066756c6c206f662065656c732e"
}
],
"version": 1
}

@ -0,0 +1,18 @@
{
"bin_outputs": [
{
"amount": 1605000,
"script_pubkey": "0020c5f4a0a4ea7c0392efe0a9670a73264cffa90b19107cd8a8e9750ff93c77fdfb"
}
],
"inputs": [
{
"prev_hash": "9c31922be756c06d02167656465c8dc83bb553bf386a3f478ae65b5c021002be",
"prev_index": 1,
"script_sig": "2200201e8dda334f11171190b3da72e526d441491464769679a319a2f011da5ad312a1",
"sequence": 4294967295
}
],
"lock_time": 0,
"version": 1
}

@ -0,0 +1,22 @@
{
"bin_outputs": [
{
"amount": 3199834,
"script_pubkey": "a9146794cf0b05c69d8e1942a8f9eeaf59a0847dafda87"
},
{
"amount": 1000000,
"script_pubkey": "a914bbc6a47c8984cf60fd1f0eb753291458b5b42aa687"
}
],
"inputs": [
{
"prev_hash": "0e4194441d68c26d3bbc3646d7ad7bc0435cc7c85ac7f39d22587cb4f6959a69",
"prev_index": 15,
"script_sig": "160014e09c199e2cbcd552f0e58acfb933b3f4f426781f",
"sequence": 4294967294
}
],
"lock_time": 1667005,
"version": 2
}

@ -0,0 +1,25 @@
{
"bin_outputs": [
{
"amount": 417937001,
"script_pubkey": "76a914f5ea91f798002a6520f19da514f354b1c37b30d188ac"
},
{
"amount": 300000000,
"script_pubkey": "76a914a579388225827d9f2fe9014add644487808c695d88ac"
}
],
"inputs": [
{
"prev_hash": "01d175a5421206439525542f83d168577e92d59e8283e8862e236a1461d5938a",
"prev_index": 2,
"script_sig": "473044022053a63f730e449f2d6c687ac53e9be627c4241614c041f458da2c4f91143179c802206ade1de030fc5fc77c4a88ccc79daedd28a79bfaf9e24533727a6fb81cbe4bd801210201d494a45f36f545443bafd1a9050b02f448dd236bb4ce2602f83978980b98f2",
"sequence": 4294967294
}
],
"expiry": 234352,
"extra_data": "00",
"lock_time": 234321,
"version": 3,
"version_group_id": 63210096
}

@ -0,0 +1,31 @@
{
"bin_outputs": [
{
"amount": 300000000,
"script_pubkey": "76a914a579388225827d9f2fe9014add644487808c695d88ac"
},
{
"amount": 1251648,
"script_pubkey": "76a91474374446b18916decd3292384ea73006ebd268ba88ac"
}
],
"inputs": [
{
"prev_hash": "4e8e8c5a5524cb8b20d05aefd5b1fd004d6c8c584e3e314876f13edb5ba0eead",
"prev_index": 0,
"script_sig": "473044022064e1e5f957308fcc91f7b174113c8e3cb8060b1404ae823ab3f77f313d5b557b02204b2afcde9ef8b61f5e85192c38fb82307d077ec91d2c8249aa69e19967df8c0c01210201d494a45f36f545443bafd1a9050b02f448dd236bb4ce2602f83978980b98f2",
"sequence": 4294967294
},
{
"prev_hash": "7afab9216fee6763ffbd6a412d46d68c480220af093c9becee6f79d41b954b13",
"prev_index": 0,
"script_sig": "47304402207f63a484ee75900ce2b0e2a5f0d52f2cfb5d1475588576f645c20ecf5e04659a02205c9b614ca846b0cb9ff4a72ca8482c9aed542282b9ee8eaa70a5f472408f3f04012103e974b89ace172f24bb25f8137d19c4205c5cf6bb6505454230ea172f54152d08",
"sequence": 4294967294
}
],
"expiry": 261318,
"extra_data": "00",
"lock_time": 261287,
"version": 3,
"version_group_id": 63210096
}

@ -241,20 +241,19 @@
"test_msg_signtx.py-test_testnet_one_two_fee": "cfd5c83510c044c456622298138e222aee135a6df607bb6e5603228535f0762f",
"test_msg_signtx.py-test_two_changes": "77ac9a437f9ba258577d17528eca1c0c60791fbc273d9cf046ce193bbd9e5e56",
"test_msg_signtx.py-test_two_two": "57707ecbcb77f670148c6076724b3da2e880d27ecf86e29135af4a5aeef6fdbc",
"test_msg_signtx_bcash.py-test_attack_amount": "05cb99d3f9b862c448d07934af46d07f0bc4775c7aef4b113f137932870370bb",
"test_msg_signtx_bcash.py-test_attack_change_input": "a03ee0471deeb54d51b73c0fde08795ab0ba8c37daec2d43f5637e705420b435",
"test_msg_signtx_bcash.py-test_send_bch_change": "a03ee0471deeb54d51b73c0fde08795ab0ba8c37daec2d43f5637e705420b435",
"test_msg_signtx_bcash.py-test_send_bch_multisig_change": "b607b039e864dc9c5f616ee6f5b780184552ff5c6b8e984ccc8eed133b3d36dd",
"test_msg_signtx_bcash.py-test_send_bch_multisig_wrongchange": "8d5c2c06f8d3dd75a03bdf6ecff865e81f8748e4ef5394d75ade3e50512ea087",
"test_msg_signtx_bcash.py-test_send_bch_nochange": "3895b874e18582ea77dea2d10ea44906fce4e67e3b7ce3118f5c959fc428d037",
"test_msg_signtx_bcash.py-test_send_bch_oldaddr": "4a832b4cec5ae0108b8f2155a08156dbbb9ce82403af98532d6ccd89e65d70e3",
"test_msg_signtx_bgold.py-test_attack_change_input": "de2fe54950938864480fd40866db18a73565fdc9de2f7867ab7e0a8ae7f65ce4",
"test_msg_signtx_bgold.py-test_send_bitcoin_gold_change": "de2fe54950938864480fd40866db18a73565fdc9de2f7867ab7e0a8ae7f65ce4",
"test_msg_signtx_bgold.py-test_send_bitcoin_gold_nochange": "65a3fa31182748333a44e8cedcee653d7532428126d6df1ef3514424adcb10f1",
"test_msg_signtx_bgold.py-test_send_btg_multisig_change": "4ed4962fa425498e4d7ae158d1233b01319dfa071edcb2d71f2f4d4e57c4b4fd",
"test_msg_signtx_bgold.py-test_send_mixed_inputs": "ed137c7c45d1bd9f2e73b4ca6ea0eff63b601e8ad73d79a90aefd2046e2d51b2",
"test_msg_signtx_bgold.py-test_send_multisig_1": "d049b3b25042c732ce26a253e7de49581adc83003713860924b8d951cb46de0c",
"test_msg_signtx_bgold.py-test_send_p2sh": "ddd48151ce1d74ade0b9858cbcdba316581991ec92c2ef54b5893e3aae75f995",
"test_msg_signtx_bgold.py-test_attack_change_input": "8e127323823058532b7960ef9507aa24c38c9f22055015d86fdf8132124fb727",
"test_msg_signtx_bgold.py-test_send_bitcoin_gold_change": "8e127323823058532b7960ef9507aa24c38c9f22055015d86fdf8132124fb727",
"test_msg_signtx_bgold.py-test_send_bitcoin_gold_nochange": "6a5adba8117be6e07405372866bf2ac4054d86f2cffb63d64fa0db1f8f3de500",
"test_msg_signtx_bgold.py-test_send_btg_multisig_change": "6a210a01310014a61c7df66558d48a5503b8e8b5644c404b193cefc94bb7dadb",
"test_msg_signtx_bgold.py-test_send_mixed_inputs": "6a5adba8117be6e07405372866bf2ac4054d86f2cffb63d64fa0db1f8f3de500",
"test_msg_signtx_bgold.py-test_send_multisig_1": "0a611e9cc266a5aec9017373cec013756b1715da3bf9d08281194b20ebad72d2",
"test_msg_signtx_bgold.py-test_send_p2sh": "7f481a8cd3474b05cf38aab47592bc754751af7e0f009677fdda95ddaa7b07ca",
"test_msg_signtx_bgold.py-test_send_p2sh_witness_change": "02e44d4c1072eb774486210f885b1bee53acfb3b7fd787207b9f955853fef055",
"test_msg_signtx_dash.py-test_send_dash": "291f1a3ace22877641494a1a470a1a4a8dab6e363fc4402dadaeb52c1288c72b",
"test_msg_signtx_dash.py-test_send_dash_dip2_input": "cf7fc7e6fe3a9e4063e743da6fc44c27dac013917bc00cfc63d13a183c091d91",
@ -271,6 +270,7 @@
"test_msg_signtx_komodo.py-test_one_one_rewards_claim": "e53f221fda81469027e39e21877a81a8fafbffbece0a45aeda12aae8873b0464",
"test_msg_signtx_peercoin.py::test_timestamp_included": "825b9bdf5238c5c6415a254a6bae4b2bd9df8fc5cb31f66f0c20145cb4e60bbb",
"test_msg_signtx_segwit.py-test_attack_change_input_address": "5ae71202c062ef7942626a80a4ceeb8d8c4ea5065a97f0de6a97505e9cb82c2c",
"test_msg_signtx_segwit.py-test_attack_mixed_inputs": "1ae5200c6ce74cefae77ab1cfd6e032d0660aa4d106b8c54e092856f656f1e39",
"test_msg_signtx_segwit.py-test_send_multisig_1": "958a0741070e057dcb889b2000e5487d391bc513e4a5d86193a355261c5f361b",
"test_msg_signtx_segwit.py-test_send_p2sh": "ca593e31e919b9e920289b13e4c70b9607f34b93d06ace69835e3d08ecf046c8",
"test_msg_signtx_segwit.py-test_send_p2sh_change": "562c7ee5a2e264c9f93387dd165403dab32bb305a4c3a6143a902c4a4c9e5950",

Loading…
Cancel
Save