Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .git-blame-ignore-revs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
00323cbeb01d1a44b3843a963a54cbce7b6e0a2a
721d1b1efc7b6a96e0ea10aaf0a907294677b12d
1 change: 0 additions & 1 deletion .github/workflows/build_and_functional_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ jobs:
with:
download_app_binaries_artifact: "app_aleo_binaries"
regenerate_snapshots: ${{ github.event_name == 'workflow_dispatch' && inputs.golden_run == 'Open a PR' }}
test_dir: "tests/standalone"

tests_swap:
name: Run swap tests using the reusable workflow
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/coding_style_checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,3 @@ jobs:
uses: LedgerHQ/ledger-app-workflows/.github/workflows/reusable_lint.yml@v1
with:
source: './src'
extensions: 'h,c'
2 changes: 1 addition & 1 deletion .github/workflows/misspellings_checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ jobs:
name: Check misspellings
uses: LedgerHQ/ledger-app-workflows/.github/workflows/reusable_spell_check.yml@v1
with:
ignore_words_list: onTop,TE
ignore_words_list: onTop,TE
2 changes: 1 addition & 1 deletion .github/workflows/python_client_checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@ jobs:
with:
run_type_check: true
src_directory: .
setup_directory: tests/application_client
setup_directory: tests
req_directory: tests/standalone
2 changes: 0 additions & 2 deletions .github/workflows/unit_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,3 @@ jobs:
name: Call Ledger unit_test
uses: LedgerHQ/ledger-app-workflows/.github/workflows/reusable_unit_tests.yml@v1
secrets: inherit
with:
test_directory: unit-tests
22 changes: 13 additions & 9 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,45 +4,49 @@

repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
rev: v6.0.0
hooks:
- id: trailing-whitespace
args: ['--markdown-linebreak-ext=md']
- id: end-of-file-fixer
- id: mixed-line-ending
- id: check-added-large-files
- id: check-merge-conflict
- id: check-case-conflict

- repo: https://github.com/codespell-project/codespell
rev: v2.4.1
rev: v2.4.2
hooks:
- id: codespell
args: ['--ignore-words-list', 'onTop,TE']

- repo: https://github.com/pre-commit/mirrors-clang-format
rev: v14.0.6
rev: v21.1.8
hooks:
- id: clang-format
types_or: [c]

- repo: https://github.com/Mateusz-Grzelinski/actionlint-py
rev: v1.7.7.23
rev: v1.7.12.24
hooks:
- id: actionlint
types_or: [yaml]
args: [-shellcheck='' -pyflakes='']

- repo: https://github.com/markdownlint/markdownlint
rev: v0.12.0
- repo: https://github.com/DavidAnson/markdownlint-cli2
rev: v0.22.1
hooks:
- id: markdownlint
- id: markdownlint-cli2
types_or: [markdown]
exclude: 'CHANGELOG\.md'

- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.15.20
hooks:
# Run the linter.
- id: ruff-check
args: [ --fix ]
types_or: [python, pyi]
args: [--fix]
# Run the formatter.
- id: ruff-format
types_or: [python, pyi]
2 changes: 2 additions & 0 deletions mypy.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[mypy]
ignore_missing_imports = True
3 changes: 3 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[pytest]
testpaths = tests/standalone
pythonpath = tests/standalone
19 changes: 19 additions & 0 deletions ruff.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
target-version = "py311"
line-length = 130

# Vendored third-party packages: not our code to lint.
exclude = [
]

[lint]
select = [
"E", # pycodestyle errors
"F", # pyflakes
"I", # isort
"B", # bugbear
"UP", # pyupgrade
"RUF", # ruff-native rules
]

