autogenerate-rpc-examples.py: disable entropy for generation.
What changed, and why it matters
This commit changes Core Lightning's internal test tooling so that automatically generated RPC documentation examples use predictable randomness and a fixed clock time. It only affects test/example generation code, not the production Lightning node software that users run. There is no security issue here; it is a developer convenience change to make generated documentation reproducible.
No security action required. This is a benign test/tooling change.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch adds a no_entropy option to the pyln-testing LightningNode and NodeFactory classes. When enabled, it sets the CLN_DEV_ENTROPY_SEED environment variable to the node’s ID, causing test nodes to use deterministic entropy. It also sets CLN_DEV_SET_TIME=1738000000 in tests/autogenerate-rpc-examples.py so generated RPC examples have stable timestamps. These changes are confined to test infrastructure and the RPC example generator; no production code paths are modified.
Changed components
contrib/pyln-testing/pyln/testing/utils.pytests/autogenerate-rpc-examples.pyInspect captured patch +14 / −1
diff --git a/contrib/pyln-testing/pyln/testing/utils.py b/contrib/pyln-testing/pyln/testing/utils.py
index ff0886d..b40184c 100644
--- a/contrib/pyln-testing/pyln/testing/utils.py
+++ b/contrib/pyln-testing/pyln/testing/utils.py
@@ -935,6 +935,7 @@ class LightningNode(object):
executable=None,
bad_notifications=False,
old_hsmsecret=None,
+ no_entropy=False,
**kwargs):
self.bitcoin = bitcoind
self.executor = executor
@@ -946,6 +947,7 @@ class LightningNode(object):
self.allow_warning = allow_warning
self.db = db
self.lightning_dir = Path(lightning_dir)
+ self.no_entropy = no_entropy
# Assume successful exit
self.rc = 0
@@ -1000,6 +1002,8 @@ class LightningNode(object):
# Avoid test flakes cause by this option unless explicitly set.
if self.cln_version >= "v24.11":
self.daemon.opts.update({"autoconnect-seeker-peers": 0})
+ if no_entropy:
+ self.daemon.env["CLN_DEV_ENTROPY_SEED"] = str(node_id)
jsondir = Path(lightning_dir) / "plugin-io"
jsondir.mkdir()
@@ -1780,6 +1784,7 @@ class NodeFactory(object):
'start',
'gossip_store_file',
'old_hsmsecret',
+ 'no_entropy',
]
node_opts = {k: v for k, v in opts.items() if k in node_opt_keys}
cli_opts = {k: v for k, v in opts.items() if k not in node_opt_keys}
diff --git a/tests/autogenerate-rpc-examples.py b/tests/autogenerate-rpc-examples.py
index 857dab9..52b5aa7 100644
--- a/tests/autogenerate-rpc-examples.py
+++ b/tests/autogenerate-rpc-examples.py
@@ -451,6 +451,7 @@ def setup_test_nodes(node_factory, bitcoind):
'log-level': 'debug',
'broken_log': '.*',
'dev-bitcoind-poll': 3, # Default 1; increased to avoid rpc failures
+ 'no_entropy': True,
}.copy()
for i in range(6)
]
@@ -1322,6 +1323,7 @@ def generate_splice_examples(node_factory, bitcoind):
'allow_bad_gossip': True,
'broken_log': '.*',
'dev-bitcoind-poll': 3,
+ 'no_entropy': True,
}.copy()
for i in range(2)
]
@@ -1396,6 +1398,7 @@ def generate_channels_examples(node_factory, bitcoind, l1, l3, l4, l5):
'allow_bad_gossip': True,
'broken_log': '.*',
'dev-bitcoind-poll': 3,
+ 'no_entropy': True,
}.copy()
for i in range(2)
]
@@ -1446,6 +1449,7 @@ def generate_channels_examples(node_factory, bitcoind, l1, l3, l4, l5):
'allow_bad_gossip': True,
'broken_log': '.*',
'dev-bitcoind-poll': 3,
+ 'no_entropy': True,
}.copy()
for i in range(2)
]
@@ -1782,7 +1786,7 @@ def generate_backup_recovery_examples(node_factory, l4, l5, l6):
logger.info('Backup and Recovery Start...')
# New node l13 used for recover and exposesecret examples
- l13 = node_factory.get_node(options={'exposesecret-passphrase': "test_exposesecret"})
+ l13 = node_factory.get_node(options={'exposesecret-passphrase': "test_exposesecret"}, no_entropy=True)
update_example(node=l13, method='exposesecret', params={'passphrase': 'test_exposesecret'})
update_example(node=l13, method='exposesecret', params=['test_exposesecret', 'cln2'])
@@ -2102,6 +2106,10 @@ def test_generate_examples(node_factory, bitcoind, executor):
logger.warning(f'This test ignores {len(IGNORE_RPCS_LIST)} rpc methods: {IGNORE_RPCS_LIST}')
REGENERATING_RPCS = [rpc.strip() for rpc in os.getenv("REGENERATE").split(', ')] if os.getenv("REGENERATE") else ALL_RPC_EXAMPLES
list_missing_examples()
+
+ # We make sure everyone is on predicable time
+ os.environ['CLN_DEV_SET_TIME'] = '1738000000'
+
l1, l2, l3, l4, l5, l6, c12, c23, c25 = setup_test_nodes(node_factory, bitcoind)
c23_2, c23res2, c34_2, inv_l11, inv_l21, inv_l22, inv_l31, inv_l32, inv_l34 = generate_transactions_examples(l1, l2, l3, l4, l5, c25, bitcoind)
rune_l21 = generate_runes_examples(l1, l2, l3)
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.