Before an xOneRS validator signs a vote, a timeout, a proposal or a V1 seal, it writes and syncs a small safety record to disk. Only after the sync returns does a signature exist. The record only rises, it lives outside the chain files, and no chain operation can lower it. The design is ADR-010, whose status is still "proposed".

This post covers what the record holds, where it is, the write order and how upgrades keep it. For key handling, see key custody and seat rotation; for the upgrade runbook, see how to upgrade or roll back.

What does the safety record hold?

The record is 339 bytes (format version 2). Its fields, from ADR-010 section 3:

REFERENCE TABLEScroll to explore all columns →
Field Meaning
identity the validator address
seq a count of writes of this record, not a clock
highest_voted_round the highest round of a vote or a timeout
signed[vote], signed[timeout], signed[propose], signed[seal_v1] per type: the round and the 32-byte digest last signed
lock flag, lock QC the locked QC: hash, round, number
highest QC, highest TC the highest QC seen and the round of the highest TC
checksum keccak256 of the bytes before it

A record that fails its length, magic, version or checksum check is a refusal to sign. It is never reset to zero.

Where does the record live?

In <datadir>/xone/safety, in a file safety.rec of two 1,024-byte slots. One function, safety_file::dir, builds that path, and the producer uses it (safety_file.rs). Since PR #1001 (merged 2026-11-15), the test crates/xone-node/tests/safety_path.rs fails if the documented path differs from the function, if any document names the old datadir/safety form, or if the restore tool does not use xone/safety.

A write goes to the slot that does not hold the newest valid frame, then the file is synced. A torn write damages only the slot being written; the other slot holds the last acknowledged state. An exclusive flock on safety.rec keeps a second process on the same host out. There is no separate LOCK file.

What is the order before a signature?

ADR-010 section 6 fixes the order:

event -> consensus step -> intent (kind, round, digest)
      -> fence open?                 no: refuse
      -> decide(record, intent)      refuse: nothing written, nothing signed
      -> persist_intent(new record)  write + fsync
      -> Ack
      -> sign
      -> send

No signature exists before the Ack. Any error of a write or a sync stops signing: the process exits, and a restart in the same boot refuses. If the node crashes after the write and before the send, a retry of the same intent signs the same bytes again, because the signer is deterministic (RFC 6979). A different digest for the same round is refused.

Why is the record never lowered?

The record changes only through functions that raise it. xone-db has no function that writes, truncates or replaces it from the chain side. Unwind, SetHead, a datadir restore and a snapshot import do not touch <datadir>/xone/safety (ADR-010 section 5). After a chain rollback the record stays high, so the signer may refuse to vote in rounds it visits again. ADR-010 calls that the intended cost.

A copy of an old record from a backup is an operator action outside the node. The node cannot tell, so every start is treated as unproven: it waits a quiet window and watches for signatures of its own key before it signs.

How does an upgrade or a restore keep it?

The rollback step of the runbook uses ops/tools/xone-rollback-restore.sh. It stages the restored datadir, copies the current safety record over the restored one on a signer, keeps the failed datadir, and stops before the swap if a safety file is missing or fails to copy (upgrade-rollback.md). The older datadir/safety wording in the docs was tracked in issue #820 and is fixed.

What is still open?

ADR-010 section 12 lists questions for the owner, among them the quiet-window formula (120 s today), the two-slot file as the store form, a shared lease for failover, and who owns xone signer init. Section 8 says the quiet window is a wait with observation, not a lock across hosts: two hosts with one key are still possible, so the one-signer rule of the mint gate applies.

The collected competitor articles state no claim about a signer safety record, so this post has no comparison table.

Frequently asked questions

Where is the xOne safety record on disk?

In <datadir>/xone/safety/safety.rec, outside chain.mdbx and the segment files.

Can I restore the safety record from a backup?

Do not. An older record can allow a second signature for a round the key already signed. The rollback tool keeps the current record and restores only the chain data.

What happens if the disk fails during the write?

Signing stops. The process exits, and a restart in the same boot refuses, as ADR-005 section 9 requires for a failed sync.

Does the v0.1.0 release use the same path?

Yes. The v0.1.0 producer already opens <datadir>/xone/safety (producer.rs at the tag). PR #1001 on 2026-11-15 moved the path into one function and added the test that ties the documents to it.

Sources