Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
26081b6
fix icons
Liuhaai Jun 10, 2025
fec5977
Code optimization
cedelavergne-ledger Jul 3, 2025
7cd53b0
Remove EIP712 streaming
cedelavergne-ledger Jul 10, 2025
9e607cc
Remove useless strings.tmp.tmp2
cedelavergne-ledger Jul 10, 2025
b24a0f3
Adapt client to EIP712 without streaming
cedelavergne-ledger Jul 11, 2025
daddfad
Update EIP712 tests
cedelavergne-ledger Jul 11, 2025
7248275
Adapt Tx Check
cedelavergne-ledger Jul 11, 2025
a914f6a
Align fuzzer
cedelavergne-ledger Jul 11, 2025
ce03483
Update snapshots
cedelavergne-ledger Jul 11, 2025
a09ebe8
Update PKIClient for physical backends
cedelavergne-ledger Jul 16, 2025
c59cc36
Merge pull request #838 from LedgerHQ/cev/B2CA-2151_remove-eip712-str…
cedelavergne-ledger Jul 18, 2025
dbd7068
Add Safe Account feature
cedelavergne-ledger Jun 20, 2025
b9c3086
Adapt fuzzing
cedelavergne-ledger Jun 20, 2025
7cf0453
Adapt client to Safe
cedelavergne-ledger Jun 20, 2025
1cdf6cd
Add Safe ragger test
cedelavergne-ledger Jun 20, 2025
5c7cfbc
Update snapshots
cedelavergne-ledger Jul 4, 2025
d12016b
Merge pull request #823 from LedgerHQ/cev/B2CA-2174_safe-account
cedelavergne-ledger Jul 18, 2025
88b690d
Fix handling of GCS slices
apaillier-ledger Jul 28, 2025
bc5b1e9
Fix handling of GCS ContainerPath FROM
apaillier-ledger Jul 28, 2025
d79574f
Merge pull request #843 from LedgerHQ/fix/apa/gcs_regressions
apaillier-ledger Jul 28, 2025
151324d
[auto-update] Update Ragger snapshots (#847)
apaillier-ledger Aug 4, 2025
a148771
Fix GCS handling of dynamic leaves of size 0
apaillier-ledger Aug 5, 2025
e711fa4
Merge pull request #848 from LedgerHQ/fix/apa/gcs_empty_bytes
apaillier-ledger Aug 5, 2025
bbc7579
🐛 (clear-signing): Fix proxy info for GCS
mbertin-ledger Jul 31, 2025
0168e45
Fix proxy info for EIP-712
apaillier-ledger Aug 4, 2025
8b7c235
Fix proxy ragger tests
apaillier-ledger Aug 4, 2025
bc15087
Change PKI key usage for proxy info to TRUSTED_NAME
apaillier-ledger Aug 5, 2025
afc93dc
Merge pull request #846 from LedgerHQ/fix/apa/proxy_info
apaillier-ledger Aug 5, 2025
2286e2f
Merge remote-tracking branch 'origin/master' into develop
apaillier-ledger Aug 7, 2025
60564d9
Improve valground output with Global Max summary and colors
cedelavergne-ledger Jul 11, 2025
7af743d
Add instrumentation for other memory allocation/free functions
cedelavergne-ledger Jul 11, 2025
3b73a16
Add test workflow for memory leaks
cedelavergne-ledger Jul 15, 2025
041f7e8
Fix few memory leaks
cedelavergne-ledger Jul 15, 2025
06b4dd5
VALGROUND
cedelavergne-ledger Aug 12, 2025
f59a385
MEMORY LEAKS
cedelavergne-ledger Aug 12, 2025
c4684ec
INSTRUMENTATION
cedelavergne-ledger Aug 12, 2025
3833264
Merge pull request #839 from LedgerHQ/cev/memory
cedelavergne-ledger Aug 14, 2025
b12f7c6
Merge pull request #815 from iotexproject/fix_icons
apaillier-ledger Aug 14, 2025
5ec1e3a
Merge remote-tracking branch 'origin/master' into develop
apaillier-ledger Aug 27, 2025
92e3ddb
Remove useless snapshots
cedelavergne-ledger Aug 8, 2025
1507874
Fix tools to include the payload data length
cedelavergne-ledger Aug 8, 2025
6d00ed4
Adapted gen_networks glyphs size depending on target
apaillier-ledger Jul 28, 2025
7ae0f49
Add dbg_whitelist use-case
cedelavergne-ledger Aug 8, 2025
b1b84c8
Port Apex
apaillier-ledger Jul 28, 2025
bbcf045
Add 48px glyphs
cedelavergne-ledger Aug 7, 2025
7cb9d64
Add 32px icons
cedelavergne-ledger Aug 7, 2025
f12c778
Adapt client to Apex
cedelavergne-ledger Aug 8, 2025
751380e
Adapt tests to Apex
cedelavergne-ledger Aug 8, 2025
022ffb0
Replace outdated plugin guide links
tdejoigny-ledger Sep 4, 2025
fb1e2e3
Add Apex_P snapshots
cedelavergne-ledger Aug 8, 2025
e4891dd
Merge pull request #853 from LedgerHQ/cev/apex_port
apaillier-ledger Sep 5, 2025
418e057
Merge pull request #854 from LedgerHQ/tdj/update_doc
tdejoigny-ledger Sep 8, 2025
7820917
Update Ethereum client changelog
tdejoigny-ledger Sep 5, 2025
c66c7b5
fix typo
tdejoigny-ledger Sep 8, 2025
11c21e2
Merge pull request #855 from LedgerHQ/tdj/publish_new_client
tdejoigny-ledger Sep 8, 2025
6e154ef
update plugin sdk (apex support)
tdejoigny-ledger Sep 9, 2025
b606fb0
Merge pull request #856 from LedgerHQ/tdj/update_plugin_sdk
tdejoigny-ledger Sep 9, 2025
d041164
[auto-update] Update Ragger snapshots
github-actions[bot] Sep 16, 2025
a160fba
Merge pull request #859 from LedgerHQ/auto/update_snapshots-6d40e830
apaillier-ledger Sep 17, 2025
6ed064c
Added missing GCS functions to the Python client
apaillier-ledger Sep 12, 2025
8e32421
Migrated GCS Ragger tests to new functions from Python client
apaillier-ledger Sep 12, 2025
80b8b1c
Removed explicit PARAM_TYPE from Field class in Python client
apaillier-ledger Jul 25, 2025
2517665
Nested GCS documentation/specifications
apaillier-ledger Jul 25, 2025
c24feca
Implemented the PARAM_CALLDATA enabled nested calldata parsing
apaillier-ledger Jun 27, 2025
943bd41
Added PARAM_CALLDATA support to Python client
apaillier-ledger Sep 16, 2025
41d6b0a
Added check for unprocessed TX contexts
apaillier-ledger Sep 15, 2025
661bb84
Added check for empty calldata nested TX
apaillier-ledger Sep 16, 2025
99ae750
Added nested GCS ragger tests
apaillier-ledger Sep 16, 2025
67dcfd8
Fixed fuzzing
apaillier-ledger Sep 17, 2025
30847cd
Simplified loop to compute size of a list by using flist_size
apaillier-ledger Aug 20, 2025
a474f59
Simplified EIP-712 field length handling in Python client
apaillier-ledger Aug 26, 2025
7ee76c7
Fixed Python client not ordering EIP-712 type fields
apaillier-ledger Aug 21, 2025
a17835d
Calldata EIP-712 filters specifications
apaillier-ledger Aug 8, 2025
98820f1
Implemented new calldata EIP-712 filters
apaillier-ledger Sep 18, 2025
30465c7
Added new calldata EIP-712 filters to Python client
apaillier-ledger Sep 16, 2025
859d18c
Added GCS in EIP-712 ragger tests
apaillier-ledger Sep 16, 2025
190a4df
Merge pull request #858 from LedgerHQ/feat/apa/multisig
apaillier-ledger Sep 18, 2025
4fcc078
Remove caution notes from tlv_structs.md
tdejoigny-ledger Sep 12, 2025
c63c66a
Merge pull request #857 from LedgerHQ/tdj/update_doc
apaillier-ledger Sep 18, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
18 changes: 18 additions & 0 deletions .github/workflows/build_and_functional_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,21 @@ jobs:
additional_app_binaries_artifact_dir: ./tests/ragger/.test_dependencies/clone/build/
test_options: "--setup lib_mode"
regenerate_snapshots: ${{ inputs.golden_run == 'Open a PR' }}

build_mem_app:
name: Build Memory application using the reusable workflow
uses: LedgerHQ/ledger-app-workflows/.github/workflows/reusable_build.yml@v1
with:
upload_app_binaries_artifact: "memory_elfs"
flags: "memory_profiling"
run_for_devices: '["nanox"]'

ragger_mem_tests:
name: Run Memory tests using the reusable workflow
needs: build_application
uses: LedgerHQ/ledger-app-workflows/.github/workflows/reusable_ragger_tests.yml@v1
with:
download_app_binaries_artifact: "memory_elfs"
test_options: " -s 2>&1 | tools/valground.py -q"
run_for_devices: '["nanox"]'
upload_snapshots_on_failure: false
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## [1.19.0](../../compare/1.18.1...1.19.0) - 2025-xx-xx

## [1.18.1](../../compare/1.18.0...1.18.1) - 2025-08-27

### Fixed
Expand Down
28 changes: 16 additions & 12 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -36,23 +36,23 @@ endif
include ./makefile_conf/chain/$(CHAIN).mk

APPVERSION_M = 1
APPVERSION_N = 18
APPVERSION_P = 1
APPVERSION = $(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)
APPVERSION_N = 19
APPVERSION_P = 0
APPVERSION = $(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)-dev

# Application source files
APP_SOURCE_PATH += src src_features src_plugins src_nbgl
APP_SOURCE_FILES += $(filter-out ./ethereum-plugin-sdk/src/main.c, $(wildcard ./ethereum-plugin-sdk/src/*.c))
INCLUDES_PATH += ./ethereum-plugin-sdk/src

ifeq ($(TARGET_NAME),$(filter $(TARGET_NAME),TARGET_STAX TARGET_FLEX))
NETWORK_ICONS_FILE = $(GEN_SRC_DIR)/net_icons.gen.c
NETWORK_ICONS_DIR = $(shell dirname "$(NETWORK_ICONS_FILE)")
ifeq ($(TARGET_NAME),$(filter $(TARGET_NAME),TARGET_STAX TARGET_FLEX TARGET_APEX_M TARGET_APEX_P))
NETWORK_ICONS_FILE = $(GEN_SRC_DIR)/net_icons.gen.c
NETWORK_ICONS_DIR = $(shell dirname "$(NETWORK_ICONS_FILE)")

$(NETWORK_ICONS_FILE):
$(shell python3 tools/gen_networks.py "$(NETWORK_ICONS_DIR)")
$(NETWORK_ICONS_FILE):
$(shell python3 tools/gen_networks.py "$(NETWORK_ICONS_DIR)")

APP_SOURCE_FILES += $(NETWORK_ICONS_FILE)
APP_SOURCE_FILES += $(NETWORK_ICONS_FILE)
endif

# Application icons following guidelines:
Expand All @@ -61,21 +61,25 @@ ICON_NANOX = icons/nanox_app_chain_$(CHAIN_ID).gif
ICON_NANOSP = icons/nanox_app_chain_$(CHAIN_ID).gif
ICON_STAX = icons/stax_app_chain_$(CHAIN_ID).gif
ICON_FLEX = icons/flex_app_chain_$(CHAIN_ID).gif
ICON_APEX_M = icons/apex_app_chain_$(CHAIN_ID).gif
ICON_APEX_P = icons/apex_app_chain_$(CHAIN_ID).gif

#prepare hsm generation
ifeq ($(TARGET_NAME),$(filter $(TARGET_NAME),TARGET_STAX TARGET_FLEX))
DEFINES += ICONGLYPH=C_chain_$(CHAIN_ID)_64px
DEFINES += ICONBITMAP=C_chain_$(CHAIN_ID)_64px_bitmap
DEFINES += ICONHOME=C_chain_$(CHAIN_ID)_64px
else
ifeq ($(TARGET_NAME),$(filter $(TARGET_NAME),TARGET_NANOX TARGET_NANOS2))
else ifeq ($(TARGET_NAME),$(filter $(TARGET_NAME), TARGET_APEX_M TARGET_APEX_P))
DEFINES += ICONGLYPH=C_chain_$(CHAIN_ID)_48px
DEFINES += ICONBITMAP=C_chain_$(CHAIN_ID)_48px_bitmap
DEFINES += ICONHOME=C_chain_$(CHAIN_ID)_48px
else ifeq ($(TARGET_NAME),$(filter $(TARGET_NAME),TARGET_NANOX TARGET_NANOS2))
DEFINES += ICONGLYPH=C_chain_$(CHAIN_ID)_14px
DEFINES += ICONBITMAP=C_chain_$(CHAIN_ID)_14px_bitmap

ICON_HOME_NANO = glyphs/home_chain_$(CHAIN_ID)_14px.gif
DEFINES += ICONHOME=C_home_chain_$(CHAIN_ID)_14px
endif
endif

# Don't define plugin function in the plugin SDK
DEFINES += IS_NOT_A_PLUGIN
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@

## About the project

Ethereum wallet application framework for Ledger Nano S, Ledger Nano S Plus, Ledger Nano X, Ledger Flex and Ledger Stax.
Ethereum wallet application framework for Ledger devices.
Ledger Blue is not maintained anymore, but the app can still be compiled for this target using the branch [`blue-final-release`](https://github.com/LedgerHQ/app-ethereum/tree/blue-final-release).

## Documentation
Expand All @@ -54,9 +54,7 @@ To compile it and load it on a device, please check out our [developer portal](h
We have the concept of plugins in the ETH app.
Find the documentations here:

- [Blog Ethereum plugins](https://blog.ledger.com/ethereum-plugins/)
- [Ethereum application Plugins : Technical Specifications](https://github.com/LedgerHQ/app-ethereum/blob/master/doc/ethapp_plugins.asc)
- [Plugin guide](https://hackmd.io/300Ukv5gSbCbVcp3cZuwRQ)
- [Plugin guide](https://ethereum-plugin-sdk.ledger.com)
- [Boilerplate plugin](https://github.com/LedgerHQ/app-plugin-boilerplate)

## Quick start guide
Expand Down Expand Up @@ -153,6 +151,8 @@ You can choose which device to compile and load for by setting the `BOLOS_SDK` e
- `BOLOS_SDK=$NANOX_SDK`
- `BOLOS_SDK=$NANOSP_SDK`
- `BOLOS_SDK=$STAX_SDK`
- `BOLOS_SDK=$FLEX_SDK`
- `BOLOS_SDK=$APEX_P_SDK`

### Loading on a physical device

Expand Down
6 changes: 6 additions & 0 deletions client/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.6.0] - 2025-09-05

### Added

- Support for Apex devices

## [0.5.0] - 2025-06-30

### Added
Expand Down
92 changes: 86 additions & 6 deletions client/src/ledger_app_clients/ethereum/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from .status_word import StatusWord
from .ledger_pki import PKIClient, PKIPubKeyUsage
from .dynamic_networks import DynamicNetwork
from .safe import SafeAccount, AccountType


class TrustedNameType(IntEnum):
Expand All @@ -35,6 +36,12 @@ class TrustedNameSource(IntEnum):
DNS = 0x05


class EIP712CalldataParamPresence(IntEnum):
NONE = 0x00
PRESENT_FILTERED = 0x01
PRESENT_VERIFYING_CONTRACT = 0x02


class SignMode(IntEnum):
BASIC = 0x00
STORE = 0x01
Expand All @@ -51,7 +58,7 @@ def __init__(self, backend: BackendInterface):
def _exchange_async(self, payload: bytes):
return self._backend.exchange_async_raw(payload)

def _exchange(self, payload: bytes):
def _exchange(self, payload: bytes) -> RAPDU:
return self._backend.exchange_raw(payload)

def response(self) -> Optional[RAPDU]:
Expand Down Expand Up @@ -154,6 +161,60 @@ def eip712_filtering_trusted_name(self,
sig,
discarded))

def eip712_filtering_calldata_info(self,
index: int,
value_filter_flag: bool,
callee_filter_flag: int,
chain_id_filter_flag: bool,
selector_filter_flag: bool,
amount_filter_flag: bool,
spender_filter_flag: int,
sig: bytes):
return self._exchange(self._cmd_builder.eip712_filtering_calldata_info(index,
value_filter_flag,
callee_filter_flag,
chain_id_filter_flag,
selector_filter_flag,
amount_filter_flag,
spender_filter_flag,
sig))

def eip712_filtering_calldata_value(self,
index: int,
sig: bytes,
discarded: bool):
return self._exchange(self._cmd_builder.eip712_filtering_calldata_value(index, sig, discarded))

def eip712_filtering_calldata_callee(self,
index: int,
sig: bytes,
discarded: bool):
return self._exchange(self._cmd_builder.eip712_filtering_calldata_callee(index, sig, discarded))

def eip712_filtering_calldata_chain_id(self,
index: int,
sig: bytes,
discarded: bool):
return self._exchange(self._cmd_builder.eip712_filtering_calldata_chain_id(index, sig, discarded))

def eip712_filtering_calldata_selector(self,
index: int,
sig: bytes,
discarded: bool):
return self._exchange(self._cmd_builder.eip712_filtering_calldata_selector(index, sig, discarded))

def eip712_filtering_calldata_amount(self,
index: int,
sig: bytes,
discarded: bool):
return self._exchange(self._cmd_builder.eip712_filtering_calldata_amount(index, sig, discarded))

def eip712_filtering_calldata_spender(self,
index: int,
sig: bytes,
discarded: bool):
return self._exchange(self._cmd_builder.eip712_filtering_calldata_spender(index, sig, discarded))

def eip712_filtering_raw(self, name: str, sig: bytes, discarded: bool):
return self._exchange_async(self._cmd_builder.eip712_filtering_raw(name, sig, discarded))

Expand All @@ -175,16 +236,19 @@ def serialize_tx(self, tx_params: dict) -> tuple[bytes, bytes]:
return encoded_tx, tx_hash

def sign(self,
bip32_path: str,
tx_params: dict,
bip32_path: Optional[str] = None,
tx_params: Optional[dict] = None,
mode: SignMode = SignMode.BASIC):
tx, _ = self.serialize_tx(tx_params)
chunks = self._cmd_builder.sign(bip32_path, tx, mode)
if tx_params is None:
tx = None
else:
tx, _ = self.serialize_tx(tx_params)
chunks = self._cmd_builder.sign(mode, bip32_path, tx)
for chunk in chunks[:-1]:
self._exchange(chunk)
return self._exchange_async(chunks[-1])

def get_challenge(self):
def get_challenge(self) -> RAPDU:
return self._exchange(self._cmd_builder.get_challenge())

def get_public_addr(self,
Expand Down Expand Up @@ -420,6 +484,12 @@ def provide_transaction_info(self, payload: bytes) -> RAPDU:
self._exchange(chunk)
return self._exchange(chunks[-1])

def provide_transaction_field_desc(self, payload: bytes) -> RAPDU:
chunks = self._cmd_builder.provide_transaction_field_desc(payload)
for chunk in chunks[:-1]:
self._exchange(chunk)
return self._exchange(chunks[-1])

def opt_in_tx_simulation(self):
return self._exchange_async(self._cmd_builder.opt_in_tx_simulation())

Expand Down Expand Up @@ -454,3 +524,13 @@ def sign_eip7702_authorization(self, bip32_path: str, auth_params: TxAuth7702):
for chunk in chunks[:-1]:
self._exchange(chunk)
return self._exchange_async(chunks[-1])

def provide_safe_account(self, safe_params: SafeAccount):
# Send ledgerPKI certificate - only for SAFE accounts
if safe_params.account_type == AccountType.SAFE:
self.pki_client.send_certificate(PKIPubKeyUsage.PUBKEY_USAGE_SAFE_ACCOUNT)

chunks = self._cmd_builder.provide_safe_account(safe_params.serialize(), safe_params.account_type)
for chunk in chunks[:-1]:
self._exchange(chunk)
return self._exchange_async(chunks[-1])
Loading
Loading