feat: eip191 tests
@@ -1,7 +1,5 @@
|
||||
from ast import List
|
||||
from contextlib import contextmanager
|
||||
from ctypes.wintypes import INT
|
||||
from re import A
|
||||
import struct
|
||||
from typing import Tuple
|
||||
|
||||
@@ -9,8 +7,9 @@ from speculos.client import SpeculosClient, ApduException
|
||||
|
||||
from ethereum_client.ethereum_cmd_builder import EthereumCommandBuilder, InsType
|
||||
from ethereum_client.exception import DeviceException
|
||||
from ethereum_client.transaction import Transaction
|
||||
from ethereum_client.transaction import PersonalTransaction, Transaction
|
||||
from ethereum_client.plugin import Plugin
|
||||
from ethereum_client.utils import parse_sign_response
|
||||
|
||||
|
||||
class EthereumCommand:
|
||||
@@ -122,47 +121,8 @@ class EthereumCommand:
|
||||
except ApduException as error:
|
||||
raise DeviceException(error_code=error.sw, ins=InsType.INS_SIGN_TX)
|
||||
|
||||
|
||||
# Not use
|
||||
@contextmanager
|
||||
def test_zemu_hard_apdu_sign(self) -> Tuple[int, int, int]:
|
||||
sign: bytes = b'\xe0\x04\x00\x00\x80\x05\x80\x00\x00\x2c\x80\x00\x00\x3c\x80\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\xf8\x69\x46\x85\x06\xa8\xb1\x5e\x00\x82\xeb\xeb\x94\x6b\x17\x54\x74\xe8\x90\x94\xc4\x4d\xa9\x8b\x95\x4e\xed\xea\xc4\x95\x27\x1d\x0f\x80\xb8\x44\x09\x5e\xa7\xb3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7d\x27\x68\xde\x32\xb0\xb8\x0b\x7a\x34\x54\xc0\x6b\xda\xc9\x4a\x69\xdd\xc7\xa9\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x01\x80\x80'
|
||||
simple_eth: bytes = b'\xe0\x04\x00\x00\x41\x05\x80\x00\x00\x2c\x80\x00\x00\x3c\x80\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\xeb\x44\x85\x03\x06\xdc\x42\x00\x82\x52\x08\x94\x5a\x32\x17\x44\x66\x70\x52\xaf\xfa\x83\x86\xed\x49\xe0\x0e\xf2\x23\xcb\xff\xc3\x87\x6f\x9c\x9e\x7b\xf6\x18\x18\x80\x01\x80\x80'
|
||||
provide_erc20: bytes = b'\xe0\x0a\x00\x00\x67\x03\x44\x41\x49\x6b\x17\x54\x74\xe8\x90\x94\xc4\x4d\xa9\x8b\x95\x4e\xed\xea\xc4\x95\x27\x1d\x0f\x00\x00\x00\x12\x00\x00\x00\x01\x30\x45\x02\x21\x00\xb3\xaa\x97\x96\x33\x28\x4e\xb0\xf5\x54\x59\x09\x93\x33\xab\x92\xcf\x06\xfd\xd5\x8d\xc9\x0e\x9c\x07\x00\x00\xc8\xe9\x68\x86\x4c\x02\x20\x7b\x10\xec\x7d\x66\x09\xf5\x1d\xda\x53\xd0\x83\xa6\xe1\x65\xa0\xab\xf3\xa7\x7e\x13\x25\x0e\x6f\x26\x07\x72\x80\x9b\x49\xaf\xf5'
|
||||
|
||||
b: bytes = b'\xe0\x04\x00\x00\x56\x05\x80\x00\x00\x2c\x80\x00\x00\x3c\x80\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\xf8\x3f\x26\x8e\x02\xcc\x9b\xe5\xc5\x3e\xa4\x4b\xd4\x3c\x28\x9d\xcd\xdc\x82\x52\x08\x94\xda\xc1\x7f\x95\x8d\x2e\xe5\x23\xa2\x20\x62\x06\x99\x45\x97\xc1\x3d\x83\x1e\xc7\x92\x8d\xb8\xb0\x86\x1b\x8f\x7f\xe5\xdf\x83\xcd\x55\x3a\x82\x98\x78\x00\x00\x80\x01\x80\x80'
|
||||
test: bytes = b"".join([b'\xe0\x04\x00\x00\x89\x05\x80\x00\x00\x2c\x80\x00\x00\x3c\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
|
||||
b'\x02',
|
||||
b'\xf8\x70\x02',
|
||||
b'\x02', #nonce
|
||||
b'\x85',
|
||||
b'\x02\x54\x0b\xe4\x00', # max priority fee per gas
|
||||
b'\x85',
|
||||
b'\x02\x54\x0b\xe4\x00', # max fee per gas
|
||||
b'\x86',
|
||||
b'\x24\x61\x39\xca\x80\x80', # gas limit
|
||||
b'\x94',
|
||||
b'\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc', # destination
|
||||
b'\x81'+
|
||||
b'\xFF' + # Amount
|
||||
b'\x00' + # Payload
|
||||
b'\xc0\x01\xa0\xe0\x7f\xb8\xa6\x4e\xa3\x78\x6c\x9a\x66\x49\xe5\x44\x29\xe2\x78\x6a\xf3\xea\x31\xc6\xd0\x61\x65\x34\x66\x78\xcf\x8c\xe4\x4f\x9b\xa0\x0e\x4a\x05\x26\xdb\x1e\x90\x5b\x71\x64\xa8\x58\xfd\x5e\xbd\x2f\x17\x59\xe2\x2e\x69\x55\x49\x94\x48\xbd\x27\x6a\x6a\xa6\x28\x30'])
|
||||
|
||||
|
||||
|
||||
try:
|
||||
with self.client._apdu_exchange_nowait(test) as ex:
|
||||
yield ex
|
||||
|
||||
#response = self.client._apdu_exchange(
|
||||
# sign
|
||||
#)
|
||||
except ApduException as error:
|
||||
raise DeviceException(error_code=error.sw, ins=InsType.INS_SIGN_TX)
|
||||
|
||||
|
||||
@contextmanager
|
||||
def simple_sign_tx(self, bip32_path: str, transaction: Transaction, result: List = list()) -> Tuple[int, bytes]:
|
||||
def simple_sign_tx(self, bip32_path: str, transaction: Transaction, result: List = list()) -> None:
|
||||
try:
|
||||
chunk: bytes = self.builder.simple_sign_tx(bip32_path=bip32_path, transaction=transaction)
|
||||
|
||||
@@ -177,19 +137,34 @@ class EthereumCommand:
|
||||
|
||||
# response = V (1) || R (32) || S (32)
|
||||
assert len(response) == 65
|
||||
v, r, s = parse_sign_response(response)
|
||||
|
||||
result.append(v)
|
||||
result.append(r)
|
||||
result.append(s)
|
||||
|
||||
|
||||
offset: int = 0
|
||||
@contextmanager
|
||||
def simple_personal_sign_tx(self, bip32_path: str, transaction: PersonalTransaction, result: List = list()) -> None:
|
||||
try:
|
||||
chunk: bytes = self.builder.simple_personal_sign_tx(bip32_path=bip32_path, transaction=transaction)
|
||||
|
||||
v: bytes = response[offset]
|
||||
offset += 1
|
||||
with self.client.apdu_exchange_nowait(cla=chunk[0], ins=chunk[1],
|
||||
p1=chunk[2], p2=chunk[3],
|
||||
data=chunk[5:]) as exchange:
|
||||
yield exchange
|
||||
response: bytes = exchange.receive()
|
||||
|
||||
except ApduException as error:
|
||||
raise DeviceException(error_code=error.sw, ins=InsType.INS_SIGN_TX)
|
||||
|
||||
r: bytes = response[offset:offset + 32]
|
||||
offset += 32
|
||||
|
||||
s: bytes = response[offset:]
|
||||
# response = V (1) || R (32) || S (32)
|
||||
assert len(response) == 65
|
||||
v, r, s = parse_sign_response(response)
|
||||
|
||||
result.append(v)
|
||||
result.append(r)
|
||||
result.append(s)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import struct
|
||||
from typing import List, Tuple, Union, Iterator, cast
|
||||
|
||||
|
||||
from ethereum_client.transaction import Transaction
|
||||
from ethereum_client.transaction import PersonalTransaction, Transaction
|
||||
from ethereum_client.plugin import Plugin
|
||||
from ethereum_client.utils import bip32_path_from_string
|
||||
|
||||
@@ -274,3 +274,38 @@ class EthereumCommandBuilder:
|
||||
p1=0x00,
|
||||
p2=0x00,
|
||||
cdata=cdata)
|
||||
|
||||
|
||||
def simple_personal_sign_tx(self, bip32_path: str, transaction: PersonalTransaction) -> bytes:
|
||||
"""Command builder for INS_SIGN_PERSONAL_TX.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
bip32_path : str
|
||||
String representation of BIP32 path.
|
||||
transaction : Transaction
|
||||
Representation of the transaction to be signed.
|
||||
|
||||
Yields
|
||||
-------
|
||||
bytes
|
||||
APDU command chunk for INS_SIGN_PERSONAL_TX.
|
||||
|
||||
"""
|
||||
bip32_paths: List[bytes] = bip32_path_from_string(bip32_path)
|
||||
|
||||
cdata: bytes = b"".join([
|
||||
len(bip32_paths).to_bytes(1, byteorder="big"),
|
||||
*bip32_paths
|
||||
])
|
||||
|
||||
|
||||
tx: bytes = transaction.serialize()
|
||||
|
||||
cdata = cdata + tx
|
||||
|
||||
return self.serialize(cla=self.CLA,
|
||||
ins=InsType.INS_SIGN_PERSONAL_TX,
|
||||
p1=0x00,
|
||||
p2=0x00,
|
||||
cdata=cdata)
|
||||
|
||||
@@ -11,6 +11,23 @@ class TransactionError(Exception):
|
||||
EIP2930 = 1
|
||||
EIP1559 = 2
|
||||
|
||||
# e0 + 08 + 00 + 00 + 38 + 05 + 8000002c 8000003c 80000000 00000000 00000000 + 0000001f + 4578616d706c652060706572736f6e616c5f7369676e60206d657373616765
|
||||
# E0 + 08 + 00 + 00 + 34 + 05 + 8000002C 8000003C 80000000 00000000 00000000 + 4578616D706C652060706572736F6E616C5F7369676E60206D657373616765
|
||||
# E0 08 00 00 35058000002C8000003C8000000000000000000000001F4578616D706C652060706572736F6E616C5F7369676E60206D657373616765
|
||||
|
||||
class PersonalTransaction:
|
||||
def __init__(self, msg: Union[str, bytes]) -> None:
|
||||
# If you want to send bytes directly you have to put "0x" before the string
|
||||
if msg[0:2] == "0x":
|
||||
self.msg: bytes = bytes.fromhex(msg[2:])
|
||||
else:
|
||||
self.msg: bytes = bytes(msg, "utf-8")
|
||||
|
||||
def serialize(self) -> bytes:
|
||||
return b"".join([
|
||||
len(self.msg).to_bytes(4, byteorder="big"),
|
||||
self.msg,
|
||||
])
|
||||
|
||||
class Transaction:
|
||||
def __init__(self, txType: int, nonce: int, gasPrice: int, gasLimit: int, to: Union[str, bytes], value: int, data: Union[str, bytes] = "", chainID: int = -1) -> None:
|
||||
|
||||
|
After Width: | Height: | Size: 368 B |
|
After Width: | Height: | Size: 463 B |
|
After Width: | Height: | Size: 423 B |
|
After Width: | Height: | Size: 407 B |
|
After Width: | Height: | Size: 368 B |
|
After Width: | Height: | Size: 492 B |
|
After Width: | Height: | Size: 489 B |
|
After Width: | Height: | Size: 474 B |
|
After Width: | Height: | Size: 490 B |
|
After Width: | Height: | Size: 407 B |
|
After Width: | Height: | Size: 368 B |
|
After Width: | Height: | Size: 475 B |
|
After Width: | Height: | Size: 471 B |
|
After Width: | Height: | Size: 465 B |
|
After Width: | Height: | Size: 449 B |
|
After Width: | Height: | Size: 466 B |
|
After Width: | Height: | Size: 407 B |
|
After Width: | Height: | Size: 368 B |
|
After Width: | Height: | Size: 423 B |
|
After Width: | Height: | Size: 407 B |
|
After Width: | Height: | Size: 449 B |
|
After Width: | Height: | Size: 449 B |
|
After Width: | Height: | Size: 415 B |
|
After Width: | Height: | Size: 624 B |
|
After Width: | Height: | Size: 463 B |
|
After Width: | Height: | Size: 415 B |
|
After Width: | Height: | Size: 882 B |
|
After Width: | Height: | Size: 570 B |
|
After Width: | Height: | Size: 463 B |
|
After Width: | Height: | Size: 415 B |
|
After Width: | Height: | Size: 853 B |
|
After Width: | Height: | Size: 852 B |
|
After Width: | Height: | Size: 837 B |
|
After Width: | Height: | Size: 814 B |
|
After Width: | Height: | Size: 522 B |
|
After Width: | Height: | Size: 463 B |
|
After Width: | Height: | Size: 415 B |
|
After Width: | Height: | Size: 503 B |
|
After Width: | Height: | Size: 463 B |
|
After Width: | Height: | Size: 499 B |
223
tests/speculos/test_eip191.py
Normal file
@@ -0,0 +1,223 @@
|
||||
from time import sleep
|
||||
import ethereum_client
|
||||
|
||||
from ethereum_client.utils import UINT64_MAX, apdu_as_string, compare_screenshot, compare_screenshot, parse_sign_response, save_screenshot, PATH_IMG
|
||||
from ethereum_client.transaction import PersonalTransaction
|
||||
|
||||
def test_personal_sign_metamask(cmd):
|
||||
result: list = []
|
||||
|
||||
bip32_path="44'/60'/0'/0/0"
|
||||
transaction = PersonalTransaction(
|
||||
msg="Example `personal_sign` message"
|
||||
)
|
||||
|
||||
with cmd.simple_personal_sign_tx(bip32_path=bip32_path, transaction=transaction, result=result) as ex:
|
||||
sleep(0.5)
|
||||
|
||||
if cmd.model == "nanos":
|
||||
# Sign message
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_metamask/00000.png")
|
||||
cmd.client.press_and_release('right')
|
||||
|
||||
# Message 1/2, 2/2
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_metamask/00001.png")
|
||||
cmd.client.press_and_release('right')
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_metamask/00002.png")
|
||||
cmd.client.press_and_release('right')
|
||||
|
||||
# Sign message
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_metamask/00003.png")
|
||||
cmd.client.press_and_release('both')
|
||||
if cmd.model == "nanox" or cmd.model == "nanosp":
|
||||
# Sign message
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_metamask/00000.png")
|
||||
cmd.client.press_and_release('right')
|
||||
|
||||
# Message
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_metamask/00001.png")
|
||||
cmd.client.press_and_release('right')
|
||||
|
||||
# Sign message
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_metamask/00002.png")
|
||||
cmd.client.press_and_release('both')
|
||||
|
||||
v, r, s = result
|
||||
|
||||
assert v == 0x1c # 28
|
||||
assert r.hex() == "916099cf0d9c21911c85f0770a47a9696a8189e78c259cf099749748c507baae"
|
||||
assert s.hex() == "0d72234bc0ac2e94c5f7a5f4f9cd8610a52be4ea55515a85b9703f1bb158415c"
|
||||
|
||||
|
||||
def test_personal_sign_reject(cmd):
|
||||
result: list = []
|
||||
|
||||
bip32_path="44'/60'/0'/0/0"
|
||||
transaction = PersonalTransaction(
|
||||
msg="This is an reject sign"
|
||||
)
|
||||
|
||||
try:
|
||||
with cmd.simple_personal_sign_tx(bip32_path=bip32_path, transaction=transaction, result=result) as ex:
|
||||
sleep(0.5)
|
||||
|
||||
if cmd.model == "nanos":
|
||||
# Sign message
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_reject/00000.png")
|
||||
cmd.client.press_and_release('right')
|
||||
|
||||
# Message 1/2, 2/2
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_reject/00001.png")
|
||||
cmd.client.press_and_release('right')
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_reject/00002.png")
|
||||
cmd.client.press_and_release('right')
|
||||
|
||||
# Sign message
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_reject/00003.png")
|
||||
cmd.client.press_and_release('right')
|
||||
|
||||
# Cancel signature
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_reject/00004.png")
|
||||
cmd.client.press_and_release('both')
|
||||
|
||||
if cmd.model == "nanox" or cmd.model == "nanosp":
|
||||
# Sign message
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_reject/00000.png")
|
||||
cmd.client.press_and_release('right')
|
||||
|
||||
# Message
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_reject/00001.png")
|
||||
cmd.client.press_and_release('right')
|
||||
|
||||
# Sign message
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_reject/00002.png")
|
||||
cmd.client.press_and_release('right')
|
||||
|
||||
# Cancel signature
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_reject/00003.png")
|
||||
cmd.client.press_and_release('both')
|
||||
|
||||
except ethereum_client.exception.errors.DenyError as error:
|
||||
assert error.args[0] == '0x6985'
|
||||
|
||||
def test_personal_sign_non_ascii(cmd):
|
||||
result: list = []
|
||||
|
||||
bip32_path="44'/60'/0'/0/0"
|
||||
transaction = PersonalTransaction(
|
||||
msg="0x9c22ff5f21f0b81b113e63f7db6da94fedef11b2119b4088b89664fb9a3cb658"
|
||||
)
|
||||
|
||||
with cmd.simple_personal_sign_tx(bip32_path=bip32_path, transaction=transaction, result=result) as ex:
|
||||
sleep(0.5)
|
||||
|
||||
if cmd.model == "nanos":
|
||||
# Sign message
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_non_ascii/00000.png")
|
||||
cmd.client.press_and_release('right')
|
||||
|
||||
# Message 1/4, 2/4, 3/4, 4/4
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_non_ascii/00001.png")
|
||||
cmd.client.press_and_release('right')
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_non_ascii/00002.png")
|
||||
cmd.client.press_and_release('right')
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_non_ascii/00003.png")
|
||||
cmd.client.press_and_release('right')
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_non_ascii/00004.png")
|
||||
cmd.client.press_and_release('right')
|
||||
|
||||
# Sign message
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_non_ascii/00005.png")
|
||||
cmd.client.press_and_release('both')
|
||||
if cmd.model == "nanox" or cmd.model == "nanosp":
|
||||
# Sign message
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_non_ascii/00000.png")
|
||||
cmd.client.press_and_release('right')
|
||||
|
||||
# Message 1/2, 2/2
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_non_ascii/00001.png")
|
||||
cmd.client.press_and_release('right')
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_non_ascii/00002.png")
|
||||
cmd.client.press_and_release('right')
|
||||
|
||||
# Sign message
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_non_ascii/00003.png")
|
||||
cmd.client.press_and_release('both')
|
||||
|
||||
v, r, s = result
|
||||
|
||||
assert v == 0x1c # 28
|
||||
assert r.hex() == "64bdbdb6959425445d00ff2536a7018d2dce904e1f7475938fe4221c3c72500c"
|
||||
assert s.hex() == "7c9208e99b6b9266a73aae17b73472d06499746edec34fd47a9dab42f06f2e42"
|
||||
|
||||
# ============================
|
||||
# The encoded message is greater than the maximum length of an apdu, that's why we cut it into 3 apdu
|
||||
# ============================
|
||||
|
||||
FIRST_PART = apdu_as_string("e008000096058000002c8000003c8000000000000000000000000000015357656c636f6d6520746f204f70656e536561210a0a436c69636b20746f207369676e20696e20616e642061636365707420746865204f70656e536561205465726d73206f6620536572766963653a2068747470733a2f2f6f70656e7365612e696f2f746f730a0a5468697320726571756573742077696c6c206e6f7420")
|
||||
SECOND_PART = apdu_as_string("e00880009674726967676572206120626c6f636b636861696e207472616e73616374696f6e206f7220636f737420616e792067617320666565732e0a0a596f75722061757468656e7469636174696f6e207374617475732077696c6c20726573657420616674657220323420686f7572732e0a0a57616c6c657420616464726573733a0a3078393835386566666432333262343033336534376439")
|
||||
THIRD_PART = apdu_as_string("e008800040303030336434316563333465636165646139340a0a4e6f6e63653a0a32623032633861302d663734662d343535342d393832312d613238303534646339313231")
|
||||
|
||||
def test_personal_sign_opensea(cmd):
|
||||
result: list = []
|
||||
|
||||
# useless but allows to see which info are in the apdu
|
||||
bip32_path="44'/60'/0'/0/0"
|
||||
transaction = PersonalTransaction(
|
||||
msg="Welcome to OpenSea!\n\nClick to sign in and accept the OpenSea Terms of Service: https://opensea.io/tos\n\nThis request will not trigger a blockchain transaction or cost any gas fees.\n\nYour authentication status will reset after 24 hours.\n\nWallet address:\n0x9858effd232b4033e47d90003d41ec34ecaeda94\n\nNonce:\n2b02c8a0-f74f-4554-9821-a28054dc9121"
|
||||
)
|
||||
|
||||
cmd.send_apdu(FIRST_PART)
|
||||
cmd.send_apdu(SECOND_PART)
|
||||
|
||||
with cmd.send_apdu_context(THIRD_PART, result=result) as ex:
|
||||
sleep(0.5)
|
||||
|
||||
if cmd.model == "nanos":
|
||||
# Sign message
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_opensea/00000.png")
|
||||
cmd.client.press_and_release('right')
|
||||
|
||||
# Message 1/5, 2/5, 3/5, 4/5, 5/5
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_opensea/00001.png")
|
||||
cmd.client.press_and_release('right')
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_opensea/00002.png")
|
||||
cmd.client.press_and_release('right')
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_opensea/00003.png")
|
||||
cmd.client.press_and_release('right')
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_opensea/00004.png")
|
||||
cmd.client.press_and_release('right')
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_opensea/00005.png")
|
||||
cmd.client.press_and_release('right')
|
||||
|
||||
# Sign message
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_opensea/00006.png")
|
||||
cmd.client.press_and_release('both')
|
||||
|
||||
if cmd.model == "nanox" or cmd.model == "nanosp":
|
||||
# Sign message
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_opensea/00000.png")
|
||||
cmd.client.press_and_release('right')
|
||||
|
||||
# Message 1/5, 2/5, 3/5, 4/5, 5/5
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_opensea/00001.png")
|
||||
cmd.client.press_and_release('right')
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_opensea/00002.png")
|
||||
cmd.client.press_and_release('right')
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_opensea/00003.png")
|
||||
cmd.client.press_and_release('right')
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_opensea/00004.png")
|
||||
cmd.client.press_and_release('right')
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_opensea/00005.png")
|
||||
cmd.client.press_and_release('right')
|
||||
|
||||
# Sign message
|
||||
compare_screenshot(cmd, f"screenshots/eip191/{PATH_IMG[cmd.model]}/personal_sign_opensea/00006.png")
|
||||
cmd.client.press_and_release('both')
|
||||
|
||||
response: bytes = result[0]
|
||||
v, r, s = parse_sign_response(response)
|
||||
|
||||
assert v == 0x1c # 28
|
||||
assert r.hex() == "61a68c986f087730d2f6ecf89d6d1e48ab963ac461102bb02664bc05c3db75bb"
|
||||
assert s.hex() == "5714729ef441e097673a7b29a681e97f6963d875eeed2081f26b0b6686cd2bd2"
|
||||