Skip to content

Commit 3305b80

Browse files
committed
fix(signing): cover ZIP-229 and ambiguous message acks
1 parent b91d87b commit 3305b80

3 files changed

Lines changed: 51 additions & 4 deletions

File tree

tests/test_msg_mayachain_signtx.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
from ecdsa.util import sigdecode_string
1010

1111
import keepkeylib.messages_pb2 as proto
12+
import keepkeylib.messages_mayachain_pb2 as mayachain_proto
1213
import keepkeylib.types_pb2 as proto_types
14+
from keepkeylib.client import CallException
1315
from keepkeylib.tools import parse_path
1416
from keepkeylib.signed_metadata import eth_sighash_legacy, keccak256
1517

@@ -54,6 +56,28 @@ def recover_eth_signer(sig_r, sig_s, sig_v, digest, chain_id):
5456

5557
class TestMsgMayaChainSignTx(common.KeepKeyTest):
5658

59+
def test_ack_rejects_send_and_deposit_together(self):
60+
"""An unused deposit submessage must not suppress the signed tx memo."""
61+
self.requires_firmware("7.15.0")
62+
self.requires_fullFeature()
63+
self.setup_mnemonic_nopin_nopassphrase()
64+
65+
response = self.client.call(mayachain_proto.MayachainSignTx(
66+
address_n=parse_path(DEFAULT_BIP32_PATH), account_number=92,
67+
chain_id="mayachain", fee_amount=3000, gas=200000,
68+
memo="SWAP:BTC.BTC:bc1qreviewthismemo", sequence=3,
69+
msg_count=1, testnet=False))
70+
self.assertIsInstance(response, mayachain_proto.MayachainMsgRequest)
71+
72+
with self.assertRaises(CallException):
73+
self.client.call(mayachain_proto.MayachainMsgAck(
74+
send=mayachain_proto.MayachainMsgSend(
75+
to_address="maya1jvt443rvhq5h8yrna55yjysvhtju0el7mdujp3",
76+
amount=10000, denom="cacao"),
77+
deposit=mayachain_proto.MayachainMsgDeposit(
78+
asset="MAYA.CACAO", amount=1, memo="unused",
79+
signer="maya1ls33ayg26kmltw7jjy55p32ghjna09zp7z4etj")))
80+
5781
def _maya_send_digest(self, account_number, chain_id, fee, gas, memo,
5882
amount, from_address, to_address, sequence):
5983
"""SHA256 of the amino StdSignDoc exactly as mayachain.c streams it.

tests/test_msg_thorchain_signtx.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,28 @@ def test_legacy_rune_does_not_send_unknown_field(self):
120120

121121
class TestMsgThorChainSignTx(common.KeepKeyTest):
122122

123+
def test_ack_rejects_send_and_deposit_together(self):
124+
"""An unused deposit submessage must not alter the send review flow."""
125+
self.requires_fullFeature()
126+
self.requires_firmware("7.15.0")
127+
self.setup_mnemonic_nopin_nopassphrase()
128+
129+
response = self.client.call(thorchain_proto.ThorchainSignTx(
130+
address_n=parse_path(DEFAULT_BIP32_PATH), account_number=92,
131+
chain_id="thorchain", fee_amount=3000, gas=200000,
132+
memo="SWAP:BTC.BTC:bc1qreviewthismemo", sequence=3,
133+
msg_count=1, testnet=False))
134+
self.assertIsInstance(response, thorchain_proto.ThorchainMsgRequest)
135+
136+
with self.assertRaises(CallException):
137+
self.client.call(thorchain_proto.ThorchainMsgAck(
138+
send=thorchain_proto.ThorchainMsgSend(
139+
to_address="thor1jvt443rvhq5h8yrna55yjysvhtju0el7ldnwwy",
140+
amount=10000, denom="rune"),
141+
deposit=thorchain_proto.ThorchainMsgDeposit(
142+
asset="THOR.RUNE", amount=1, memo="unused",
143+
signer="thor1ls33ayg26kmltw7jjy55p32ghjna09zp6z69y8")))
144+
123145
def test_thorchain_sign_tx(self):
124146
self.requires_fullFeature()
125147
self.requires_firmware("7.0.2")

tests/test_msg_zcash_sign_pczt_device.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -168,10 +168,11 @@ def sign_kwargs(actions, ironwood=False, **overrides):
168168
# victim's note, reusing an approved action's alpha so the one emitted
169169
# RedPallas signature verified in both bundles.
170170
#
171-
# ZIP-244 empty-bundle digest: BLAKE2b-256 of the empty string
172-
# personalized "ZTxIdOrchardHash". The device now requires exactly this.
171+
# ZIP-229 v6 empty-bundle digest: BLAKE2b-256 of the empty string
172+
# personalized "ZTxIdOrchardH_v6". The v5/ZIP-244
173+
# "ZTxIdOrchardHash" value is a different digest.
173174
kwargs['orchard_digest'] = bytes.fromhex(
174-
'9fbe4ed13b0c08e671c11a3407d84e1117cd45028a2eee1b9feae78b48a6e2c1')
175+
'a3367d2fdea2910159fc5026e9bf1fccd3e28ce5e6de46bfb71587230eea9515')
175176
kwargs.update(overrides)
176177
return kwargs
177178

@@ -319,7 +320,7 @@ def test_ironwood_rejects_a_non_empty_orchard_bundle(self):
319320
"""
320321
actions = [note_action(CMX_IRONWOOD)]
321322
kwargs = sign_kwargs(actions, ironwood=True)
322-
# Anything but the ZIP-244 empty-bundle digest must be refused.
323+
# Anything but the ZIP-229 v6 empty-bundle digest must be refused.
323324
kwargs['orchard_digest'] = bytes([0x11]) * 32
324325

325326
with self.assertRaises(Exception) as caught:

0 commit comments

Comments
 (0)