Coverage for tests/ledger/hsm2dongle_cmds/test_hsm2dongle_sign_auth_segwit.py: 100%
44 statements
« prev ^ index » next coverage.py v7.5.3, created at 2025-07-10 13:43 +0000
« prev ^ index » next coverage.py v7.5.3, created at 2025-07-10 13:43 +0000
1# The MIT License (MIT)
2#
3# Copyright (c) 2021 RSK Labs Ltd
4#
5# Permission is hereby granted, free of charge, to any person obtaining a copy of
6# this software and associated documentation files (the "Software"), to deal in
7# the Software without restriction, including without limitation the rights to
8# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9# of the Software, and to permit persons to whom the Software is furnished to do
10# so, subject to the following conditions:
11#
12# The above copyright notice and this permission notice shall be included in all
13# copies or substantial portions of the Software.
14#
15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21# SOFTWARE.
23from unittest.mock import Mock, patch, call
24from parameterized import parameterized
25from tests.ledger.test_hsm2dongle import TestHSM2DongleBase, HSM2DongleTestMode
26from ledger.hsm2dongle import (
27 HSM2DongleError,
28 SighashComputationMode,
29)
30from ledgerblue.commException import CommException
32import logging
34logging.disable(logging.CRITICAL)
37class TestHSM2DongleSignAuthorizedSegwit(TestHSM2DongleBase):
38 def setUp(self):
39 super().setUp()
41 self.SEGWIT_SPEC = {
42 "exchanges": [
43 "q-path >02 01 11223344 D2040000",
44 "a-tx0 <02 02 0C",
45 "q-tx0 >02 02 0F000000 01 0E00 AABBCCDDEE",
46 "a-tx1 <02 02 03",
47 "q-tx1 >02 02 FF7788",
48 "a-tx2 <02 02 05",
49 "q-tx2 >02 02 0522446688",
50 "a-tx3 <02 02 09",
51 "q-tx3 >02 02 AA 992C0A0000000000",
52 "a-rc0 <02 04 04",
53 "q-rc0 >02 04 00112233",
54 "a-rc1 <02 04 06",
55 "q-rc1 >02 04 445566778899",
56 "a-mp0 <02 08 04",
57 "q-mp0 >02 08 03 03 3344",
58 "a-mp1 <02 08 03",
59 "q-mp1 >02 08 55 02 66",
60 "a-mp2 <02 08 07",
61 "q-mp2 >02 08 77 05 aabbccddee",
62 "a-sig <02 81 AABBCCDD",
63 ],
64 "mode": SighashComputationMode.SEGWIT,
65 "tx": "aabbccddeeff7788",
66 "input": 1234,
67 "ws": "22446688aa",
68 "ov": 666777,
69 "receipt": "00112233445566778899",
70 "mp": ["334455", "6677", "aabbccddee"],
71 }
73 @patch("ledger.hsm2dongle.HSM2DongleSignature")
74 def test_ok(self, HSM2DongleSignatureMock):
75 key_id = Mock(**{"to_binary.return_value": bytes.fromhex("11223344")})
76 spec = self.process_sign_auth_spec({**self.SEGWIT_SPEC, "keyid": key_id})
77 HSM2DongleSignatureMock.return_value = "the-signature"
79 self.assertEqual(
80 (True, "the-signature"),
81 self.do_sign_auth(spec)
82 )
83 self.assert_exchange(spec["requests"])
84 self.assertEqual(
85 [call(bytes.fromhex("aabbccdd"))],
86 HSM2DongleSignatureMock.call_args_list,
87 )
89 def test_long_witness_script_length(self):
90 exchanges = [
91 "q-path >02 01 11223344 D2040000",
92 "a-tx0 <02 02 0C",
93 "q-tx0 >02 02 0F000000 01 0D01 AABBCCDDEE",
94 "a-tx1 <02 02 03",
95 "q-tx1 >02 02 FF7788",
96 "a-tx2 <02 02 08",
97 "q-tx2 >02 02 FD0201 0001020304",
98 "a-tx3 <FF",
99 ]
100 key_id = Mock(**{"to_binary.return_value": bytes.fromhex("11223344")})
101 spec = self.process_sign_auth_spec({
102 **self.SEGWIT_SPEC, "exchanges": exchanges,
103 "keyid": key_id, "ws": self.buf(258).hex()
104 }, stop="a-tx3", replace=CommException("forced-stop", 0xFFFF)
105 )
107 with self.assertRaises(HSM2DongleError):
108 self.do_sign_auth(spec)
109 self.assert_exchange(spec["requests"])
111 @parameterized.expand([
112 ("input", "a-tx1", 0x6A88, -2),
113 ("tx_hash_mismatch", "a-tx3", 0x6A8D, -2),
114 ("tx_version", "a-tx2", 0x6A8E, -2),
115 ("invalid_sighash_computation_mode", "a-tx3", 0x6A97, -2),
116 ("invalid_extradata_size", "a-tx1", 0x6A98, -2),
117 ("unknown", "a-tx2", 0x6AFF, -10),
118 ("unexpected", "a-tx3", [0, 0, 0xFF], -10),
119 ])
120 def test_btctx_invalid(self, _, stop, device_error, expected_response):
121 if type(device_error) == int:
122 last_response = CommException("msg", device_error)
123 else:
124 last_response = bytes(device_error)
126 key_id = Mock(**{"to_binary.return_value": bytes.fromhex("11223344")})
127 spec = self.process_sign_auth_spec(
128 {**self.SEGWIT_SPEC, "keyid": key_id},
129 stop=stop,
130 replace=last_response
131 )
133 self.assertEqual(
134 (False, expected_response),
135 self.do_sign_auth(spec)
136 )
137 self.assert_exchange(spec["requests"])
139 def test_btctx_unexpected_error_exc(self):
140 key_id = Mock(**{"to_binary.return_value": bytes.fromhex("11223344")})
141 spec = self.process_sign_auth_spec(
142 {**self.SEGWIT_SPEC, "keyid": key_id},
143 stop="a-tx2",
144 replace=CommException("", 0xFF)
145 )
147 with self.assertRaises(HSM2DongleError):
148 self.do_sign_auth(spec)
149 self.assert_exchange(spec["requests"])
152class TestHSM2DongleSGXSignAuthorizedSegwit(TestHSM2DongleSignAuthorizedSegwit):
153 def get_test_mode(self):
154 return HSM2DongleTestMode.SGX