ignore = [
]
11 changes: 3 additions & 8 deletions tests/application_client/bech32m.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,7 @@ def convert_bits(
return True

@staticmethod
def encode(
output: list[int], hrp: list[int], data: list[int], is_m_encoding: bool
) -> bool:
def encode(output: list[int], hrp: list[int], data: list[int], is_m_encoding: bool) -> bool:
chk = 1
for item in hrp:
ch = item
Expand All @@ -88,7 +86,7 @@ def encode(
chk = BECH32M.polymod_step(chk) ^ item
output.append(ord(BECH32M.CHARSET[item]))

for i in range(6):
for _ in range(6):
chk = BECH32M.polymod_step(chk)
chk ^= BECH32M.final_constant(is_m_encoding)
for i in range(6):
Expand All @@ -103,10 +101,7 @@ def decode(hrp: list[int], data: list[int], input_data: list[int]) -> bool:
return False

data_offset = 0
while (
data_offset < len(input_data)
and input_data[len(input_data) - 1 - data_offset] != 49
):
while data_offset < len(input_data) and input_data[len(input_data) - 1 - data_offset] != 49:
data_offset += 1

hrp_len = len(input_data) - (1 + data_offset)
Expand Down
39 changes: 9 additions & 30 deletions tests/application_client/bigint_256.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,7 @@ def is_even(self) -> bool:
return not self.is_odd()

def is_zero(self) -> bool:
return (
self.value[0] == 0
and self.value[1] == 0
and self.value[2] == 0
and self.value[3] == 0
)
return self.value[0] == 0 and self.value[1] == 0 and self.value[2] == 0 and self.value[3] == 0

def div2(self):
t = 0
Expand All @@ -70,18 +65,10 @@ def add_carry_u64(c: int, a: int, b: int) -> tuple[int, int]:

def add_nocarry(self, other) -> bool:
carry = 0
self.value[0], carry = BigInteger256.add_carry_u64(
carry, self.value[0], other.value[0]
)
self.value[1], carry = BigInteger256.add_carry_u64(
carry, self.value[1], other.value[1]
)
self.value[2], carry = BigInteger256.add_carry_u64(
carry, self.value[2], other.value[2]
)
self.value[3], carry = BigInteger256.add_carry_u64(
carry, self.value[3], other.value[3]
)
self.value[0], carry = BigInteger256.add_carry_u64(carry, self.value[0], other.value[0])
self.value[1], carry = BigInteger256.add_carry_u64(carry, self.value[1], other.value[1])
self.value[2], carry = BigInteger256.add_carry_u64(carry, self.value[2], other.value[2])
self.value[3], carry = BigInteger256.add_carry_u64(carry, self.value[3], other.value[3])
return carry != 0

@staticmethod
Expand All @@ -96,16 +83,8 @@ def subborrow_u64(c: int, a: int, b: int) -> tuple[int, int]:

def sub_noborrow(self, other) -> bool:
borrow = 0
self.value[0], borrow = BigInteger256.subborrow_u64(
borrow, self.value[0], other.value[0]
)
self.value[1], borrow = BigInteger256.subborrow_u64(
borrow, self.value[1], other.value[1]
)
self.value[2], borrow = BigInteger256.subborrow_u64(
borrow, self.value[2], other.value[2]
)
self.value[3], borrow = BigInteger256.subborrow_u64(
borrow, self.value[3], other.value[3]
)
self.value[0], borrow = BigInteger256.subborrow_u64(borrow, self.value[0], other.value[0])
self.value[1], borrow = BigInteger256.subborrow_u64(borrow, self.value[1], other.value[1])
self.value[2], borrow = BigInteger256.subborrow_u64(borrow, self.value[2], other.value[2])
self.value[3], borrow = BigInteger256.subborrow_u64(borrow, self.value[3], other.value[3])
return borrow != 0
27 changes: 8 additions & 19 deletions tests/application_client/command_sender.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,10 @@ def get_app_and_version(self) -> RAPDU:
)

def get_version(self) -> RAPDU:
return self.backend.exchange(
cla=CLA, ins=InsType.CMD_GET_VERSION, p1=0x00, p2=0x00, data=b""
)
return self.backend.exchange(cla=CLA, ins=InsType.CMD_GET_VERSION, p1=0x00, p2=0x00, data=b"")

def get_app_name(self) -> RAPDU:
return self.backend.exchange(
cla=CLA, ins=InsType.CMD_GET_APP_NAME, p1=0x00, p2=0x00, data=b""
)
return self.backend.exchange(cla=CLA, ins=InsType.CMD_GET_APP_NAME, p1=0x00, p2=0x00, data=b"")

def get_address_without_confirmation(self, path: str) -> RAPDU:
return self.backend.exchange(
Expand Down Expand Up @@ -121,13 +117,9 @@ def get_tvk(self, tx_datas: dict) -> RAPDU:
if len(apdus) != 0:
for item in apdus[:-1]:
apdu = bytes.fromhex(item)
self.backend.exchange(
cla=apdu[0], ins=apdu[1], p1=apdu[2], p2=apdu[3], data=apdu[5:]
)
self.backend.exchange(cla=apdu[0], ins=apdu[1], p1=apdu[2], p2=apdu[3], data=apdu[5:])
apdu = bytes.fromhex(apdus[-1])
return self.backend.exchange(
cla=apdu[0], ins=apdu[1], p1=apdu[2], p2=apdu[3], data=apdu[5:]
)
return self.backend.exchange(cla=apdu[0], ins=apdu[1], p1=apdu[2], p2=apdu[3], data=apdu[5:])
return RAPDU(0x0000, b"")

@contextmanager
Expand All @@ -138,15 +130,12 @@ def sign_transaction(self, tx_datas: dict) -> Generator[None, None, None]:
return
for item in apdus[:-1]:
apdu = bytes.fromhex(item)
self.backend.exchange(
cla=apdu[0], ins=apdu[1], p1=apdu[2], p2=apdu[3], data=apdu[5:]
)
self.backend.exchange(cla=apdu[0], ins=apdu[1], p1=apdu[2], p2=apdu[3], data=apdu[5:])
apdu = bytes.fromhex(apdus[-1])
with self.backend.exchange_async(
cla=apdu[0], ins=apdu[1], p1=apdu[2], p2=apdu[3], data=apdu[5:]
) as response:
with self.backend.exchange_async(cla=apdu[0], ins=apdu[1], p1=apdu[2], p2=apdu[3], data=apdu[5:]) as response:
yield response

# Retrieve the last asynchronous response from the backend
def get_async_response(self) -> RAPDU | None:
def get_async_response(self) -> RAPDU:
assert self.backend.last_async_response is not None
return self.backend.last_async_response
12 changes: 0 additions & 12 deletions tests/application_client/setup.cfg
Original file line number Diff line number Diff line change
@@ -1,14 +1,2 @@
[tool:pytest]
addopts = --strict-markers

[pycodestyle]
max-line-length = 140

[mypy-hid.*]
ignore_missing_imports = True

[mypy-pytest.*]
ignore_missing_imports = True

[mypy-ledgered.*]
ignore_missing_imports = True
36 changes: 11 additions & 25 deletions tests/application_client/transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,13 @@ def extract_tlv(tlv: str) -> tuple[TlvTypes, int, str, int]:
else:
t = Transaction.TlvTypes(0)

l = int(tlv[offset : offset + 2], base=16)
length = int(tlv[offset : offset + 2], base=16)
offset += 2

v = tlv[offset : offset + 2 * l]
offset += 2 * l
v = tlv[offset : offset + 2 * length]
offset += 2 * length

return t, l, v, offset
return t, length, v, offset

@staticmethod
def gen_chunks(lst: str, n: int) -> list[tuple]:
Expand Down Expand Up @@ -138,9 +138,7 @@ def get_input_type_from_string(input_type: str) -> str:
elif sp_input_type[-1] == "private":
val += "02" + Transaction.get_plaintext_type_from_string(sp_input_type[0])
elif sp_input_type[-1] == "record":
val += (
f"03{len(sp_input_type[0]):02x}{sp_input_type[0].encode('ascii').hex()}"
)
val += f"03{len(sp_input_type[0]):02x}{sp_input_type[0].encode('ascii').hex()}"
elif sp_input_type[-1] == "external_record":
val += "04"
elif sp_input_type[-1] == "merkle_proof":
Expand Down Expand Up @@ -203,18 +201,14 @@ def generate_request(request: dict, is_root: bool) -> str:
else:
val += Transaction.forge_tlv(Transaction.TlvTypes.NETWORK_ID, "0001")
# Program id
val += Transaction.forge_tlv(
Transaction.TlvTypes.PROGRAM_ID, f"{request['program_id'].encode().hex()}"
)
val += Transaction.forge_tlv(Transaction.TlvTypes.PROGRAM_ID, f"{request['program_id'].encode().hex()}")
# Function name
val += Transaction.forge_tlv(
Transaction.TlvTypes.FUNCTION_NAME,
f"{request['function_name'].encode().hex()}",
)
# Input count
val += Transaction.forge_tlv(
Transaction.TlvTypes.INPUT_COUNT, f"{len(request['inputs']):02x}"
)
val += Transaction.forge_tlv(Transaction.TlvTypes.INPUT_COUNT, f"{len(request['inputs']):02x}")
# Input values & types
val += Transaction.generate_input(request["inputs"])
# Nested call count
Expand All @@ -225,9 +219,7 @@ def generate_request(request: dict, is_root: bool) -> str:
)

if "program_checksum" in request and len(request["program_checksum"]):
val += Transaction.forge_tlv(
Transaction.TlvTypes.PROGRAM_CHECKSUM, request["program_checksum"]
)
val += Transaction.forge_tlv(Transaction.TlvTypes.PROGRAM_CHECKSUM, request["program_checksum"])

return val

Expand All @@ -253,22 +245,16 @@ def gen_intent_apdu(self, tx: dict) -> list[str]:
# Version
req += Transaction.forge_tlv(Transaction.TlvTypes.VERSION, "01")
# max_base_fee
req += Transaction.forge_tlv(
Transaction.TlvTypes.MAX_BASE_FEE, f"{tx['max_base_fee']:08x}"
)
req += Transaction.forge_tlv(Transaction.TlvTypes.MAX_BASE_FEE, f"{tx['max_base_fee']:08x}")
# max_priority_fee
req += Transaction.forge_tlv(
Transaction.TlvTypes.MAX_PRIORITY_FEE, f"{tx['max_priority_fee']:08x}"
)
req += Transaction.forge_tlv(Transaction.TlvTypes.MAX_PRIORITY_FEE, f"{tx['max_priority_fee']:08x}")
# fee_function_name
req += Transaction.forge_tlv(
Transaction.TlvTypes.FEE_FUNCTION_NAME,
tx["fee_function_name"].encode().hex(),
)
# fee_program_id
req += Transaction.forge_tlv(
Transaction.TlvTypes.FEE_PROGRAM_ID, tx["fee_program_id"].encode().hex()
)
req += Transaction.forge_tlv(Transaction.TlvTypes.FEE_PROGRAM_ID, tx["fee_program_id"].encode().hex())
# request
req += Transaction.forge_tlv(
Transaction.TlvTypes.REQUEST,
Expand Down
Loading
Loading