Files
app-ethereum/tests/ragger/test_blind_sign.py
2024-05-07 16:24:00 +02:00

139 lines
5.0 KiB
Python

from pathlib import Path
import json
import pytest
from web3 import Web3
from ragger.backend import BackendInterface
from ragger.firmware import Firmware
from ragger.navigator import Navigator, NavInsID
from ragger.navigator.navigation_scenario import NavigateWithScenario
from ragger.error import ExceptionRAPDU
from constants import ABIS_FOLDER
from client.client import EthAppClient, StatusWord
from client.settings import SettingID, settings_toggle
import client.response_parser as ResponseParser
from client.utils import recover_transaction
BIP32_PATH = "m/44'/60'/0'/0/0"
# Token approval, would require loading the "internal plugin" &
# providing the token metadata from the CAL
def test_blind_sign(firmware: Firmware,
backend: BackendInterface,
navigator: Navigator,
default_screenshot_path: Path):
app_client = EthAppClient(backend)
with open(f"{ABIS_FOLDER}/erc20.json", encoding="utf-8") as file:
contract = Web3().eth.contract(
abi=json.load(file),
address=None
)
data = contract.encodeABI("approve", [
# Uniswap Protocol: Permit2
bytes.fromhex("000000000022d473030f116ddee9f6b43ac78ba3"),
Web3.to_wei("2", "ether")
])
tx_params = {
"nonce": 235,
"maxFeePerGas": Web3.to_wei(100, "gwei"),
"maxPriorityFeePerGas": Web3.to_wei(10, "gwei"),
"gas": 44001,
# Maker: Dai Stablecoin
"to": bytes.fromhex("6b175474e89094c44da98b954eedeac495271d0f"),
"data": data,
"chainId": 1
}
with pytest.raises(ExceptionRAPDU) as e:
with app_client.sign(BIP32_PATH, tx_params):
pass
assert e.value.status == StatusWord.INVALID_DATA
moves = []
if firmware.device.startswith("nano"):
if firmware.device == "nanos":
moves += [NavInsID.RIGHT_CLICK]
moves += [NavInsID.BOTH_CLICK]
else:
moves += [NavInsID.USE_CASE_CHOICE_CONFIRM]
navigator.navigate_and_compare(default_screenshot_path,
"blind-signed_approval",
moves)
# Token approval, would require loading the "internal plugin" &
# providing the token metadata from the CAL
def test_sign_parameter_selector(firmware: Firmware,
backend: BackendInterface,
navigator: Navigator,
scenario_navigator: NavigateWithScenario,
test_name: str,
default_screenshot_path: Path):
app_client = EthAppClient(backend)
with app_client.get_public_addr(bip32_path=BIP32_PATH, display=False):
pass
_, DEVICE_ADDR, _ = ResponseParser.pk_addr(app_client.response().data)
with open(f"{ABIS_FOLDER}/erc20.json", encoding="utf-8") as file:
abi = json.load(file)
contract_name = "approve"
count = 0
for elt in abi:
if elt["name"] == contract_name:
count = len(elt["inputs"])
break
assert count == 2, "Invalid inputs number"
tx_params = {
"nonce": 235,
"maxFeePerGas": Web3.to_wei(100, "gwei"),
"maxPriorityFeePerGas": Web3.to_wei(10, "gwei"),
"gas": 44001,
# Maker: Dai Stablecoin
"to": bytes.fromhex("6b175474e89094c44da98b954eedeac495271d0f"),
"data": Web3().eth.contract(abi=abi).encodeABI(contract_name, [
# Uniswap Protocol: Permit2
bytes.fromhex("000000000022d473030f116ddee9f6b43ac78ba3"),
Web3.to_wei("2", "ether")
]),
"chainId": 1
}
settings_toggle(firmware, navigator, [SettingID.DEBUG_DATA, SettingID.BLIND_SIGNING])
with app_client.sign(BIP32_PATH, tx_params):
if firmware.device.startswith("nano"):
end_text = "Approve"
nav_inst = NavInsID.RIGHT_CLICK
valid_instr = [NavInsID.BOTH_CLICK]
else:
end_text = "Confirm"
nav_inst = NavInsID.USE_CASE_REVIEW_TAP
valid_instr = [NavInsID.USE_CASE_REVIEW_CONFIRM]
# Loop for "Selector" + the contract inputs
for step in range(count + 1):
navigator.navigate_until_text_and_compare(nav_inst,
valid_instr,
end_text,
default_screenshot_path,
f"{test_name}/step_{step}",
screen_change_after_last_instruction=False)
step +=1
# Transaction review
if firmware.device.startswith("nano"):
end_text = "Accept"
else:
end_text = "Sign"
scenario_navigator.review_approve(default_screenshot_path, f"{test_name}/step_{step}", end_text)
# verify signature
vrs = ResponseParser.signature(app_client.response().data)
addr = recover_transaction(tx_params, vrs)
assert addr == DEVICE_ADDR