Skip to content

Commit ea79f77

Browse files
Merge pull request #935 from LedgerHQ/cev/B2CA-2477_formatters
B2CA-2477: Add new formatters
2 parents d39bfc6 + 40f5f03 commit ea79f77

207 files changed

Lines changed: 3164 additions & 165 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/unit_tests.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: Unit testing with Codecov coverage checking
2+
3+
on:
4+
workflow_dispatch:
5+
push:
6+
branches:
7+
- develop
8+
- master
9+
pull_request:
10+
11+
jobs:
12+
job_unit_test:
13+
name: Call Ledger unit_test
14+
uses: LedgerHQ/ledger-app-workflows/.github/workflows/reusable_unit_tests.yml@v1
15+
secrets: inherit
16+
with:
17+
test_directory: tests/unit
18+
additional_packages: pkg-config libbsd-dev

client/src/ledger_app_clients/ethereum/gcs.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ class ParamType(IntEnum):
9999
TRUSTED_NAME = 0x08
100100
CALLDATA = 0x09
101101
TOKEN = 0x0a
102+
NETWORK = 0x0b
102103

103104

104105
class TypeFamily(IntEnum):
@@ -219,6 +220,7 @@ class ContainerPath(IntEnum):
219220
FROM = 0x00
220221
TO = 0x01
221222
VALUE = 0x02
223+
CHAIN_ID = 0x03
222224

223225

224226
class Value(TlvSerializable):
@@ -544,27 +546,63 @@ def serialize(self) -> bytes:
544546
return payload
545547

546548

549+
class ParamNetwork(FieldParam):
550+
version: int
551+
value: Value
552+
553+
def __init__(self, version: int, value: Value):
554+
self.type = ParamType.NETWORK
555+
self.version = version
556+
self.value = value
557+
558+
def serialize(self) -> bytes:
559+
payload = bytearray()
560+
payload += self.serialize_field(0x00, self.version)
561+
payload += self.serialize_field(0x01, self.value.serialize())
562+
return payload
563+
564+
547565
class FieldTag(IntEnum):
548566
VERSION = 0x00
549567
NAME = 0x01
550568
PARAM_TYPE = 0x02
551569
PARAM = 0x03
552570

553571

572+
class VisibleType(IntEnum):
573+
ALWAYS = 0x00
574+
MUST_BE = 0x01
575+
IF_NOT_IN = 0x02
576+
577+
554578
class Field(TlvSerializable):
555579
version: int
556580
name: str
557581
param: FieldParam
582+
visible: Optional[VisibleType]
583+
constraints: Optional[list[bytes]]
558584

559-
def __init__(self, version: int, name: str, param: FieldParam):
585+
def __init__(self,
586+
version: int,
587+
name: str,
588+
param: FieldParam,
589+
visible: Optional[VisibleType] = None,
590+
constraints: Optional[list[bytes]] = None):
560591
self.version = version
561592
self.name = name
562593
self.param = param
594+
self.visible = visible
595+
self.constraints = constraints
563596

564597
def serialize(self) -> bytes:
565598
payload = bytearray()
566599
payload += self.serialize_field(FieldTag.VERSION, self.version)
567600
payload += self.serialize_field(FieldTag.NAME, self.name)
568601
payload += self.serialize_field(FieldTag.PARAM_TYPE, self.param.type)
569602
payload += self.serialize_field(FieldTag.PARAM, self.param.serialize())
603+
if self.visible is not None:
604+
payload += self.serialize_field(0x04, self.visible)
605+
if self.constraints is not None:
606+
for constraint in self.constraints:
607+
payload += self.serialize_field(0x05, constraint)
570608
return payload

doc/tlv_structs.md

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,21 @@
6464
It contains no signature since the signed TRANSACTION_INFO struct already has a hash of all the FIELD
6565
structs, which attests of the authenticity, order and completeness of all FIELD structs.
6666

67-
| Name | Tag | Payload type | Description | Optional | Source / value |
68-
|------------|------|--------------|----------------------------|----------|------------------------------------------------------------|
69-
| VERSION | 0x00 | uint8 | struct version | | constant: `0x0` |
70-
| NAME | 0x01 | char[] | field display name (ASCII) | | `$.display.formats.<format id>.fields.[<field id>].label` |
71-
| PARAM_TYPE | 0x02 | uint8 | `ParamType` | | `$.display.formats.<format id>.fields.[<field id>].params` |
72-
| PARAM | 0x03 | PARAM_* | | | `$.display.formats.<format id>.fields.[<field id>].params` |
67+
| Name | Tag | Payload type | Description | Optional | Source / value |
68+
|------------|------|--------------|-------------------------------------|----------|-------------------------------------------------------------|
69+
| VERSION | 0x00 | uint8 | struct version | | constant: `0x0` |
70+
| NAME | 0x01 | char[] | field display name (ASCII) | | `$.display.formats.<format id>.fields.[<field id>].label` |
71+
| PARAM_TYPE | 0x02 | uint8 | `ParamType` | | `$.display.formats.<format id>.fields.[<field id>].params` |
72+
| PARAM | 0x03 | PARAM_* | | | `$.display.formats.<format id>.fields.[<field id>].params` |
73+
| VISIBLE | 0x04 | uint8 | `VisibleType` visibility condition | x | `$.display.formats.<format id>.fields.[<field id>].visible` |
74+
| CONSTRAINT | 0x05 | uint8[] | constraint value (raw bytes) | x | `$.display.formats.<format id>.fields.[<field id>].visible` |
75+
76+
> __Notes__:
77+
>
78+
> - `VISIBLE` defaults to `ALWAYS` (0x00) if not present
79+
> - `VISIBLE` can be present only once and should be served before any `CONSTRAINT`
80+
> - `CONSTRAINT` is only present when `VISIBLE` is `MUST_BE` or `IF_NOT_IN`
81+
> - `CONSTRAINT` tag can appear multiple times for multiple allowed/excluded values (OR semantics). The limit is 5 constraints.
7382
7483
with `ParamType` enum defined as:
7584

