Ragger app client now has proper generic sign methods
This commit is contained in:
@@ -11,7 +11,14 @@ from .tlv import format_tlv
|
|||||||
|
|
||||||
|
|
||||||
WEI_IN_ETH = 1e+18
|
WEI_IN_ETH = 1e+18
|
||||||
|
GWEI_IN_ETH = 1e+9
|
||||||
|
|
||||||
|
class TxData:
|
||||||
|
selector: bytes
|
||||||
|
parameters: list[bytes]
|
||||||
|
def __init__(self, selector: bytes, params: list[bytes]):
|
||||||
|
self.selector = selector
|
||||||
|
self.parameters = params
|
||||||
|
|
||||||
class StatusWord(IntEnum):
|
class StatusWord(IntEnum):
|
||||||
OK = 0x9000
|
OK = 0x9000
|
||||||
@@ -96,31 +103,79 @@ class EthAppClient:
|
|||||||
def eip712_filtering_show_field(self, name: str, sig: bytes):
|
def eip712_filtering_show_field(self, name: str, sig: bytes):
|
||||||
return self._send(self._cmd_builder.eip712_filtering_show_field(name, sig))
|
return self._send(self._cmd_builder.eip712_filtering_show_field(name, sig))
|
||||||
|
|
||||||
def send_fund(self,
|
def _sign(self, bip32_path: str, raw_tx: bytes):
|
||||||
bip32_path: str,
|
chunks = self._cmd_builder.sign(bip32_path, raw_tx)
|
||||||
nonce: int,
|
|
||||||
gas_price: int,
|
|
||||||
gas_limit: int,
|
|
||||||
to: bytes,
|
|
||||||
amount: float,
|
|
||||||
chain_id: int):
|
|
||||||
data: List[Union[int, bytes]] = list()
|
|
||||||
data.append(nonce)
|
|
||||||
data.append(gas_price)
|
|
||||||
data.append(gas_limit)
|
|
||||||
data.append(to)
|
|
||||||
data.append(int(amount * WEI_IN_ETH))
|
|
||||||
data.append(bytes())
|
|
||||||
data.append(chain_id)
|
|
||||||
data.append(bytes())
|
|
||||||
data.append(bytes())
|
|
||||||
|
|
||||||
chunks = self._cmd_builder.sign(bip32_path, rlp.encode(data))
|
|
||||||
for chunk in chunks[:-1]:
|
for chunk in chunks[:-1]:
|
||||||
with self._send(chunk):
|
with self._send(chunk):
|
||||||
pass
|
pass
|
||||||
return self._send(chunks[-1])
|
return self._send(chunks[-1])
|
||||||
|
|
||||||
|
def _data_to_payload(self, data: TxData) -> bytes:
|
||||||
|
payload = bytearray(data.selector)
|
||||||
|
for param in data.parameters:
|
||||||
|
payload += param.rjust(32, b'\x00')
|
||||||
|
return payload
|
||||||
|
|
||||||
|
def _sign_common(self,
|
||||||
|
tx: list,
|
||||||
|
gas_price: float,
|
||||||
|
gas_limit: int,
|
||||||
|
destination: bytes,
|
||||||
|
amount: float,
|
||||||
|
data: TxData):
|
||||||
|
tx.append(int(gas_price * GWEI_IN_ETH))
|
||||||
|
tx.append(gas_limit)
|
||||||
|
tx.append(destination)
|
||||||
|
if amount > 0:
|
||||||
|
tx.append(int(amount * WEI_IN_ETH))
|
||||||
|
else:
|
||||||
|
tx.append(bytes())
|
||||||
|
if data is not None:
|
||||||
|
tx.append(self._data_to_payload(data))
|
||||||
|
else:
|
||||||
|
tx.append(bytes())
|
||||||
|
return tx
|
||||||
|
|
||||||
|
def sign_legacy(self,
|
||||||
|
bip32_path: str,
|
||||||
|
nonce: int,
|
||||||
|
gas_price: float,
|
||||||
|
gas_limit: int,
|
||||||
|
destination: bytes,
|
||||||
|
amount: float,
|
||||||
|
chain_id: int,
|
||||||
|
data: TxData = None):
|
||||||
|
tx = list()
|
||||||
|
tx.append(nonce)
|
||||||
|
tx = self._sign_common(tx, gas_price, gas_limit, destination, amount, data)
|
||||||
|
tx.append(chain_id)
|
||||||
|
tx.append(bytes())
|
||||||
|
tx.append(bytes())
|
||||||
|
return self._sign(bip32_path, rlp.encode(tx))
|
||||||
|
|
||||||
|
def sign_1559(self,
|
||||||
|
bip32_path: str,
|
||||||
|
chain_id: int,
|
||||||
|
nonce: int,
|
||||||
|
max_prio_gas_price: float,
|
||||||
|
max_gas_price: float,
|
||||||
|
gas_limit: int,
|
||||||
|
destination: bytes,
|
||||||
|
amount: float,
|
||||||
|
data: TxData = None,
|
||||||
|
access_list = list()):
|
||||||
|
tx = list()
|
||||||
|
tx.append(chain_id)
|
||||||
|
tx.append(nonce)
|
||||||
|
tx.append(int(max_prio_gas_price * GWEI_IN_ETH))
|
||||||
|
tx = self._sign_common(tx, max_gas_price, gas_limit, destination, amount, data)
|
||||||
|
tx.append(access_list)
|
||||||
|
tx.append(False)
|
||||||
|
tx.append(bytes())
|
||||||
|
tx.append(bytes())
|
||||||
|
# prefix with transaction type
|
||||||
|
return self._sign(bip32_path, b'\x02' + rlp.encode(tx))
|
||||||
|
|
||||||
def get_challenge(self):
|
def get_challenge(self):
|
||||||
return self._send(self._cmd_builder.get_challenge())
|
return self._send(self._cmd_builder.get_challenge())
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ KEY_ID = 1
|
|||||||
ALGO_ID = 1
|
ALGO_ID = 1
|
||||||
BIP32_PATH = "m/44'/60'/0'/0/0"
|
BIP32_PATH = "m/44'/60'/0'/0/0"
|
||||||
NONCE = 21
|
NONCE = 21
|
||||||
GAS_PRICE = 13000000000
|
GAS_PRICE = 13
|
||||||
GAS_LIMIT = 21000
|
GAS_LIMIT = 21000
|
||||||
AMOUNT = 1.22
|
AMOUNT = 1.22
|
||||||
|
|
||||||
@@ -50,13 +50,13 @@ def test_send_fund(firmware: Firmware,
|
|||||||
with app_client.provide_domain_name(challenge, NAME, ADDR):
|
with app_client.provide_domain_name(challenge, NAME, ADDR):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
with app_client.send_fund(BIP32_PATH,
|
with app_client.sign_legacy(BIP32_PATH,
|
||||||
NONCE,
|
NONCE,
|
||||||
GAS_PRICE,
|
GAS_PRICE,
|
||||||
GAS_LIMIT,
|
GAS_LIMIT,
|
||||||
ADDR,
|
ADDR,
|
||||||
AMOUNT,
|
AMOUNT,
|
||||||
CHAIN_ID):
|
CHAIN_ID):
|
||||||
moves = list()
|
moves = list()
|
||||||
if firmware.device.startswith("nano"):
|
if firmware.device.startswith("nano"):
|
||||||
moves += [ NavInsID.RIGHT_CLICK ] * 4
|
moves += [ NavInsID.RIGHT_CLICK ] * 4
|
||||||
@@ -101,13 +101,13 @@ def test_send_fund_wrong_addr(firmware: Firmware,
|
|||||||
addr = bytearray(ADDR)
|
addr = bytearray(ADDR)
|
||||||
addr.reverse()
|
addr.reverse()
|
||||||
|
|
||||||
with app_client.send_fund(BIP32_PATH,
|
with app_client.sign_legacy(BIP32_PATH,
|
||||||
NONCE,
|
NONCE,
|
||||||
GAS_PRICE,
|
GAS_PRICE,
|
||||||
GAS_LIMIT,
|
GAS_LIMIT,
|
||||||
addr,
|
addr,
|
||||||
AMOUNT,
|
AMOUNT,
|
||||||
CHAIN_ID):
|
CHAIN_ID):
|
||||||
moves = list()
|
moves = list()
|
||||||
if firmware.device.startswith("nano"):
|
if firmware.device.startswith("nano"):
|
||||||
moves += [ NavInsID.RIGHT_CLICK ] * 4
|
moves += [ NavInsID.RIGHT_CLICK ] * 4
|
||||||
@@ -130,13 +130,13 @@ def test_send_fund_non_mainnet(firmware: Firmware,
|
|||||||
with app_client.provide_domain_name(challenge, NAME, ADDR):
|
with app_client.provide_domain_name(challenge, NAME, ADDR):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
with app_client.send_fund(BIP32_PATH,
|
with app_client.sign_legacy(BIP32_PATH,
|
||||||
NONCE,
|
NONCE,
|
||||||
GAS_PRICE,
|
GAS_PRICE,
|
||||||
GAS_LIMIT,
|
GAS_LIMIT,
|
||||||
ADDR,
|
ADDR,
|
||||||
AMOUNT,
|
AMOUNT,
|
||||||
5):
|
5):
|
||||||
moves = list()
|
moves = list()
|
||||||
if firmware.device.startswith("nano"):
|
if firmware.device.startswith("nano"):
|
||||||
moves += [ NavInsID.RIGHT_CLICK ] * 5
|
moves += [ NavInsID.RIGHT_CLICK ] * 5
|
||||||
@@ -159,13 +159,13 @@ def test_send_fund_unknown_chain(firmware: Firmware,
|
|||||||
with app_client.provide_domain_name(challenge, NAME, ADDR):
|
with app_client.provide_domain_name(challenge, NAME, ADDR):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
with app_client.send_fund(BIP32_PATH,
|
with app_client.sign_legacy(BIP32_PATH,
|
||||||
NONCE,
|
NONCE,
|
||||||
GAS_PRICE,
|
GAS_PRICE,
|
||||||
GAS_LIMIT,
|
GAS_LIMIT,
|
||||||
ADDR,
|
ADDR,
|
||||||
AMOUNT,
|
AMOUNT,
|
||||||
9):
|
9):
|
||||||
moves = list()
|
moves = list()
|
||||||
if firmware.device.startswith("nano"):
|
if firmware.device.startswith("nano"):
|
||||||
moves += [ NavInsID.RIGHT_CLICK ] * 5
|
moves += [ NavInsID.RIGHT_CLICK ] * 5
|
||||||
|
|||||||
Reference in New Issue
Block a user