mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-15 19:08:07 +00:00
458 lines
20 KiB
Python
458 lines
20 KiB
Python
# This file is part of the Trezor project.
|
|
#
|
|
# Copyright (C) 2012-2019 SatoshiLabs and contributors
|
|
#
|
|
# This library is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU Lesser General Public License version 3
|
|
# as published by the Free Software Foundation.
|
|
#
|
|
# This library is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU Lesser General Public License for more details.
|
|
#
|
|
# You should have received a copy of the License along with this library.
|
|
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
|
|
|
|
import pytest
|
|
|
|
from trezorlib import btc, messages as proto
|
|
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
|
|
|
|
B = proto.ButtonRequestType
|
|
TX_API = TxCache("Bgold")
|
|
|
|
TXHASH_25526b = bytes.fromhex(
|
|
"25526bf06c76ad3082bba930cf627cdd5f1b3cd0b9907dd7ff1a07e14addc985"
|
|
)
|
|
TXHASH_db77c2 = bytes.fromhex(
|
|
"db77c2461b840e6edbe7f9280043184a98e020d9795c1b65cb7cef2551a8fb18"
|
|
)
|
|
TXHASH_e5040e = bytes.fromhex(
|
|
"e5040e1bc1ae7667ffb9e5248e90b2fb93cd9150234151ce90e14ab2f5933bcd"
|
|
)
|
|
TXHASH_65b811 = bytes.fromhex(
|
|
"65b811d3eca0fe6915d9f2d77c86c5a7f19bf66b1b1253c2c51cb4ae5f0c017b"
|
|
)
|
|
|
|
|
|
# All data taken from T1
|
|
@pytest.mark.altcoin
|
|
class TestMsgSigntxBitcoinGold:
|
|
def test_send_bitcoin_gold_change(self, client):
|
|
inp1 = proto.TxInputType(
|
|
address_n=parse_path("44'/156'/0'/0/0"),
|
|
amount=1995344,
|
|
prev_hash=TXHASH_25526b,
|
|
prev_index=0,
|
|
script_type=proto.InputScriptType.SPENDADDRESS,
|
|
)
|
|
out1 = proto.TxOutputType(
|
|
address_n=parse_path("44'/156'/0'/1/0"),
|
|
amount=1896050,
|
|
script_type=proto.OutputScriptType.PAYTOADDRESS,
|
|
)
|
|
out2 = proto.TxOutputType(
|
|
address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe",
|
|
amount=73452,
|
|
script_type=proto.OutputScriptType.PAYTOADDRESS,
|
|
)
|
|
with client:
|
|
client.set_expected_responses(
|
|
[
|
|
request_input(0),
|
|
request_output(0),
|
|
request_output(1),
|
|
proto.ButtonRequest(code=B.ConfirmOutput),
|
|
proto.ButtonRequest(code=B.SignTx),
|
|
request_input(0),
|
|
request_output(0),
|
|
request_output(1),
|
|
request_finished(),
|
|
]
|
|
)
|
|
_, serialized_tx = btc.sign_tx(
|
|
client, "Bgold", [inp1], [out1, out2], prev_txes=TX_API
|
|
)
|
|
|
|
assert (
|
|
serialized_tx.hex()
|
|
== "010000000185c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b5225000000006b483045022100963904da0731b71ce468afd45366dd80fbff566ec0d39c1161ab85d17459c7ca02202f5c24a7a7272d98b14a3f5bc000c7cde8ac0eb773f20f4c3131518186cc98854121023bd0ec4022d12d0106c5b7308a25572953ba1951f576f691354a7b147ee0cc1fffffffff0272ee1c00000000001976a9141c82b9c11f193ad82413caadc0955730572b50ae88acec1e0100000000001976a914ea5f904d195079a350b534db4446433b3cec222e88ac00000000"
|
|
)
|
|
|
|
def test_send_bitcoin_gold_nochange(self, client):
|
|
inp1 = proto.TxInputType(
|
|
address_n=parse_path("44'/156'/0'/1/0"),
|
|
amount=1896050,
|
|
prev_hash=TXHASH_25526b,
|
|
prev_index=0,
|
|
script_type=proto.InputScriptType.SPENDADDRESS,
|
|
)
|
|
inp2 = proto.TxInputType(
|
|
address_n=parse_path("44'/156'/0'/0/1"),
|
|
# 1LRspCZNFJcbuNKQkXgHMDucctFRQya5a3
|
|
amount=73452,
|
|
prev_hash=TXHASH_db77c2,
|
|
prev_index=1,
|
|
script_type=proto.InputScriptType.SPENDADDRESS,
|
|
)
|
|
out1 = proto.TxOutputType(
|
|
address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe",
|
|
amount=1934960,
|
|
script_type=proto.OutputScriptType.PAYTOADDRESS,
|
|
)
|
|
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(),
|
|
]
|
|
)
|
|
_, serialized_tx = btc.sign_tx(
|
|
client, "Bgold", [inp1, inp2], [out1], prev_txes=TX_API
|
|
)
|
|
|
|
assert (
|
|
serialized_tx.hex()
|
|
== "010000000285c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b5225000000006b483045022100928852076c9fab160c07564cd54691af1cbc37fb28f0b7bee7299c7925ef62f0022058856387afecc6508f2f04ecdfd292a13026a5b2107ebdd2cc789bdf8820d552412102a6c3998d0d4e5197ff41aab5c53580253b3b91f583f4c31f7624be7dc83ce15fffffffff18fba85125ef7ccb651b5c79d920e0984a18430028f9e7db6e0e841b46c277db010000006b483045022100faa2f4f01cc95e680349a093923aae0aa2ea01429873555aa8a84bf630ef33a002204c3f4bf567e2d20540c0f71dc278481d6ccb6b95acda2a2f87ce521c79d6b872412102d54a7e5733b1635e5e9442943f48179b1700206b2d1925250ba10f1c86878be8ffffffff0170861d00000000001976a914ea5f904d195079a350b534db4446433b3cec222e88ac00000000"
|
|
)
|
|
|
|
def test_attack_change_input(self, client):
|
|
inp1 = proto.TxInputType(
|
|
address_n=parse_path("44'/156'/11'/0/0"),
|
|
amount=1995344,
|
|
prev_hash=TXHASH_25526b,
|
|
prev_index=0,
|
|
script_type=proto.InputScriptType.SPENDADDRESS,
|
|
)
|
|
out1 = proto.TxOutputType(
|
|
address_n=parse_path("44'/156'/11'/1/0"),
|
|
amount=1896050,
|
|
script_type=proto.OutputScriptType.PAYTOADDRESS,
|
|
)
|
|
out2 = proto.TxOutputType(
|
|
address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe",
|
|
amount=73452,
|
|
script_type=proto.OutputScriptType.PAYTOADDRESS,
|
|
)
|
|
|
|
run_attack = False
|
|
|
|
def attack_processor(msg):
|
|
nonlocal run_attack
|
|
|
|
if msg.tx.inputs and msg.tx.inputs[0] == inp1:
|
|
if run_attack:
|
|
msg.tx.inputs[0].address_n[2] = H_(1)
|
|
else:
|
|
run_attack = True
|
|
|
|
return msg
|
|
|
|
client.set_filter(proto.TxAck, attack_processor)
|
|
with client:
|
|
client.set_expected_responses(
|
|
[
|
|
request_input(0),
|
|
request_output(0),
|
|
request_output(1),
|
|
proto.ButtonRequest(code=B.ConfirmOutput),
|
|
proto.ButtonRequest(code=B.SignTx),
|
|
request_input(0),
|
|
proto.Failure(code=proto.FailureType.ProcessError),
|
|
]
|
|
)
|
|
with pytest.raises(TrezorFailure):
|
|
btc.sign_tx(client, "Bgold", [inp1], [out1, out2], prev_txes=TX_API)
|
|
|
|
@pytest.mark.multisig
|
|
def test_send_btg_multisig_change(self, client):
|
|
nodes = [
|
|
btc.get_public_node(
|
|
client, parse_path(f"48'/156'/{i}'"), coin_name="Bgold"
|
|
).node
|
|
for i in range(1, 4)
|
|
]
|
|
|
|
def getmultisig(chain, nr, signatures=[b"", b"", b""], nodes=nodes):
|
|
return proto.MultisigRedeemScriptType(
|
|
nodes=nodes, address_n=[chain, nr], signatures=signatures, m=2
|
|
)
|
|
|
|
inp1 = proto.TxInputType(
|
|
address_n=parse_path("48'/156'/3'/0/0"),
|
|
multisig=getmultisig(0, 0),
|
|
# 33Ju286QvonBz5N1V754ZekQv4GLJqcc5R
|
|
amount=48490,
|
|
prev_hash=TXHASH_25526b,
|
|
prev_index=0,
|
|
script_type=proto.InputScriptType.SPENDMULTISIG,
|
|
)
|
|
out1 = proto.TxOutputType(
|
|
address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe",
|
|
amount=24000,
|
|
script_type=proto.OutputScriptType.PAYTOADDRESS,
|
|
)
|
|
out2 = proto.TxOutputType(
|
|
address_n=parse_path("48'/156'/3'/1/0"),
|
|
multisig=getmultisig(1, 0),
|
|
script_type=proto.OutputScriptType.PAYTOMULTISIG,
|
|
amount=24000,
|
|
)
|
|
with client:
|
|
client.set_expected_responses(
|
|
[
|
|
request_input(0),
|
|
request_output(0),
|
|
proto.ButtonRequest(code=B.ConfirmOutput),
|
|
request_output(1),
|
|
proto.ButtonRequest(code=B.SignTx),
|
|
request_input(0),
|
|
request_output(0),
|
|
request_output(1),
|
|
request_finished(),
|
|
]
|
|
)
|
|
signatures, serialized_tx = btc.sign_tx(
|
|
client, "Bgold", [inp1], [out1, out2], prev_txes=TX_API
|
|
)
|
|
|
|
assert (
|
|
signatures[0].hex()
|
|
== "3045022100d954f341ddd3ec96e4bc6cdb90f2df9b2032723f85e4a0187346dd743130bfca0220105ce08b795c70dc09a55569d7874bff684a877219ec2fc37c88cdffe12f332c"
|
|
)
|
|
|
|
inp1 = proto.TxInputType(
|
|
address_n=parse_path("48'/156'/1'/0/0"),
|
|
multisig=getmultisig(0, 0, [b"", b"", signatures[0]]),
|
|
amount=48490,
|
|
prev_hash=TXHASH_25526b,
|
|
prev_index=0,
|
|
script_type=proto.InputScriptType.SPENDMULTISIG,
|
|
)
|
|
out2.address_n[2] = H_(1)
|
|
|
|
with client:
|
|
client.set_expected_responses(
|
|
[
|
|
request_input(0),
|
|
request_output(0),
|
|
proto.ButtonRequest(code=B.ConfirmOutput),
|
|
request_output(1),
|
|
proto.ButtonRequest(code=B.SignTx),
|
|
request_input(0),
|
|
request_output(0),
|
|
request_output(1),
|
|
request_finished(),
|
|
]
|
|
)
|
|
signatures, serialized_tx = btc.sign_tx(
|
|
client, "Bgold", [inp1], [out1, out2], prev_txes=TX_API
|
|
)
|
|
|
|
assert (
|
|
signatures[0].hex()
|
|
== "30440220614f9a18695365a2edba0d930404a77cae970d3430ad86c5b5239a96fd54bf84022030bc76a322e3b2b1c987622b5eb6da23ac1e6c905ee9b3b6405a4e4edd5bbb87"
|
|
)
|
|
assert (
|
|
serialized_tx.hex()
|
|
== "010000000185c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b522500000000fdfd00004730440220614f9a18695365a2edba0d930404a77cae970d3430ad86c5b5239a96fd54bf84022030bc76a322e3b2b1c987622b5eb6da23ac1e6c905ee9b3b6405a4e4edd5bbb8741483045022100d954f341ddd3ec96e4bc6cdb90f2df9b2032723f85e4a0187346dd743130bfca0220105ce08b795c70dc09a55569d7874bff684a877219ec2fc37c88cdffe12f332c414c695221035a8db79c0ef57a202664a3da60ca41e8865c6d86ed0aafc03f8e75173341b58021037fba152d8fca660cc49973d8bc9421ff49a75b44ea200873d70d3990f763ed4c210348cbcbd93e069416e0d5db93e86b5698852d9fd54502ad0bed9722fa83f90e4b53aeffffffff02c05d0000000000001976a914ea5f904d195079a350b534db4446433b3cec222e88acc05d00000000000017a914623c803f7fb654dac8dda7786fbf9bc38cd867f48700000000"
|
|
)
|
|
|
|
def test_send_p2sh(self, client):
|
|
inp1 = proto.TxInputType(
|
|
address_n=parse_path("49'/156'/0'/1/0"),
|
|
amount=123456789,
|
|
prev_hash=TXHASH_25526b,
|
|
prev_index=0,
|
|
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
|
|
)
|
|
out1 = proto.TxOutputType(
|
|
address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe",
|
|
amount=12300000,
|
|
script_type=proto.OutputScriptType.PAYTOADDRESS,
|
|
)
|
|
out2 = proto.TxOutputType(
|
|
address="GZFLExxrvWFuFT1xRzhfwQWSE2bPDedBfn",
|
|
script_type=proto.OutputScriptType.PAYTOADDRESS,
|
|
amount=123456789 - 11000 - 12300000,
|
|
)
|
|
with client:
|
|
client.set_expected_responses(
|
|
[
|
|
request_input(0),
|
|
request_output(0),
|
|
proto.ButtonRequest(code=B.ConfirmOutput),
|
|
request_output(1),
|
|
proto.ButtonRequest(code=B.ConfirmOutput),
|
|
proto.ButtonRequest(code=B.SignTx),
|
|
request_input(0),
|
|
request_output(0),
|
|
request_output(1),
|
|
request_input(0),
|
|
request_finished(),
|
|
]
|
|
)
|
|
_, serialized_tx = btc.sign_tx(
|
|
client, "Bgold", [inp1], [out1, out2], prev_txes=TX_API
|
|
)
|
|
|
|
assert (
|
|
serialized_tx.hex()
|
|
== "0100000000010185c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b52250000000017160014b5355d001e720d8f4513da00ff2bba4dcf9d39fcffffffff02e0aebb00000000001976a914ea5f904d195079a350b534db4446433b3cec222e88ac3df39f06000000001976a914a8f757819ec6779409f45788f7b4a0e8f51ec50488ac02473044022073fcbf2876f073f78923ab427f14de5b2a0fbeb313a9b2b650b3567061f242a702202f45fc22c501108ff6222afe3aca7da9d8c7dc860f9cda335bef31fa184e7bef412102ecea08b559fc5abd009acf77cfae13fa8a3b1933e3e031956c65c12cec8ca3e300000000"
|
|
)
|
|
|
|
def test_send_p2sh_witness_change(self, client):
|
|
inp1 = proto.TxInputType(
|
|
address_n=parse_path("49'/156'/0'/1/0"),
|
|
amount=123456789,
|
|
prev_hash=TXHASH_25526b,
|
|
prev_index=0,
|
|
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
|
|
)
|
|
out1 = proto.TxOutputType(
|
|
address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe",
|
|
amount=12300000,
|
|
script_type=proto.OutputScriptType.PAYTOADDRESS,
|
|
)
|
|
out2 = proto.TxOutputType(
|
|
address_n=parse_path("49'/156'/0'/1/0"),
|
|
script_type=proto.OutputScriptType.PAYTOP2SHWITNESS,
|
|
amount=123456789 - 11000 - 12300000,
|
|
)
|
|
with client:
|
|
client.set_expected_responses(
|
|
[
|
|
request_input(0),
|
|
request_output(0),
|
|
proto.ButtonRequest(code=B.ConfirmOutput),
|
|
request_output(1),
|
|
proto.ButtonRequest(code=B.SignTx),
|
|
request_input(0),
|
|
request_output(0),
|
|
request_output(1),
|
|
request_input(0),
|
|
request_finished(),
|
|
]
|
|
)
|
|
_, serialized_tx = btc.sign_tx(
|
|
client, "Bgold", [inp1], [out1, out2], prev_txes=TX_API
|
|
)
|
|
|
|
assert (
|
|
serialized_tx.hex()
|
|
== "0100000000010185c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b52250000000017160014b5355d001e720d8f4513da00ff2bba4dcf9d39fcffffffff02e0aebb00000000001976a914ea5f904d195079a350b534db4446433b3cec222e88ac3df39f060000000017a9140cd03822b799a452c106d1b3771844a067b17f118702483045022100d79b33384c686d8dd40ad5f84f46691d30994992c1cb42e934c2a625d86cb2f902206859805a9a98ba140b71a9d4b9a6b8df94a9424f9c40f3bd804149fd6e278d63412102ecea08b559fc5abd009acf77cfae13fa8a3b1933e3e031956c65c12cec8ca3e300000000"
|
|
)
|
|
|
|
@pytest.mark.multisig
|
|
def test_send_multisig_1(self, client):
|
|
nodes = [
|
|
btc.get_public_node(
|
|
client, parse_path(f"49'/156'/{i}'"), coin_name="Bgold"
|
|
).node
|
|
for i in range(1, 4)
|
|
]
|
|
multisig = proto.MultisigRedeemScriptType(
|
|
nodes=nodes, address_n=[1, 0], signatures=[b"", b"", b""], m=2
|
|
)
|
|
|
|
inp1 = proto.TxInputType(
|
|
address_n=parse_path("49'/156'/1'/1/0"),
|
|
prev_hash=TXHASH_25526b,
|
|
prev_index=1,
|
|
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
|
|
multisig=multisig,
|
|
amount=1610436,
|
|
)
|
|
|
|
out1 = proto.TxOutputType(
|
|
address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe",
|
|
amount=1605000,
|
|
script_type=proto.OutputScriptType.PAYTOADDRESS,
|
|
)
|
|
|
|
with client:
|
|
client.set_expected_responses(
|
|
[
|
|
request_input(0),
|
|
request_output(0),
|
|
proto.ButtonRequest(code=B.ConfirmOutput),
|
|
proto.ButtonRequest(code=B.SignTx),
|
|
request_input(0),
|
|
request_output(0),
|
|
request_input(0),
|
|
request_finished(),
|
|
]
|
|
)
|
|
signatures, _ = btc.sign_tx(
|
|
client, "Bgold", [inp1], [out1], prev_txes=TX_API
|
|
)
|
|
# store signature
|
|
inp1.multisig.signatures[0] = signatures[0]
|
|
# sign with third key
|
|
inp1.address_n[2] = H_(3)
|
|
client.set_expected_responses(
|
|
[
|
|
request_input(0),
|
|
request_output(0),
|
|
proto.ButtonRequest(code=B.ConfirmOutput),
|
|
proto.ButtonRequest(code=B.SignTx),
|
|
request_input(0),
|
|
request_output(0),
|
|
request_input(0),
|
|
request_finished(),
|
|
]
|
|
)
|
|
_, serialized_tx = btc.sign_tx(
|
|
client, "Bgold", [inp1], [out1], prev_txes=TX_API
|
|
)
|
|
|
|
assert (
|
|
serialized_tx.hex()
|
|
== "0100000000010185c9dd4ae1071affd77d90b9d03c1b5fdd7c62cf30a9bb8230ad766cf06b52250100000023220020ea9ec48498c451286c2ebaf9e19255e2873b0fb517d67b2f2005298c7e437829ffffffff01887d1800000000001976a914ea5f904d195079a350b534db4446433b3cec222e88ac0400473044022077cb8b2a534f79328810ca8c330539ae9ffa086c359ddb7da11026557b04eef202201d95be0dd1da0aa01720953e52d5dabffd19a998d1490c13a21b8e52e4ead2e041483045022100e41cbd6a501ba8fe6f65554420e23e950d35af0da9b052da54a087463b0717ca02206c695c8d1f74f9535b5d89a2fd1f9326a0ef20e5400137f1e1daeee992b62b594169522103279aea0b253b144d1b2bb8532280001a996dcddd04f86e5e13df1355032cbc1321032c6465c956c0879663fa8be974c912d229c179a5cdedeb29611a1bec1f951eb22103494480a4b72101cbd2eadac8e18c7a3a7589a7f576bf46b8971c38c51e5eceeb53ae00000000"
|
|
)
|
|
|
|
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,
|
|
prev_index=0,
|
|
)
|
|
|
|
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,
|
|
)
|
|
out1 = proto.TxOutputType(
|
|
address="GfDB1tvjfm3bukeoBTtfNqrJVFohS2kCTe",
|
|
amount=31000000 + 7289000 - 1000,
|
|
script_type=proto.OutputScriptType.PAYTOADDRESS,
|
|
)
|
|
|
|
with client:
|
|
_, serialized_tx = btc.sign_tx(
|
|
client, "Bgold", [inp1, inp2], [out1], prev_txes=TX_API
|
|
)
|
|
|
|
assert (
|
|
serialized_tx.hex()
|
|
== "01000000000102cd3b93f5b24ae190ce5141235091cd93fbb2908e24e5b9ff6776aec11b0e04e5000000006a473044022061e94392fa4c0a4bf510bf713c23a37c6c5f6f4dbe5c116e86cff23a93c578e9022026661d2ffb1102d07b7c1631270152441fa171d91108b75a7b9a2cc36ca7db6c4121023bd0ec4022d12d0106c5b7308a25572953ba1951f576f691354a7b147ee0cc1fffffffff7b010c5faeb41cc5c253121b6bf69bf1a7c5867cd7f2d91569fea0ecd311b8650100000000ffffffff01803a4802000000001976a914ea5f904d195079a350b534db4446433b3cec222e88ac0002483045022100e39d9bff8350b9ba20cb2ed88e82d7568a83184616acdc16bd1adb4005c5a471022066ff36084e896a69a91a0fad01721f20f2bb42b41e20be35e72fc3729ac7ace74121030b75ccac9add5f82a4c61fe34e791a2f2eda61b544bce4f6fa3d403bb0de748400000000"
|
|
)
|