commit 4a9bd974c2e7697210ed5987bb8c67542ab4bf7e
parent 4231d8648b77b407743a186b3cf8bbfed360ba2b
Author: Joris Hartog <jorishartog@hotmail.com>
Date: Wed, 19 Aug 2026 15:54:23 +0200
Document mainnet candidate rehearsal
Diffstat:
3 files changed, 151 insertions(+), 15 deletions(-)
diff --git a/README.md b/README.md
@@ -121,7 +121,7 @@ Use your iuna wallet address as the worker username. Accepted shares become PoW
## Operator Docs
-- [Starting the genesis node](docs/genesis.md)
+- [Genesis and candidate rehearsal](docs/genesis.md)
- [Operator failure playbooks](docs/operator-playbooks.md)
## Contributing
diff --git a/ROADMAP.md b/ROADMAP.md
@@ -51,7 +51,7 @@ These items are not protocol rules. They are the attack and reliability checks t
- [x] Multi-node in-memory simulation covers delayed gossip, withheld burn bundles, bundle equivocation, partitions, restarts, persistence reload, and convergence.
- [x] Long-running release-mode soak test runs with automatic burn/finalization, P2P sync, Stratum-disabled and Stratum-enabled nodes, and periodic node restarts.
- [x] Operator failure playbooks exist for stalled height, divergent tips, old snapshots, no burn committee signatures, recovery blocks, and corrupted local persistence.
-- [ ] Mainnet-candidate release rehearsal includes fresh genesis, published bootnodes, checksums, backup/restore instructions, and a no-reset stability window.
+- [x] Mainnet-candidate release rehearsal includes fresh genesis, published bootnodes, checksums, backup/restore instructions, and a no-reset stability window.
## Milestones
diff --git a/docs/genesis.md b/docs/genesis.md
@@ -1,39 +1,175 @@
-# Starting The Genesis Node
+# Genesis And Candidate Rehearsal
-This is operator documentation for bootstrapping a iuna devnet. Most users should join an existing seed node instead.
+This is operator documentation for bootstrapping a iuna devnet or mainnet-candidate network. Most users should join an existing bootnode instead of creating genesis.
-## Start Setup
+Keep the management UI bound to `127.0.0.1`. Only the P2P listener should be internet-facing.
-Start with a public P2P bind and a local-only management UI:
+## Candidate Manifest
+
+Before a mainnet-candidate reset, publish one manifest in the release notes or operator coordination channel:
+
+```text
+version:
+git commit:
+release tag:
+genesis operator:
+genesis start time:
+genesis hash:
+stability window:
+bootnodes:
+checksums:
+```
+
+Fill it with:
+
+- the exact release artifact version and git commit;
+- the release tag, once created;
+- the genesis operator and UTC start time;
+- the genesis hash after the first node starts;
+- the agreed no-reset stability window, for example one week;
+- every public bootnode as `<host>:<p2p-port>`;
+- a link or pasted copy of `downloads/SHA256SUMS`.
+
+Do not start the stability window until the fresh genesis exists, at least one published bootnode is reachable, and independent operators have verified the release checksums.
+
+## Release Artifacts
+
+Build and deploy from the candidate commit:
+
+```sh
+cargo test --locked
+cargo test --locked --release --test properties -- --ignored
+./deployment.sh <version>
+```
+
+The deployment script writes release packages to `downloads/` and creates `downloads/SHA256SUMS`.
+
+Verify the files before publishing them:
```sh
-cargo run -- --p2p 0.0.0.0:9444 --http 127.0.0.1:18661
+shasum -a 256 -c downloads/SHA256SUMS
```
-Open `http://127.0.0.1:18661`, set the wallet password, write down the recovery phrase, and finish setup.
+On Linux, `sha256sum -c downloads/SHA256SUMS` is equivalent.
+
+Publish the checksums with the release artifacts. A node operator should be able to download the artifact and verify it before starting a candidate node.
## Create Genesis
-Restart from a fresh chain database with `--genesis`:
+Genesis requires a fresh wallet path and a fresh chain database. Use a new data directory for the reset candidate:
```sh
-cargo run -- --genesis --p2p 0.0.0.0:9444 --http 127.0.0.1:18661
+iuna --genesis --data-dir ~/.iuna-candidate-genesis --p2p 0.0.0.0:9444 --http 127.0.0.1:18661
```
+For local source builds, use the same flags through Cargo:
+
+```sh
+cargo run -- --genesis --data-dir ~/.iuna-candidate-genesis --p2p 0.0.0.0:9444 --http 127.0.0.1:18661
+```
+
+Open `http://127.0.0.1:18661`, set the wallet password if prompted, write down the recovery phrase, and finish setup. The process prints the wallet file, config file, chain database, management UI, and P2P listener on startup.
+
Genesis bootstraps the chain with a 1 IUNA burn, creates launch tickets for the first blocks, measures an initial VDF delay, and leaves the starter wallet with spendable IUNA for early testing.
-## Invite Nodes
+After startup, record the genesis hash from block `0` in the local UI or authenticated blocks endpoint:
-Give other node operators your public P2P address:
+```sh
+curl -s 'http://127.0.0.1:18661/api/blocks?before_height=1&limit=1'
+```
+
+If `curl` returns an auth response, collect the same value from the local UI or include the browser session cookie in the request.
+
+## Publish Bootnodes
+
+Publish at least one stable public P2P address:
```text
your-host.example:9444
```
-They can join with:
+For every bootnode:
+
+- allow inbound TCP traffic on the P2P port;
+- keep the HTTP management UI local-only;
+- publish the address operators should use with `--join`;
+- record the operator or owner in the candidate manifest.
+
+If a bootnode address changes during the stability window, treat it as an operational incident and update the manifest. Do not hide bootnode churn from candidate notes.
+
+## Join Nodes
+
+Start joining nodes with a fresh data directory and a published bootnode:
+
+```sh
+iuna --data-dir ~/.iuna-candidate --p2p 0.0.0.0:9445 --http 127.0.0.1:18661 --join your-host.example:9444
+```
+
+For a public peer, configure the reachable P2P listener and announce address in Settings or with CLI flags:
+
+```sh
+iuna --data-dir ~/.iuna-candidate --p2p 0.0.0.0:9445 --p2p-announce your-node.example:9445 --http 127.0.0.1:18661 --join your-host.example:9444
+```
+
+For a private wallet-only node, leave inbound P2P disabled in Settings and connect outbound to bootnodes.
+
+## Backup And Restore Drill
+
+Before the stability window starts, every core operator should prove they can restore their node.
+
+Back up:
+
+- `wallet.json`;
+- `config.json`;
+- `chain.sqlite3`;
+- `ui_data.sqlite3`;
+- the release artifact used to run the node;
+- the matching `SHA256SUMS` entry;
+- the wallet recovery phrase, stored separately from the machine.
+
+With the default data directory these files live under `~/.iuna`. With `--data-dir`, they live under that directory unless `--wallet` or `--chain-db` overrides the path.
+
+Restore rehearsal:
+
+1. Stop the node.
+2. Copy the backup into a new restore data directory.
+3. Start the same release binary with `--data-dir <restore-dir>`.
+4. Confirm the wallet address, local height, tip hash, and peers match expectations.
+5. If restoring without chain state, start with a published bootnode and let the node sync:
```sh
-cargo run -- --p2p 0.0.0.0:9445 --http 127.0.0.1:18661 --join your-host.example:9444
+iuna --data-dir <restore-dir> --join your-host.example:9444
```
-Keep the management UI bound to `127.0.0.1`.
+Never use `--genesis` to recover a node. `--genesis` is only for creating a fresh network.
+
+## No-Reset Stability Window
+
+For the mainnet-candidate rehearsal, treat unplanned resets as launch-blocking incidents unless they were explicitly scheduled before the window started.
+
+Start the window only after:
+
+- genesis hash and start time are published;
+- release artifacts and `SHA256SUMS` are published;
+- at least one bootnode is reachable from an independent host;
+- at least one non-genesis node has synced from the published bootnode;
+- backup/restore has been rehearsed by core operators.
+
+During the window, record daily:
+
+- height and tip hash from at least two nodes;
+- peer count and stale peer count;
+- last block age;
+- finalizer mode, recovery blocks, and fallback frequency;
+- mempool size and rejected block or transaction errors;
+- any node restart, bootnode change, restore, rollback, or manual chain deletion.
+
+Use [operator failure playbooks](operator-playbooks.md) for stalled height, divergent tips, old snapshots, missing burn committee signatures, recovery blocks, and corrupted local persistence.
+
+Exit criteria:
+
+- no unplanned reset during the full agreed window;
+- fresh nodes can still sync from genesis through published bootnodes;
+- release artifact checksums are independently verified;
+- backup/restore rehearsal has passed;
+- all launch-blocking incidents are fixed or explicitly deferred before mainnet.