Skip to main content

Module binding_check

Module binding_check 

Source
Expand description

Startup self-check: is the local iroh key the one bound on-chain? (#1034)

SlashJudge._checkRegistered resolves an accused node through CapacityBond.nodeIdOf, so slashability follows the binding, not the key the daemon happens to serve under. A node whose node.secret was replaced without a matching bindNodeId therefore keeps serving and keeps getting paid while its bond is unreachable — it is unslashable. Nothing else in the runtime notices: the node is healthy, its channels settle, and its peers simply stop routing to an id no longer in the staker set, which reads like ordinary churn.

That is the gap this check closes, and the reason it exists on the daemon at all rather than only in decdn node rotate-key. The command is written so the state is unreachable through it — the key file is committed only after the bind confirms — but the state is reachable around it, by an operator copying a key file, restoring the wrong backup, or running decdn key-gen --force in a data dir that was already registered.

§Advisory, deliberately

The result never blocks startup. A daemon that refused to boot on a mismatch would be brickable by a transient RPC failure, and — worse — unable to run during the very window an operator needs it up to diagnose and repair the binding. So the check reports: a WARN line at bring-up and a field on admin_v1_health, both naming the repair.

§Sampled once

The binding changes only by an explicit operator transaction, so this runs once during bring-up rather than per health poll — admin_v1_health is on the readiness path, and putting a chain round trip behind it would make every probe pay for a value that almost never moves.

Structs§

BindingReport
Outcome of the bring-up binding check, as carried into AdminState.

Functions§

check
Read CapacityBond.addressToNodeId(operator) and compare it with the key the daemon is about to serve under, logging the outcome.
classify
Classify a binding read. Pure so every arm is reachable from a unit test — the chain read that produces bound cannot be steered to these values from a fixture without deploying a contract per case.