1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-28 10:29:04 +00:00

fix(python): drop simple-rlp dependency and use internal copy

This commit is contained in:
Pavol Rusnak 2023-09-26 23:02:09 +02:00 committed by matejcik
parent df42c99bc9
commit 9b78dd107b
8 changed files with 94 additions and 35 deletions

11
poetry.lock generated
View File

@ -1429,16 +1429,6 @@ colorama = "*"
dev = ["black", "flake8", "isort"] dev = ["black", "flake8", "isort"]
tests = ["pytest"] tests = ["pytest"]
[[package]]
name = "simple-rlp"
version = "0.1.2"
description = "RLP (Recursive Length Prefix) - Encode and decode data structures"
optional = false
python-versions = ">=3.6"
files = [
{file = "simple-rlp-0.1.2.tar.gz", hash = "sha256:5c4a9c58f1b742f7fa8af0fe4ea6ff9fb02294ae041912f771570dfaf339d2b9"},
]
[[package]] [[package]]
name = "six" name = "six"
version = "1.16.0" version = "1.16.0"
@ -1580,7 +1570,6 @@ ecdsa = ">=0.9"
libusb1 = ">=1.6.4" libusb1 = ">=1.6.4"
mnemonic = ">=0.20" mnemonic = ">=0.20"
requests = ">=2.4.0" requests = ">=2.4.0"
simple-rlp = {version = ">=0.1.2", markers = "python_version >= \"3.7\""}
typing_extensions = ">=3.10" typing_extensions = ">=3.10"
[package.extras] [package.extras]

View File

@ -55,7 +55,6 @@ ed25519 = "^1.4"
requests = "^2.31" requests = "^2.31"
termcolor = "*" termcolor = "*"
Pillow = "^9" Pillow = "^9"
simple-rlp = "^0.1.2"
# crypto # crypto
ecdsa = "^0.16" ecdsa = "^0.16"

View File

@ -0,0 +1 @@
Drop simple-rlp dependency and use internal copy

View File

@ -6,5 +6,4 @@ libusb1>=1.6.4
construct>=2.9,!=2.10.55 construct>=2.9,!=2.10.55
typing_extensions>=3.10 typing_extensions>=3.10
dataclasses ; python_version<'3.7' dataclasses ; python_version<'3.7'
simple-rlp>=0.1.2 ; python_version>='3.7'
construct-classes>=0.1.2 construct-classes>=0.1.2

View File

