Skip to content

Commit 3a81a54

Browse files
committed
fix(tokens): fail closed when the vetted token source is missing
The firmware token table is generated by this repository: lib/firmware/ CMakeLists.txt runs ethereum_tokens.py to produce ethereum_tokens.def, and unittests/firmware/coins.cpp reads the result. build() checked neither that the vetted ethereum-lists source was present nor that the scan produced anything. On an ordinary non-recursive checkout every add_tokens() call returns early, the table serializes zero rows, "0 of 0 kept" goes to stderr, and the firmware builds green with an empty token table -- the device would then show raw addresses and unknown decimals for every ERC-20 it should have recognized. Measured directly: the old path yields 0 tokens and raises nothing; the guard now raises. add_tokens() also returned out of the whole scan on the first entry that was not a regular file, where os.listdir order is arbitrary. That one is latent, not live: the currently pinned ethereum-lists has no non-file entries in any scanned directory, and the table is 1378 tokens with or without the change. It is corrected to `continue` so the hazard cannot arrive with a source bump. Restores the fail-closed form that already exists on the fork develop line. Adds the guarding regression test, which fails without this change.
1 parent 6e472fc commit 3a81a54

2 files changed

Lines changed: 25 additions & 1 deletion

File tree

keepkeylib/eth/ethereum_tokens.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,30 @@ def add_tokens(self, network):
2929
fullpath = os.path.join(dirname, filename)
3030

3131
if not os.path.isfile(fullpath):
32-
return
32+
continue
3333

3434
with open(fullpath, 'r') as f:
3535
token = json.load(f)
3636

3737
self.tokens.append(ETHToken(token, network))
3838

3939
def build(self):
40+
source = HERE + '/ethereum-lists/src/tokens'
41+
if not os.path.isdir(source):
42+
raise RuntimeError(
43+
'vetted ethereum-lists token source is missing; initialize '
44+
'submodules recursively before generating firmware tables')
45+
4046
with open(HERE + '/ethereum_networks.json', 'r') as f:
4147
networks = json.load(f)
4248

4349
for network in networks:
4450
self.add_tokens(network)
4551

52+
if not self.tokens:
53+
raise RuntimeError(
54+
'vetted ethereum-lists token source produced zero candidates')
55+
4656
def serialize_c(self, outf):
4757
# Flash budget: this table is the largest read-only symbol in the ARM
4858
# image. See token_policy for why it is capped rather than complete.

tests/test_token_table_generators.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"""
2424

2525
import ast
26+
import importlib
2627
import os
2728
import re
2829
import subprocess
@@ -58,6 +59,19 @@ def _vetted_source_present():
5859

5960
class TestTokenTableGenerators(unittest.TestCase):
6061

62+
def test_ethereum_tokens_missing_source_fails_closed(self):
63+
"""A non-recursive checkout must stop the firmware build, not emit 0 rows."""
64+
module = importlib.import_module('keepkeylib.eth.ethereum_tokens')
65+
original_here = module.HERE
66+
with tempfile.TemporaryDirectory() as tmp:
67+
module.HERE = tmp
68+
try:
69+
with self.assertRaisesRegex(
70+
RuntimeError, 'ethereum-lists token source is missing'):
71+
module.ETHTokenTable().build()
72+
finally:
73+
module.HERE = original_here
74+
6175
def _run(self, script):
6276
"""Run one generator into a temp file and return its rows."""
6377
with tempfile.TemporaryDirectory() as tmp:

0 commit comments

Comments
 (0)