mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-22 07:28:10 +00:00
Merge branch 'release/2020-06'
This commit is contained in:
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=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])),
|
||||
|
||||
helpers.UiConfirmOutput(out1, coin),
|
||||
True,
|
||||
|
||||
TxRequest(request_type=TXOUTPUT, details=TxRequestDetailsType(request_index=1, tx_hash=None), serialized=EMPTY_SERIALIZED),
|
||||
TxAck(tx=TransactionType(outputs=[out2])),
|
||||
|
||||
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'),
|
||||
)),
|
||||
|
||||
TxAck(tx=TransactionType(inputs=[inp1])),
|
||||
|
||||
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())
|
||||
]
|
||||
|
||||
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 (binu[i]) break;
|
||||
}
|
||||
|
||||
// prepend the correct number of null-bytes
|
||||
if (zerocount > i) {
|
||||
/* result too large */
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
--*binszp;
|
||||
}
|
||||
*binszp += zerocount;
|
||||
*binszp = binsz - i + zerocount;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
2468
crypto/bignum.c
2468
crypto/bignum.c
File diff suppressed because it is too large
Load Diff
206
crypto/bignum.h
206
crypto/bignum.h
@ -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);
|
||||
|
||||
void bn_inverse(bignum256 *x, const bignum256 *prime);
|
||||
|
||||
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,
|
||||
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_subtract(const bignum256 *a, const bignum256 *b, bignum256 *res);
|
||||
// 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_divmod58(bignum256 *a, uint32_t *r);
|
||||
// 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_divmod1000(bignum256 *a, uint32_t *r);
|
||||
// y = x
|
||||
static inline void bn_copy(const bignum256 *x, bignum256 *y) { *y = *x; }
|
||||
|
||||
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_even(const bignum256 *x) {
|
||||
return (x->val[0] & 1) == 0;
|
||||
}
|
||||
|
||||
// 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
1028
crypto/tests/test_bignum.py
Executable file
1028
crypto/tests/test_bignum.py
Executable file
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 (!txinput->has_amount) {
|
||||
fsm_sendFailure(FailureType_Failure_DataError,
|
||||
_("Segwit input without amount"));
|
||||
signing_abort();
|
||||
return false;
|
||||
}
|
||||
if (!compile_input_script_sig(txinput)) {
|
||||
fsm_sendFailure(FailureType_Failure_ProcessError,
|
||||
_("Failed to compile input"));
|
||||
signing_abort();
|
||||
return false;
|
||||
}
|
||||
if (txinput->amount > authorized_bip143_in) {
|
||||
fsm_sendFailure(FailureType_Failure_DataError,
|
||||
_("Transaction has changed during signing"));
|
||||
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 = [
|
||||
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),
|
||||
]
|
||||
if client.features.model != "1": # extra screen for lock_time
|
||||
er += [proto.ButtonRequest(code=B.SignTx)]
|
||||
er += [
|
||||
(trezor_core, proto.ButtonRequest(code=B.SignTx)),
|
||||
proto.ButtonRequest(code=B.SignTx),
|
||||
request_input(0),
|
||||
request_output(0),
|
||||
request_finished(),
|
||||
]
|
||||
|
||||
client.set_expected_responses(er)
|
||||
)
|
||||
|
||||
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 = [
|
||||
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),
|
||||
]
|
||||
if client.features.model != "1": # extra screen for lock_time
|
||||
er += [proto.ButtonRequest(code=B.SignTx)]
|
||||
er += [
|
||||
(trezor_core, proto.ButtonRequest(code=B.SignTx)),
|
||||
proto.ButtonRequest(code=B.SignTx),
|
||||
request_input(0),
|
||||
request_output(0),
|
||||
request_output(1),
|
||||
request_finished(),
|
||||
]
|
||||
client.set_expected_responses(er)
|
||||
)
|
||||
|
||||
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…
Reference in New Issue
Block a user