hsmd: don't assert that our own locktime is > 0.
What changed, and why it matters
This commit fixes a crash in Core Lightning when a user sets 'watchtime-blocks' to 0. The crash came from an internal safety check (assertion) in the HSM (hardware security module) stub code that rejected a locktime of 0. The fix removes several 'fail fast' assertions in the stub HSM because, by design, that stub is meant to accept everything and let other parts of the code enforce policy. The change is described as safe for testing but not recommended for mainnet.
Treat as a bug-fix commit rather than a security vulnerability. Users should not set watchtime-blocks=0 on mainnet because it reduces the time window for penalty transactions. Operators should ensure they run a validating signer or HSM implementation (e.g., VLS) if they require strict policy enforcement.
Security signals we found
Removal of defensive assertions in HSM stub code
Crash fix triggered by a configuration value (watchtime-blocks=0)
Policy delegation from stub HSM to openingd / external signer
Test re-enabled from expected-fail to passing
Evidence from the diff
In hsmd/libhsmd.c, the handle_setup_channel stub removed assertions that channel_value > 0, funding_txid is non-zero, local_to_self_delay > 0, and remote_to_self_delay > 0. It also removed an unused mem_is_zero helper and an unused value_msat variable. The commit message states the stub HSM accepts everything by policy, and openingd (or a real HSM such as VLS) is responsible for policy enforcement. A previously xfail test, test_zero_locktime_blocks, is now enabled to verify the node works with watchtime-blocks=0.
Changed components
hsmd/libhsmd.ctests/test_misc.pyInspect captured patch +0 / −18
diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c
index 7ce12bc0..c013ec4a 100644
--- a/hsmd/libhsmd.c
+++ b/hsmd/libhsmd.c
@@ -352,15 +352,6 @@ static u8 *handle_new_channel(struct hsmd_client *c, const u8 *msg_in)
return towire_hsmd_new_channel_reply(NULL);
}
-static bool mem_is_zero(const void *mem, size_t len)
-{
- size_t i;
- for (i = 0; i < len; ++i)
- if (((const unsigned char *)mem)[i])
- return false;
- return true;
-}
-
/* ~This stub implementation is overriden by fully validating signers
* that need the unchanging channel parameters. */
static u8 *handle_setup_channel(struct hsmd_client *c, const u8 *msg_in)
@@ -377,7 +368,6 @@ static u8 *handle_setup_channel(struct hsmd_client *c, const u8 *msg_in)
struct pubkey remote_funding_pubkey;
u16 remote_to_self_delay;
u8 *remote_shutdown_script;
- struct amount_msat value_msat;
struct channel_type *channel_type;
if (!fromwire_hsmd_setup_channel(tmpctx, msg_in, &is_outbound,
@@ -394,13 +384,6 @@ static u8 *handle_setup_channel(struct hsmd_client *c, const u8 *msg_in)
/* Stub implementation */
- /* Fail fast if any values are uninitialized or obviously wrong. */
- assert(amount_sat_greater(channel_value, AMOUNT_SAT(0)));
- assert(amount_sat_to_msat(&value_msat, channel_value));
- assert(!mem_is_zero(&funding_txid, sizeof(funding_txid)));
- assert(local_to_self_delay > 0);
- assert(remote_to_self_delay > 0);
-
return towire_hsmd_setup_channel_reply(NULL);
}
diff --git a/tests/test_misc.py b/tests/test_misc.py
index 6f8db4c8..ed6ff389 100644
--- a/tests/test_misc.py
+++ b/tests/test_misc.py
@@ -4974,7 +4974,6 @@ def test_tracing(node_factory):
assert 'parentId' in res[0]
-@pytest.mark.xfail(strict=True)
def test_zero_locktime_blocks(node_factory, bitcoind):
"""Ensure our node "works" even if locktime set to 0."""
l1, l2, l3 = node_factory.line_graph(3, opts=[{}, {'watchtime-blocks': 0}, {}], wait_for_announce=True)
Why this scored 31/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.