@ -25,7 +25,7 @@ per-file-ignores =
helper-scripts/*:I helper-scripts/*:I
tools/*:I tools/*:I
tests/*:I tests/*:I
known-modules = libusb1:[usb1],hidapi:[hid],PyQt5:[PyQt5.QtWidgets,PyQt5.QtGui,PyQt5.QtCore],simple-rlp:[rlp] known-modules = libusb1:[usb1],hidapi:[hid],PyQt5:[PyQt5.QtWidgets,PyQt5.QtGui,PyQt5.QtCore]
[isort] [isort]
profile = black profile = black

View File

@ -0,0 +1,55 @@
# inspired by core/src/trezor/crypto/rlp.py
import typing as t
from collections.abc import Sequence
if t.TYPE_CHECKING:
RLPItem = t.Union[t.Sequence["RLPItem"], bytes, int]
def _byte_size(x: int) -> int:
if x < 0:
raise ValueError("only unsigned ints are supported")
return (x.bit_length() + 7) // 8
def _int_to_bytes(n: int) -> bytes:
"""Convert to a correctly sized bytes object."""
return n.to_bytes(_byte_size(n), "big")
def _encode_with_length(value: bytes, header_byte: int) -> bytes:
length = len(value)
if length == 1 and value[0] <= 0x7F:
return value
elif length <= 55:
return (header_byte + length).to_bytes(1, "big") + value
else:
encoded_length = _int_to_bytes(length)
return (
(header_byte + 55 + len(encoded_length)).to_bytes(1, "big")
+ encoded_length
+ value
)
def encode(value: "RLPItem") -> bytes:
"""Encode lists or objects to bytes."""
if isinstance(value, int):
# ints are stored as byte strings
value = _int_to_bytes(value)
# sanity check: `str` is a Sequence so it would be incorrectly
# picked up by the Sequence branch below
assert not isinstance(value, str)
# check for bytes type first, because bytes is a Sequence too
if isinstance(value, bytes):
header_byte = 0x80
elif isinstance(value, Sequence):
header_byte = 0xC0
value = b"".join(encode(item) for item in value)
else:
raise TypeError("Unsupported type")
return _encode_with_length(value, header_byte)

View File

@ -20,21 +20,11 @@ import sys
import tarfile import tarfile
from decimal import Decimal from decimal import Decimal
from pathlib import Path from pathlib import Path
from typing import ( from typing import TYPE_CHECKING, Any, Dict, List, NoReturn, Optional, TextIO
TYPE_CHECKING,
Any,
Dict,
List,
NoReturn,
Optional,
Sequence,
TextIO,
Tuple,
)
import click import click
from .. import definitions, ethereum, tools from .. import _rlp, definitions, ethereum, tools
from ..messages import EthereumDefinitions from ..messages import EthereumDefinitions
from . import with_client from . import with_client
@ -162,7 +152,7 @@ def _erc20_contract(token_address: str, to_address: str, amount: int) -> str:
def _format_access_list( def _format_access_list(
access_list: List[ethereum.messages.EthereumAccessList], access_list: List[ethereum.messages.EthereumAccessList],
) -> List[Tuple[bytes, Sequence[bytes]]]: ) -> "_rlp.RLPItem":
return [ return [
(ethereum.decode_hex(item.address), item.storage_keys) for item in access_list (ethereum.decode_hex(item.address), item.storage_keys) for item in access_list
] ]
@ -386,11 +376,6 @@ def sign_tx(
try to connect to an ethereum node and auto-fill these values. You can configure try to connect to an ethereum node and auto-fill these values. You can configure
the connection with WEB3_PROVIDER_URI environment variable. the connection with WEB3_PROVIDER_URI environment variable.
""" """
try:
import rlp
except ImportError:
_print_eth_dependencies_and_die()
is_eip1559 = eip2718_type == 2 is_eip1559 = eip2718_type == 2
if ( if (
(not is_eip1559 and gas_price is None) (not is_eip1559 and gas_price is None)
@ -490,8 +475,6 @@ def sign_tx(
to = ethereum.decode_hex(to_address) to = ethereum.decode_hex(to_address)
# NOTE: rlp.encode needs a list input to iterate through all its items,
# it does not work with a tuple
if is_eip1559: if is_eip1559:
transaction_items = [ transaction_items = [
chain_id, chain_id,
@ -518,7 +501,7 @@ def sign_tx(
data_bytes, data_bytes,
*sig, *sig,
] ]
transaction = rlp.encode(transaction_items) transaction = _rlp.encode(transaction_items)
if eip2718_type is not None: if eip2718_type is not None:
eip2718_prefix = f"{eip2718_type:02x}" eip2718_prefix = f"{eip2718_type:02x}"

33
python/tests/test_rlp.py Normal file
View File

@ -0,0 +1,33 @@
import pytest
from trezorlib import _rlp
VECTORS = ( # data, expected
(b"\x10", b"\x10"),
(b"dog", b"\x83dog"),
(b"A" * 55, b"\xb7" + b"A" * 55),
(b"A" * 56, b"\xb8\x38" + b"A" * 56),
(b"A" * 1024, b"\xb9\x04\x00" + b"A" * 1024),
([b"dog", b"cat", [b"spy"]], b"\xcd\x83dog\x83cat\xc4\x83spy"),
([b"A" * 1024], b"\xf9\x04\x03\xb9\x04\x00" + b"A" * 1024),
([], b"\xc0"),
([b"A"] * 55, b"\xf7" + b"A" * 55),
([b"A"] * 56, b"\xf8\x38" + b"A" * 56),
([b"A"] * 1024, b"\xf9\x04\x00" + b"A" * 1024),
([b"dog"] * 1024, b"\xf9\x10\x00" + b"\x83dog" * 1024),
(b"", b"\x80"),
(1, b"\x01"),
(0x7F, b"\x7f"),
(0x80, b"\x81\x80"),
(0x1_0000_0001, b"\x85\x01\x00\x00\x00\x01"),
(2 ** (54 * 8), b"\xb7\x01" + b"\x00" * 54),
(2 ** (55 * 8), b"\xb8\x38\x01" + b"\x00" * 55),
([0x1234, 0x5678], b"\xc6\x82\x12\x34\x82\x56\x78"),
)
@pytest.mark.parametrize("data, expected", VECTORS)
def test_encode(data: "_rlp.RLPItem", expected: bytes):
actual = _rlp.encode(data)
assert len(actual) == len(expected)
assert actual == expected