Skip to content

Commit 1095bfe

Browse files
authored
docs: add Staking CLI page + unjail recovery cross-ref (#13)
Documents the new `sentrix staking …` subcommand shipped in sentrix-labs/ sentrix#749 (v2.2.22). Covers all four TX-based ops (register, add-self- stake, unjail, claim-rewards) with their fork dependencies, common arguments, and an end-to-end recovery walkthrough for the val3 case (jailed below MIN_SELF_STAKE, can't unjail plain). Also pins the ADD_SELF_STAKE_HEIGHT testnet activation height (5,800,000, scheduled 2026-05-30) and mainnet status (disabled, pending planned window). Updates tokenomics/staking.md to link to the new CLI page from the slashing section so operators landing on slashing docs find the recovery procedure inline. No URL changes — adds two new sections inside the existing docs/ operations and docs/tokenomics directories so the lowercase-dash URL convention from docs#11 stays intact.
1 parent c583022 commit 1095bfe

2 files changed

Lines changed: 124 additions & 1 deletion

File tree

docs/operations/staking-cli.md

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
# Staking CLI (`sentrix staking …`)
2+
3+
TX-based staking operations — the proper consensus-safe path for validator + delegator state changes. Use these instead of `sentrix validator unjail` / `force-unjail`, which mutate the stake registry directly in the database without updating the state trie and require a cluster-wide trie reconciliation to recover.
4+
5+
Every command here builds a signed transaction targeted at `PROTOCOL_TREASURY`, queues it in the local mempool, and lets the chain's normal `apply_block` path execute the op — so the state trie stays consistent on every peer that re-executes the block.
6+
7+
Shipped in **v2.2.22**.
8+
9+
## Common arguments
10+
11+
| Flag | Description |
12+
|---|---|
13+
| `--keystore <path>` | Path to the sender's Argon2id v2 keystore file. Password comes from the `SENTRIX_WALLET_PASSWORD` env var, or is read from stdin via a non-echoing prompt if the env var is unset. |
14+
| `--fee <sentri>` | Transaction fee in sentri (1 SRX = 100,000,000 sentri). Defaults to 10,000 sentri (0.0001 SRX) on every command. |
15+
16+
Run while the chain process for that node is stopped — the CLI takes an exclusive lock on `chain.db`. When the node starts again, the queued tx is gossiped via libp2p mempool and an active proposer includes it in the next block.
17+
18+
## `sentrix staking register`
19+
20+
Register the sender as a validator candidate. The wallet must hold at least `self_stake + fee` SRX. On apply, `self_stake` is escrowed into `PROTOCOL_TREASURY` and the sender enters the candidate pool; active set entry happens at the next epoch boundary if total stake ranks in the top 21.
21+
22+
```bash
23+
sentrix staking register \
24+
--keystore /path/to/my-validator.keystore \
25+
--self-stake 15000 \
26+
--commission-rate 1000 \
27+
--fee 10000
28+
```
29+
30+
| Argument | Meaning |
31+
|---|---|
32+
| `--self-stake` | Bonded SRX, whole units. Must be ≥ `MIN_SELF_STAKE` (15,000 SRX). |
33+
| `--commission-rate` | Basis points (1000 = 10%, max 10000 = 100%). |
34+
35+
After the tx applies, query `/staking/validators/<addr>` to confirm registration. Verify the entry's `is_active` flips to `true` at the next epoch (28,800 blocks ≈ 1 day at 1s blocks).
36+
37+
## `sentrix staking add-self-stake`
38+
39+
Top up the sender's `self_stake` by `--amount` SRX. The most common use is unblocking a jailed validator whose `self_stake` fell below `MIN_SELF_STAKE` after a downtime slash — the dispatcher's `unjail()` floor check rejects until the validator is back above the threshold.
40+
41+
```bash
42+
sentrix staking add-self-stake \
43+
--keystore /path/to/my-validator.keystore \
44+
--amount 15 \
45+
--fee 10000
46+
```
47+
48+
**Fork dependency:** `AddSelfStake` dispatch is gated by `ADD_SELF_STAKE_HEIGHT`. Defaults:
49+
50+
| Chain | Default activation | Notes |
51+
|---|---|---|
52+
| Sentrix Testnet (7120) | **h=5,800,000** (active since v2.2.22) | Set 2026-05-30 to recover the 2026-05-30 stall artifact. |
53+
| Sentrix Chain mainnet (7119) | `u64::MAX` (disabled) | Pending a planned activation window. |
54+
55+
Operators can override either chain via `ADD_SELF_STAKE_HEIGHT=<height>` env, but every peer in the active set must agree on the value or consensus will fork at the activation boundary.
56+
57+
If the tx applies before the fork activates, the dispatcher returns `gated by ADD_SELF_STAKE_HEIGHT fork (currently disabled)` and the sender's fee is consumed for the failed attempt.
58+
59+
## `sentrix staking unjail`
60+
61+
Submit an Unjail tx — the proper TX-based path. Goes through `apply_block` so `state_trie` stays consistent.
62+
63+
```bash
64+
sentrix staking unjail \
65+
--keystore /path/to/my-validator.keystore \
66+
--fee 10000
67+
```
68+
69+
Requirements:
70+
71+
- `self_stake ≥ MIN_SELF_STAKE` (use `add-self-stake` first if slashed below)
72+
- `current_height ≥ jail_until` (jail period expired — `DOWNTIME_JAIL_BLOCKS = 600` blocks ≈ 10 min after the original jail event)
73+
- Validator is not `is_tombstoned` (permanent ban — no recovery)
74+
75+
This is the recommended path. Do not use `sentrix validator unjail` or `sentrix validator force-unjail` unless the chain is so stuck that no transaction can be mined — those edit the DB directly and the warning printed by the CLI documents the cluster-wide recovery required.
76+
77+
## `sentrix staking claim-rewards`
78+
79+
Drain the sender's accumulated pending-rewards (validator-side + delegator-side) from `PROTOCOL_TREASURY` into their account balance.
80+
81+
```bash
82+
sentrix staking claim-rewards \
83+
--keystore /path/to/my-validator.keystore \
84+
--fee 10000
85+
```
86+
87+
No arguments beyond the keystore and fee. The dispatcher reads `pending_rewards` for the sender, peek-then-transfer-then-drains the accumulators (audit H5, 2026-05-06).
88+
89+
## End-to-end recovery example (val3, 2026-05-30 testnet)
90+
91+
Val3 was jailed during the 2026-05-30 stall recovery with `self_stake = 14,985 SRX` (0.1% downtime slash brought it below the 15,000 SRX floor). Recovery procedure once `ADD_SELF_STAKE_HEIGHT` activates on testnet at h=5,800,000:
92+
93+
```bash
94+
# 1. Pull rewards into the wallet so we have spendable SRX
95+
sentrix staking claim-rewards \
96+
--keystore /opt/sentrix-testnet-docker/data/val3/wallets/sentrix-testnet-val3.keystore \
97+
--fee 10000
98+
99+
# 2. Top up self_stake back above MIN_SELF_STAKE
100+
sentrix staking add-self-stake \
101+
--keystore /opt/sentrix-testnet-docker/data/val3/wallets/sentrix-testnet-val3.keystore \
102+
--amount 15
103+
104+
# 3. Unjail — dispatcher's floor check now passes
105+
sentrix staking unjail \
106+
--keystore /opt/sentrix-testnet-docker/data/val3/wallets/sentrix-testnet-val3.keystore
107+
```
108+
109+
Start the val3 container after step 3 completes; the mempool gossips the queued txs, an active proposer includes them, and val3 rejoins the active set at the next epoch boundary.
110+
111+
## Comparison with `sentrix validator unjail` / `force-unjail`
112+
113+
| Property | `sentrix staking …` (this page) | `sentrix validator unjail` / `force-unjail` |
114+
|---|---|---|
115+
| State change goes through | Block apply path | Direct DB write |
116+
| Updates `state_trie` | Yes (apply_block recomputes) | **No** — leaves trie hash stale |
117+
| Verify-deep on peers | Passes | **Fails** until cluster-wide trie rebuild |
118+
| Cluster-wide outage required | No (single-node CLI run, peers gossip the tx) | Yes (halt-all, reset-trie, tar-pipe, simul-start) |
119+
| Phantom stake risk | None — tx.amount comes from sender balance | Yes for `force-unjail` (restores stake without minting) |
120+
121+
Use the TX path whenever the chain can still mine blocks. Direct-DB commands are break-glass only — keep them around for the case where the chain is so stuck that no transaction can mine.

docs/tokenomics/staking.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ All slash amounts are **basis points** (1 bp = 0.01%, so 100 bp = 1%).
3535
| Slash on jail | **10 bp = 0.1%** of self-stake | `DOWNTIME_SLASH_BP` in `liveness.rs:67` |
3636
| Jail duration | 600 blocks (10 min @ 1s) | `DOWNTIME_JAIL_BLOCKS` in `liveness.rs:77` |
3737

38-
Validator must sign ≥30% of blocks in any rolling 4-hour window. If signed-blocks-in-window drops below 4,320, validator is jailed for 10 minutes + slashed 0.1% of self-stake. After jail expires, validator must submit `StakingOp::Unjail` to rejoin the active set.
38+
Validator must sign ≥30% of blocks in any rolling 4-hour window. If signed-blocks-in-window drops below 4,320, validator is jailed for 10 minutes + slashed 0.1% of self-stake. After jail expires, validator submits `StakingOp::Unjail` (or `sentrix staking unjail` via CLI — see [Staking CLI](../operations/staking-cli.md)) to rejoin the active set.
39+
40+
> If a downtime slash brings `self_stake` below `MIN_SELF_STAKE` (15,000 SRX), the dispatcher's floor check rejects plain `Unjail`. Recovery requires `StakingOp::AddSelfStake` first (top up back above the floor), then `Unjail`. See [Staking CLI](../operations/staking-cli.md) for the procedure.
3941
4042
Real-world downtime tolerance:
4143
- Weekly 10-min deploy → 0.07% downtime (absorbed)

0 commit comments

Comments
 (0)