Signers
The calendar signs its anchor transactions with one key at a time. We call each key's run a signer epoch, number the epochs from 1 and list every one the calendar has used at /v1/signers.
The Signer List
Reading https://etchd.app/v1/signers
All times are UTC. firstTick is the first tick the key was able to anchor, the oldest one that no transaction held when the key took over. lastTick is the highest tick it anchored. For the key that signs now, both end fields stay empty.
Epoch 1 is the launch key, a temporary hot wallet we funded with 0.1 ETC to sign until we rotate to a long-term key, and whichever key is signing, the signer refuses to spend more than 0.05 ETC in one UTC day.
The Accepted Window
A verifier with the list looks up the sender of each anchor transaction. The key counts as known only when the anchor block's time falls inside its window, from 60 seconds before activeFrom to 900 seconds after activeTo, with no upper bound while the key is current. The 60 seconds allow for block times that run behind the calendar's clock, and the 900 seconds for a transaction still in flight when a key is retired.
A listed key used outside its window comes back as known: false with outsideWindow: true. A leaked key shows up this way once the calendar has rotated away from it, and its later transactions stop passing as ours.
The verifier enforces the list only when you pass the flag shown under Checking the Sender, and it applies the window by the rules of Signer Epochs in SPEC.md.
How Rotation Works
A rotation moves anchoring to a new key and changes no commitment. Old proofs verify as before, because tick headers and calldata carry no epoch.
- The operator makes the new key offline and installs it on the signer Worker as
ETCHD_SIGNER_KEY_NEXT. Nothing signs with it yet./v1/statusshows it assigner.next. - The new address is funded from the cold wallet. Rotation refuses a key that holds less than one day of spend, 0.033264 ETC.
- An admin call to
/v1/admin/rotatestops new batches, waits for the transaction in flight to be mined, reads the new key's balance and nonce from the calendar's four ETC RPCs (theETC_RPCSlist inpackages/worker/wrangler.jsonc) with a quorum of two, switches the signer and records the new epoch. If anything fails the old key keeps signing. - The new epoch appears here with an open end, and the next anchor transaction on Blockscout comes from the new address. Because each key counts its own nonces from 0, an anchor transaction is named by epoch and nonce, as in
/v1/anchors/2/0.
The old address keeps about 0.001 ETC for 30 days, because in that time the daily reorg audit can send an old-epoch transaction back to the mempool with its stored bytes and mining it again costs gas from that address.
If a key leaks, a watchdog halts anchoring and the rotation runs while halted, as The Anchor Key in the Trust Model describes. Operators run it by the steps in Key Rotation in DEPLOY.md, and the Anchor code is in packages/worker/src/anchor/anchor.ts.