Summary
operator::send_heartbeat (crates/gitlawb-node/src/operator.rs:118-145) connects and sends with no timeout at any stage, and the heartbeat loop's select! arm awaits it to completion (:160-180), so one hung chain-RPC call (silent TCP black hole, or a provider that accepts the tx but stalls receipt polling) stops the interval silently: no tick, no error log, no heartbeat again. Related: heartbeat_interval_hours (config.rs:172) is documented as "must be < 24h" but has no clap range or validate() check.
Impact
The node silently drops out of "currently active" on-chain after the 24h window - a liveness/penalty failure with no local signal. A misconfigured interval above 24h makes staying active impossible by construction.
Remediation
- Wrap the heartbeat send in a timeout and log + continue on expiry.
- Validate
heartbeat_interval_hours in validate()/clap range.
Proposed labels: kind:bug, crate:node, subsystem:attestation.
Summary
operator::send_heartbeat(crates/gitlawb-node/src/operator.rs:118-145) connects and sends with no timeout at any stage, and the heartbeat loop's select! arm awaits it to completion (:160-180), so one hung chain-RPC call (silent TCP black hole, or a provider that accepts the tx but stalls receipt polling) stops the interval silently: no tick, no error log, no heartbeat again. Related:heartbeat_interval_hours(config.rs:172) is documented as "must be < 24h" but has no clap range orvalidate()check.Impact
The node silently drops out of "currently active" on-chain after the 24h window - a liveness/penalty failure with no local signal. A misconfigured interval above 24h makes staying active impossible by construction.
Remediation
heartbeat_interval_hoursinvalidate()/clap range.Proposed labels: kind:bug, crate:node, subsystem:attestation.