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:
parent
df42c99bc9
commit
9b78dd107b
11
poetry.lock
generated
11
poetry.lock
generated
@ -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]
|
||||||
|
@ -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"
|
||||||
|
1
python/.changelog.d/3045.fixed
Normal file
1
python/.changelog.d/3045.fixed
Normal file
@ -0,0 +1 @@
|
|||||||
|
Drop simple-rlp dependency and use internal copy
|
@ -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
|
||||||
|
@ -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
|
||||||
|
55
python/src/trezorlib/_rlp.py
Normal file
55
python/src/trezorlib/_rlp.py
Normal 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)
|
@ -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
33
python/tests/test_rlp.py
Normal 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
|
Loading…
Reference in New Issue
Block a user