|
|
|
@ -21,9 +21,39 @@ 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
|
|
|
|
|
|
|
|
|
|
B = proto.ButtonRequestType
|
|
|
|
|
TX_API = TxCache("Testnet")
|
|
|
|
|
|
|
|
|
|
TXHASH_20912f = bytes.fromhex(
|
|
|
|
|
"20912f98ea3ed849042efed0fdac8cb4fc301961c5988cba56902d8ffb61c337"
|
|
|
|
|
)
|
|
|
|
|
TXHASH_091446 = bytes.fromhex(
|
|
|
|
|
"09144602765ce3dd8f4329445b20e3684e948709c5cdcaf12da3bb079c99448a"
|
|
|
|
|
)
|
|
|
|
|
TXHASH_65b811 = bytes.fromhex(
|
|
|
|
|
"65b811d3eca0fe6915d9f2d77c86c5a7f19bf66b1b1253c2c51cb4ae5f0c017b"
|
|
|
|
|
)
|
|
|
|
|
TXHASH_e5040e = bytes.fromhex(
|
|
|
|
|
"e5040e1bc1ae7667ffb9e5248e90b2fb93cd9150234151ce90e14ab2f5933bcd"
|
|
|
|
|
)
|
|
|
|
|
TXHASH_9c3192 = bytes.fromhex(
|
|
|
|
|
"9c31922be756c06d02167656465c8dc83bb553bf386a3f478ae65b5c021002be"
|
|
|
|
|
)
|
|
|
|
|
TXHASH_f41cbe = bytes.fromhex(
|
|
|
|
|
"f41cbedd8becee05a830f418d13aa665125464547db5c7a6cd28f21639fe1228"
|
|
|
|
|
)
|
|
|
|
|
TXHASH_c93480 = bytes.fromhex(
|
|
|
|
|
"c9348040bbc2024e12dcb4a0b4806b0398646b91acf314da028c3f03dd0179fc"
|
|
|
|
|
)
|
|
|
|
|
TXHASH_31bc1c = bytes.fromhex(
|
|
|
|
|
"31bc1c88ce6ae337a6b3057a16d5bad0b561ad1dfc047d0a7fbb8814668f91e5"
|
|
|
|
|
)
|
|
|
|
|
TXHASH_a345b8 = bytes.fromhex(
|
|
|
|
|
"a345b85759b385c6446055e4c3baa77e8161a65009dc009489b48aa6587ce348"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TestMsgSigntxSegwitNative:
|
|
|
|
|
def test_send_p2sh(self, client):
|
|
|
|
@ -31,9 +61,7 @@ class TestMsgSigntxSegwitNative:
|
|
|
|
|
address_n=parse_path("49'/1'/0'/1/0"),
|
|
|
|
|
# 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX
|
|
|
|
|
amount=123456789,
|
|
|
|
|
prev_hash=bytes.fromhex(
|
|
|
|
|
"20912f98ea3ed849042efed0fdac8cb4fc301961c5988cba56902d8ffb61c337"
|
|
|
|
|
),
|
|
|
|
|
prev_hash=TXHASH_20912f,
|
|
|
|
|
prev_index=0,
|
|
|
|
|
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
|
|
|
|
|
)
|
|
|
|
@ -50,38 +78,17 @@ class TestMsgSigntxSegwitNative:
|
|
|
|
|
with client:
|
|
|
|
|
client.set_expected_responses(
|
|
|
|
|
[
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=1),
|
|
|
|
|
),
|
|
|
|
|
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
|
|
|
|
|
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=1),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
|
|
|
|
|
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(
|
|
|
|
@ -98,9 +105,7 @@ class TestMsgSigntxSegwitNative:
|
|
|
|
|
address_n=parse_path("49'/1'/0'/1/0"),
|
|
|
|
|
# 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX
|
|
|
|
|
amount=123456789,
|
|
|
|
|
prev_hash=bytes.fromhex(
|
|
|
|
|
"20912f98ea3ed849042efed0fdac8cb4fc301961c5988cba56902d8ffb61c337"
|
|
|
|
|
),
|
|
|
|
|
prev_hash=TXHASH_20912f,
|
|
|
|
|
prev_index=0,
|
|
|
|
|
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
|
|
|
|
|
)
|
|
|
|
@ -117,37 +122,16 @@ class TestMsgSigntxSegwitNative:
|
|
|
|
|
with client:
|
|
|
|
|
client.set_expected_responses(
|
|
|
|
|
[
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=1),
|
|
|
|
|
),
|
|
|
|
|
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=1),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
|
|
|
|
|
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(
|
|
|
|
@ -163,9 +147,7 @@ class TestMsgSigntxSegwitNative:
|
|
|
|
|
inp1 = proto.TxInputType(
|
|
|
|
|
address_n=parse_path("84'/1'/0'/0/0"),
|
|
|
|
|
amount=12300000,
|
|
|
|
|
prev_hash=bytes.fromhex(
|
|
|
|
|
"09144602765ce3dd8f4329445b20e3684e948709c5cdcaf12da3bb079c99448a"
|
|
|
|
|
),
|
|
|
|
|
prev_hash=TXHASH_091446,
|
|
|
|
|
prev_index=0,
|
|
|
|
|
script_type=proto.InputScriptType.SPENDWITNESS,
|
|
|
|
|
)
|
|
|
|
@ -182,38 +164,17 @@ class TestMsgSigntxSegwitNative:
|
|
|
|
|
with client:
|
|
|
|
|
client.set_expected_responses(
|
|
|
|
|
[
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=1),
|
|
|
|
|
),
|
|
|
|
|
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
|
|
|
|
|
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=1),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
|
|
|
|
|
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(
|
|
|
|
@ -229,9 +190,7 @@ class TestMsgSigntxSegwitNative:
|
|
|
|
|
inp1 = proto.TxInputType(
|
|
|
|
|
address_n=parse_path("84'/1'/0'/0/0"),
|
|
|
|
|
amount=12300000,
|
|
|
|
|
prev_hash=bytes.fromhex(
|
|
|
|
|
"09144602765ce3dd8f4329445b20e3684e948709c5cdcaf12da3bb079c99448a"
|
|
|
|
|
),
|
|
|
|
|
prev_hash=TXHASH_091446,
|
|
|
|
|
prev_index=0,
|
|
|
|
|
script_type=proto.InputScriptType.SPENDWITNESS,
|
|
|
|
|
)
|
|
|
|
@ -248,37 +207,16 @@ class TestMsgSigntxSegwitNative:
|
|
|
|
|
with client:
|
|
|
|
|
client.set_expected_responses(
|
|
|
|
|
[
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=1),
|
|
|
|
|
),
|
|
|
|
|
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=1),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
|
|
|
|
|
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(
|
|
|
|
@ -295,18 +233,14 @@ class TestMsgSigntxSegwitNative:
|
|
|
|
|
address_n=parse_path("49'/1'/0'/1/0"),
|
|
|
|
|
# 2N1LGaGg836mqSQqiuUBLfcyGBhyZbremDX
|
|
|
|
|
amount=111145789,
|
|
|
|
|
prev_hash=bytes.fromhex(
|
|
|
|
|
"09144602765ce3dd8f4329445b20e3684e948709c5cdcaf12da3bb079c99448a"
|
|
|
|
|
),
|
|
|
|
|
prev_hash=TXHASH_091446,
|
|
|
|
|
prev_index=1,
|
|
|
|
|
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
|
|
|
|
|
)
|
|
|
|
|
inp2 = proto.TxInputType(
|
|
|
|
|
address_n=parse_path("84'/1'/0'/1/0"),
|
|
|
|
|
amount=7289000,
|
|
|
|
|
prev_hash=bytes.fromhex(
|
|
|
|
|
"65b811d3eca0fe6915d9f2d77c86c5a7f19bf66b1b1253c2c51cb4ae5f0c017b"
|
|
|
|
|
),
|
|
|
|
|
prev_hash=TXHASH_65b811,
|
|
|
|
|
prev_index=1,
|
|
|
|
|
script_type=proto.InputScriptType.SPENDWITNESS,
|
|
|
|
|
)
|
|
|
|
@ -331,59 +265,23 @@ class TestMsgSigntxSegwitNative:
|
|
|
|
|
with client:
|
|
|
|
|
client.set_expected_responses(
|
|
|
|
|
[
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=1),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=1),
|
|
|
|
|
),
|
|
|
|
|
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=2),
|
|
|
|
|
),
|
|
|
|
|
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
|
|
|
|
|
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=1),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=1),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=2),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=1),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
|
|
|
|
|
request_input(0),
|
|
|
|
|
request_input(1),
|
|
|
|
|
request_output(0),
|
|
|
|
|
proto.ButtonRequest(code=B.ConfirmOutput),
|
|
|
|
|
request_output(1),
|
|
|
|
|
proto.ButtonRequest(code=B.ConfirmOutput),
|
|
|
|
|
request_output(2),
|
|
|
|
|
proto.ButtonRequest(code=B.ConfirmOutput),
|
|
|
|
|
proto.ButtonRequest(code=B.SignTx),
|
|
|
|
|
request_input(0),
|
|
|
|
|
request_input(1),
|
|
|
|
|
request_output(0),
|
|
|
|
|
request_output(1),
|
|
|
|
|
request_output(2),
|
|
|
|
|
request_input(0),
|
|
|
|
|
request_input(1),
|
|
|
|
|
request_finished(),
|
|
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
_, serialized_tx = btc.sign_tx(
|
|
|
|
@ -401,18 +299,14 @@ class TestMsgSigntxSegwitNative:
|
|
|
|
|
inp1 = proto.TxInputType(
|
|
|
|
|
address_n=parse_path("44'/1'/0'/0/0"),
|
|
|
|
|
# amount=31000000,
|
|
|
|
|
prev_hash=bytes.fromhex(
|
|
|
|
|
"e5040e1bc1ae7667ffb9e5248e90b2fb93cd9150234151ce90e14ab2f5933bcd"
|
|
|
|
|
),
|
|
|
|
|
prev_hash=TXHASH_e5040e,
|
|
|
|
|
prev_index=0,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
inp2 = proto.TxInputType(
|
|
|
|
|
address_n=parse_path("84'/1'/0'/1/0"),
|
|
|
|
|
amount=7289000,
|
|
|
|
|
prev_hash=bytes.fromhex(
|
|
|
|
|
"65b811d3eca0fe6915d9f2d77c86c5a7f19bf66b1b1253c2c51cb4ae5f0c017b"
|
|
|
|
|
),
|
|
|
|
|
prev_hash=TXHASH_65b811,
|
|
|
|
|
prev_index=1,
|
|
|
|
|
script_type=proto.InputScriptType.SPENDWITNESS,
|
|
|
|
|
)
|
|
|
|
@ -447,9 +341,7 @@ class TestMsgSigntxSegwitNative:
|
|
|
|
|
|
|
|
|
|
inp1 = proto.TxInputType(
|
|
|
|
|
address_n=parse_path("49'/1'/1'/0/0"),
|
|
|
|
|
prev_hash=bytes.fromhex(
|
|
|
|
|
"9c31922be756c06d02167656465c8dc83bb553bf386a3f478ae65b5c021002be"
|
|
|
|
|
),
|
|
|
|
|
prev_hash=TXHASH_9c3192,
|
|
|
|
|
prev_index=1,
|
|
|
|
|
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
|
|
|
|
|
multisig=multisig,
|
|
|
|
@ -465,29 +357,14 @@ class TestMsgSigntxSegwitNative:
|
|
|
|
|
with client:
|
|
|
|
|
client.set_expected_responses(
|
|
|
|
|
[
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
|
|
|
|
|
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
|
|
|
|
|
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(
|
|
|
|
@ -499,29 +376,14 @@ class TestMsgSigntxSegwitNative:
|
|
|
|
|
inp1.address_n[2] = H_(3)
|
|
|
|
|
client.set_expected_responses(
|
|
|
|
|
[
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
|
|
|
|
|
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
|
|
|
|
|
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(
|
|
|
|
@ -548,9 +410,7 @@ class TestMsgSigntxSegwitNative:
|
|
|
|
|
|
|
|
|
|
inp1 = proto.TxInputType(
|
|
|
|
|
address_n=parse_path("84'/1'/2'/0/1"),
|
|
|
|
|
prev_hash=bytes.fromhex(
|
|
|
|
|
"f41cbedd8becee05a830f418d13aa665125464547db5c7a6cd28f21639fe1228"
|
|
|
|
|
),
|
|
|
|
|
prev_hash=TXHASH_f41cbe,
|
|
|
|
|
prev_index=0,
|
|
|
|
|
script_type=proto.InputScriptType.SPENDWITNESS,
|
|
|
|
|
multisig=multisig,
|
|
|
|
@ -566,29 +426,14 @@ class TestMsgSigntxSegwitNative:
|
|
|
|
|
with client:
|
|
|
|
|
client.set_expected_responses(
|
|
|
|
|
[
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
|
|
|
|
|
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
|
|
|
|
|
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(
|
|
|
|
@ -600,29 +445,14 @@ class TestMsgSigntxSegwitNative:
|
|
|
|
|
inp1.address_n[2] = H_(1)
|
|
|
|
|
client.set_expected_responses(
|
|
|
|
|
[
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
|
|
|
|
|
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
|
|
|
|
|
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(
|
|
|
|
@ -655,9 +485,7 @@ class TestMsgSigntxSegwitNative:
|
|
|
|
|
|
|
|
|
|
inp1 = proto.TxInputType(
|
|
|
|
|
address_n=parse_path("84'/1'/1'/1/0"),
|
|
|
|
|
prev_hash=bytes.fromhex(
|
|
|
|
|
"c9348040bbc2024e12dcb4a0b4806b0398646b91acf314da028c3f03dd0179fc"
|
|
|
|
|
),
|
|
|
|
|
prev_hash=TXHASH_c93480,
|
|
|
|
|
prev_index=0,
|
|
|
|
|
script_type=proto.InputScriptType.SPENDWITNESS,
|
|
|
|
|
multisig=multisig,
|
|
|
|
@ -674,28 +502,13 @@ class TestMsgSigntxSegwitNative:
|
|
|
|
|
with client:
|
|
|
|
|
client.set_expected_responses(
|
|
|
|
|
[
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
|
|
|
|
|
request_input(0),
|
|
|
|
|
request_output(0),
|
|
|
|
|
proto.ButtonRequest(code=B.SignTx),
|
|
|
|
|
request_input(0),
|
|
|
|
|
request_output(0),
|
|
|
|
|
request_input(0),
|
|
|
|
|
request_finished(),
|
|
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
signatures, _ = btc.sign_tx(
|
|
|
|
@ -708,28 +521,13 @@ class TestMsgSigntxSegwitNative:
|
|
|
|
|
out1.address_n[2] = H_(3)
|
|
|
|
|
client.set_expected_responses(
|
|
|
|
|
[
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
|
|
|
|
|
request_input(0),
|
|
|
|
|
request_output(0),
|
|
|
|
|
proto.ButtonRequest(code=B.SignTx),
|
|
|
|
|
request_input(0),
|
|
|
|
|
request_output(0),
|
|
|
|
|
request_input(0),
|
|
|
|
|
request_finished(),
|
|
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
_, serialized_tx = btc.sign_tx(
|
|
|
|
@ -762,9 +560,7 @@ class TestMsgSigntxSegwitNative:
|
|
|
|
|
|
|
|
|
|
inp1 = proto.TxInputType(
|
|
|
|
|
address_n=parse_path("49'/1'/1'/1/1"),
|
|
|
|
|
prev_hash=bytes.fromhex(
|
|
|
|
|
"31bc1c88ce6ae337a6b3057a16d5bad0b561ad1dfc047d0a7fbb8814668f91e5"
|
|
|
|
|
),
|
|
|
|
|
prev_hash=TXHASH_31bc1c,
|
|
|
|
|
prev_index=0,
|
|
|
|
|
script_type=proto.InputScriptType.SPENDP2SHWITNESS,
|
|
|
|
|
multisig=multisig,
|
|
|
|
@ -781,28 +577,13 @@ class TestMsgSigntxSegwitNative:
|
|
|
|
|
with client:
|
|
|
|
|
client.set_expected_responses(
|
|
|
|
|
[
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
|
|
|
|
|
request_input(0),
|
|
|
|
|
request_output(0),
|
|
|
|
|
proto.ButtonRequest(code=B.SignTx),
|
|
|
|
|
request_input(0),
|
|
|
|
|
request_output(0),
|
|
|
|
|
request_input(0),
|
|
|
|
|
request_finished(),
|
|
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
signatures, _ = btc.sign_tx(
|
|
|
|
@ -815,28 +596,13 @@ class TestMsgSigntxSegwitNative:
|
|
|
|
|
out1.address_n[2] = H_(3)
|
|
|
|
|
client.set_expected_responses(
|
|
|
|
|
[
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
|
|
|
|
|
request_input(0),
|
|
|
|
|
request_output(0),
|
|
|
|
|
proto.ButtonRequest(code=B.SignTx),
|
|
|
|
|
request_input(0),
|
|
|
|
|
request_output(0),
|
|
|
|
|
request_input(0),
|
|
|
|
|
request_finished(),
|
|
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
_, serialized_tx = btc.sign_tx(
|
|
|
|
@ -873,18 +639,14 @@ class TestMsgSigntxSegwitNative:
|
|
|
|
|
inp1 = proto.TxInputType(
|
|
|
|
|
address_n=parse_path("84'/1'/0'/0/0"),
|
|
|
|
|
amount=12300000,
|
|
|
|
|
prev_hash=bytes.fromhex(
|
|
|
|
|
"09144602765ce3dd8f4329445b20e3684e948709c5cdcaf12da3bb079c99448a"
|
|
|
|
|
),
|
|
|
|
|
prev_hash=TXHASH_091446,
|
|
|
|
|
prev_index=0,
|
|
|
|
|
script_type=proto.InputScriptType.SPENDWITNESS,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
inp2 = proto.TxInputType(
|
|
|
|
|
address_n=parse_path("84'/1'/0'/0/0"),
|
|
|
|
|
prev_hash=bytes.fromhex(
|
|
|
|
|
"a345b85759b385c6446055e4c3baa77e8161a65009dc009489b48aa6587ce348"
|
|
|
|
|
),
|
|
|
|
|
prev_hash=TXHASH_a345b8,
|
|
|
|
|
prev_index=0,
|
|
|
|
|
script_type=proto.InputScriptType.SPENDWITNESS,
|
|
|
|
|
multisig=multisig_in,
|
|
|
|
@ -907,51 +669,21 @@ class TestMsgSigntxSegwitNative:
|
|
|
|
|
with client:
|
|
|
|
|
client.set_expected_responses(
|
|
|
|
|
[
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=1),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=1),
|
|
|
|
|
),
|
|
|
|
|
request_input(0),
|
|
|
|
|
request_input(1),
|
|
|
|
|
request_output(0),
|
|
|
|
|
proto.ButtonRequest(code=B.ConfirmOutput),
|
|
|
|
|
request_output(1),
|
|
|
|
|
# Ensure that the multisig output is not identified as a change output.
|
|
|
|
|
proto.ButtonRequest(code=proto.ButtonRequestType.ConfirmOutput),
|
|
|
|
|
proto.ButtonRequest(code=proto.ButtonRequestType.SignTx),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=1),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXOUTPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=1),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=0),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(
|
|
|
|
|
request_type=proto.RequestType.TXINPUT,
|
|
|
|
|
details=proto.TxRequestDetailsType(request_index=1),
|
|
|
|
|
),
|
|
|
|
|
proto.TxRequest(request_type=proto.RequestType.TXFINISHED),
|
|
|
|
|
proto.ButtonRequest(code=B.ConfirmOutput),
|
|
|
|
|
proto.ButtonRequest(code=B.SignTx),
|
|
|
|
|
request_input(0),
|
|
|
|
|
request_input(1),
|
|
|
|
|
request_output(0),
|
|
|
|
|
request_output(1),
|
|
|
|
|
request_input(0),
|
|
|
|
|
request_input(1),
|
|
|
|
|
request_finished(),
|
|
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|