@@ -86,6 +95,15 @@ with `ParamType` enum defined as:
8695
| TRUSTED_NAME | 0x08 |
8796
| CALLDATA | 0x09 |
8897
| TOKEN | 0x0a |
98+
| NETWORK | 0x0b |
99+
100+
with `VisibleType` enum defined as:
101+
102+
| Name | Value | Description |
103+
|-----------|-------|--------------------------------------------------------------------------------------------|
104+
| ALWAYS | 0x00 | Field is always displayed (default) |
105+
| MUST_BE | 0x01 | Field not displayed but must match one of the constraint values, otherwise tx is rejected |
106+
| IF_NOT_IN | 0x02 | Field is displayed only if value is NOT in the constraint list |
89107

90108
### PARAM_RAW
91109

@@ -212,6 +230,20 @@ and `TrustedNameSource` enum defined as:
212230

213231
This struct can contain `NATIVE_CURRENCY` multiple times for multiple addresses.
214232

233+
### PARAM_NETWORK
234+
235+
| Name | Tag | Payload type | Description | Optional | Source / value |
236+
|---------|------|--------------|-----------------------------|----------|----------------------------------------------------------|
237+
| VERSION | 0x00 | uint8 | struct version | | constant: `0x0` |
238+
| VALUE | 0x01 | VALUE | reference to chain ID value | | `$.display.formats.<format id>.fields.[<field id>].path` |
239+
240+
The device looks up the network name from the chain ID using:
241+
242+
1. Dynamic networks
243+
2. Built-in networks
244+
245+
If the network is not found, the device falls back to displaying the raw chain ID.
246+
215247
### VALUE
216248

217249
| Name | Tag | Payload type | Description | Optional | Source / value |
@@ -238,26 +270,14 @@ with `TypeFamily` enum defined as:
238270

239271
and `ContainerPath` enum defined as:
240272

241-
| Name | Value |
242-
|-------|-------|
243-
| FROM | 0x00 |
244-
| TO | 0x01 |
245-
| VALUE | 0x02 |
246-
247-
The TLV payload must include exactly one of `DATA_PATH`, `CONTAINER_PATH` or `CONSTANT`.
248-
249-
with `TypeFamily` enum defined as:
273+
| Name | Value |
274+
|----------|-------|
275+
| FROM | 0x00 |
276+
| TO | 0x01 |
277+
| VALUE | 0x02 |
278+
| CHAIN_ID | 0x03 |
250279

251-
| Name | Value |
252-
|---------|-------|
253-
| UINT | 0x01 |
254-
| INT | 0x02 |
255-
| UFIXED | 0x03 |
256-
| FIXED | 0x04 |
257-
| ADDRESS | 0x05 |
258-
| BOOL | 0x06 |
259-
| BYTES | 0x07 |
260-
| STRING | 0x08 |
280+
> __Note__: The TLV payload must include exactly one of `DATA_PATH`, `CONTAINER_PATH` or `CONSTANT`.
261281
262282
### DATA_PATH
263283

src/features/generic_tx_parser/cmd_field.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,13 @@ static bool handle_tlv_payload(const uint8_t *payload, uint16_t size) {
1717
ctx.field = &field;
1818
parsing_ret = tlv_parse(payload, size, (f_tlv_data_handler) &handle_field_struct, &ctx);
1919
hashing_ret = cx_hash_no_throw(get_fields_hash_ctx(), 0, payload, size, NULL, 0) == CX_OK;
20-
if (!parsing_ret || !hashing_ret) return false;
20+
if (!parsing_ret || !hashing_ret) {
21+
cleanup_field_constraints(&field);
22+
return false;
23+
}
2124
if (!verify_field_struct(&ctx)) {
2225
PRINTF("Error: could not verify the field struct!\n");
26+
cleanup_field_constraints(&field);
2327
return false;
2428
}
2529
if (!format_field(&field)) {

0 commit comments

Comments
 (0)