diff --git a/src/pages/guide/node/operate-validator.mdx b/src/pages/guide/node/operate-validator.mdx
index d6b93af..2b266c0 100644
--- a/src/pages/guide/node/operate-validator.mdx
+++ b/src/pages/guide/node/operate-validator.mdx
@@ -1,51 +1,20 @@
---
title: Operate your validator node
-description: Day-to-day operations for Tempo validators. Node lifecycle, upgrades, key rotation, monitoring, and troubleshooting.
+description: Day-to-day operations for Tempo validators. Node lifecycle, monitoring, metrics, log management, and Grafana dashboards.
---
# Operate your validator
This guide covers day-to-day operations for running a Tempo validator in production.
-## Validator states
+Validator management differs depending on which ValidatorConfig version is active:
-Your validator moves through different states during operation. The transitions will happen only once on your validator's creation. Every state transition will happen on epoch boundaries in the happy case.
+- **[ValidatorConfig V2](/guide/node/validator-config-v2)** (post-T2) — self-service key rotation, IP updates, and ownership transfers
+- **[ValidatorConfig V1](/guide/node/validator-config-v1)** (pre-T2, legacy) — all management operations require coordinating with the Tempo team
-```mermaid
-flowchart TD
- A[Inactive] -->|epoch ends| B["Syncer
The validator starts syncing"]
- B -->|+1 epoch| C["Syncer and Player"]
- C -->|"+1 epoch, receives share"| D["Syncer
Player
Dealer"]
- D -->|"once fully synced"| E["Voter ↔ Proposer"]
+For validator states and lifecycle transitions, see the respective V1 and V2 pages.
- click A "#not-a-participant-e"
- click B "#syncer-epoch-e1"
- click C "#player-epoch-e2"
- click D "#dealer-epoch-e3"
- click E "#dealer-epoch-e3"
-```
-
-Currently, on mainnet and testnet, the epoch length is around 3 hours, which means that your validator will transition through these states approximately every 3 hours. If the epoch length ever changes, the transition times will also change.
-
-#### Not a participant (E)
-
-Epoch E marks the addition of your validator to the on-chain validator configuration smart contract. Your validator isn't considered a peer by validators yet. This is because the validator hasn't been refreshed in the current epoch yet. It is normal that no height metrics progress during this period, your node has to be considered
-a syncer to receive blocks.
-
-#### Syncer (epoch E+1)
-
-Your validator is now considered a peer by validators. It's syncing with the network and will be considered a player in the next epoch.
-
-#### Player (epoch E+2)
-
-Your validator is receiving consensus signing shares from dealers during the ceremony.
-
-#### Dealer (epoch E+3)
-
-Your validator is distributing consensus signing shares to other validators during the ceremony. Once your node is fully synced up, it will also
-be able to propose blocks and vote for other validators' proposed blocks.
-
-#### Checking your validator's state
+## Checking your validator's state
Monitor these metrics to track your validator's state:
@@ -140,47 +109,14 @@ The node will finish processing the current block before shutting down. Avoid us
**You cannot reset a validator's data and continue with the same identity.** Doing so risks inconsistent voting, which can cause irrecoverable network safety failures.
:::
-If you need to reset your validator's data, you must rotate to a new validator identity. This requires coordinating with the Tempo team to deactivate your old identity and register a new one.
+If you need to reset your validator's data, you must rotate to a new validator identity. See key rotation under [ValidatorConfig V2](/guide/node/validator-config-v2#rotate-validator-identity) or [ValidatorConfig V1](/guide/node/validator-config-v1#signing-key-rotation).
## Key Management
-### Signing Key Rotation
-
-To rotate your validator's signing key:
-
-1. Generate a new keypair:
-
-```bash
-tempo consensus generate-private-key --output
-tempo consensus calculate-public-key --private-key
-```
-
-2. Contact the Tempo team to update your validator's public key on-chain
-
-3. Once confirmed, update your node configuration to use the new key and restart. Once the node is running, your validator will go through the [validator lifecycle](/guide/node/operate-validator#validator-states).
-
-:::warning
-The old validator identity must be deactivated before the new one is activated
-:::
-
-### Signing Share Recovery
+For signing key rotation, IP address updates, signing share recovery, and ownership transfers, see:
-:::danger
-**You cannot reset a validator's data and continue with the same identity.** Doing so risks inconsistent voting, which can cause irrecoverable network safety failures.
-:::
-
-If you lose your signing share (stored on the database in `/consensus/`), you will need to rotate to a new validator identity. This requires coordinating with the Tempo team to deactivate your old identity and register a new one.
-We're planning to release a high-availability feature that allows storing consensus data in an external database, which will enable signing share recovery without the need for key rotation.
-
-### Deleting Signing Shares
-
-:::warning[Breaking Change in v1.1.0]
-`--delete-signing-share` now requires the `--force` flag to prevent accidental deletion of validator signing keys. **Update any automation scripts that manage validator key lifecycle.**
-:::
-
-```bash
-tempo consensus --delete-signing-share --force
-```
+- **[ValidatorConfig V2](/guide/node/validator-config-v2)** (post-T2) — self-service operations
+- **[ValidatorConfig V1](/guide/node/validator-config-v1#key-management)** (pre-T2) — coordinated through the Tempo team
## Log Management
diff --git a/src/pages/guide/node/validator-config-v1.mdx b/src/pages/guide/node/validator-config-v1.mdx
new file mode 100644
index 0000000..15098a6
--- /dev/null
+++ b/src/pages/guide/node/validator-config-v1.mdx
@@ -0,0 +1,75 @@
+---
+title: ValidatorConfig V1 (Legacy)
+description: Legacy validator management via ValidatorConfig V1. Key rotation, IP updates, and signing share recovery pre-T2.
+---
+
+# ValidatorConfig V1 (Legacy)
+
+:::warning
+This page documents ValidatorConfig V1 behavior, which applies **before the T2 hardfork**. Once T2 is active and migration from V1 to V2 is complete, use [ValidatorConfig V2](/guide/node/validator-config-v2) instead. You can [check if V2 is initialized](/guide/node/validator-config-v2#check-if-v2-is-active) to confirm the migration is complete.
+:::
+
+ValidatorConfig V1 is the original precompile for managing consensus participants. All management operations are permissioned and require coordinating with the Tempo team.
+
+## Validator states
+
+Under V1, your validator goes through the following states after being added on-chain. Each transition happens on epoch boundaries.
+
+```mermaid
+flowchart TD
+ A[Inactive] -->|epoch ends| B["Syncer
The validator starts syncing"]
+ B -->|+1 epoch| C["Syncer and Player"]
+ C -->|"+1 epoch, receives share"| D["Syncer
Player
Dealer"]
+ D -->|"once fully synced"| E["Voter ↔ Proposer"]
+
+ click A "#not-a-participant-e"
+ click B "#syncer-epoch-e1"
+ click C "#player-epoch-e2"
+ click D "#dealer-epoch-e3"
+ click E "#dealer-epoch-e3"
+```
+
+Currently, on mainnet and testnet, the epoch length is around 3 hours, which means that your validator will transition through these states approximately every 3 hours.
+
+#### Not a participant (E)
+
+Epoch E marks the addition of your validator to the on-chain validator configuration smart contract. Your validator isn't considered a peer by validators yet. This is because the validator hasn't been refreshed in the current epoch yet. It is normal that no height metrics progress during this period, your node has to be considered a syncer to receive blocks.
+
+#### Syncer (epoch E+1)
+
+Your validator is now considered a peer by validators. It's syncing with the network and will be considered a player in the next epoch.
+
+#### Player (epoch E+2)
+
+Your validator is receiving consensus signing shares from dealers during the ceremony.
+
+#### Dealer (epoch E+3)
+
+Your validator is distributing consensus signing shares to other validators during the ceremony. Once your node is fully synced up, it will also be able to propose blocks and vote for other validators' proposed blocks.
+
+## Key Management
+
+### Signing Key Rotation
+
+1. Generate a new keypair:
+
+```bash
+tempo consensus generate-private-key --output
+tempo consensus calculate-public-key --private-key
+```
+
+2. Contact the Tempo team to update your validator's public key on-chain
+
+3. Once confirmed, update your node configuration to use the new key and restart. Once the node is running, your validator will go through the [validator states](#validator-states) again.
+
+:::warning
+The old validator identity must be deactivated before the new one is activated.
+:::
+
+### Signing Share Recovery
+
+If you lose your signing share, coordinate with the Tempo team to deactivate your old identity and register a new one.
+
+### Update IP Addresses
+
+Contact the Tempo team to update your validator's ingress and egress addresses on-chain.
diff --git a/src/pages/guide/node/validator-config-v2.mdx b/src/pages/guide/node/validator-config-v2.mdx
new file mode 100644
index 0000000..69abf00
--- /dev/null
+++ b/src/pages/guide/node/validator-config-v2.mdx
@@ -0,0 +1,208 @@
+---
+title: ValidatorConfig V2
+description: Manage your validator with ValidatorConfig V2. Self-service key rotation, IP updates, and ownership transfer.
+---
+
+# ValidatorConfig V2
+
+ValidatorConfig V2 ([TIP-1017](/protocol/tips/tip-1017)) is a new precompile for managing consensus participants. It replaces the original ValidatorConfig with stronger safety guarantees: ed25519 signature verification at registration, append-only history, and self-service operations for validators.
+
+V2 becomes available after the T2 hardfork is activated and after an admin has finished the migration of entries from V1 to V2. Migration completion will be communicated to operators — you can also [check if V2 is active](#check-if-v2-is-active) yourself.
+
+## Validator states
+
+With V2, the syncer warmup phase from V1 is removed. Once added, a validator immediately becomes a player in the next epoch.
+
+```mermaid
+flowchart TD
+ A[Inactive] -->|epoch ends| B["Player
Receives signing shares"]
+ B -->|"+1 epoch, receives share"| C["Player
Dealer"]
+ C -->|"once fully synced"| D["Voter ↔ Proposer"]
+```
+
+Compare this to the [V1 validator states](/guide/node/validator-config-v1#validator-states), which required an additional syncer epoch before becoming a player.
+
+## What changes for operators
+
+With V2, validators can perform several operations themselves without coordinating with the Tempo team:
+
+- **Rotate your validator identity** — swap to a new ed25519 key without losing your committee slot
+- **Update IP addresses** — change ingress and egress endpoints independently (V2 supports asymmetric ingress/egress IPs)
+- **Transfer ownership** — rebind your validator entry to a new address
+- **Fee recipient separation** — will be enabled in a future hardfork. For now, continue using `--consensus.fee-recipient` when starting your node.
+
+All write operations require either the contract owner or the validator's own address.
+
+## Precompile address
+
+```solidity
+address constant VALIDATOR_CONFIG_V2 = 0xCCCCCCCC00000000000000000000000000000001;
+```
+
+## Check if V2 is active
+
+After the T2 hardfork, the contract owner migrates validators from V1 to V2. Use these calls to check if migration is complete and V2 is active:
+
+```bash
+# Returns true once migration is complete and V2 is the active config
+cast call 0xCCCCCCCC00000000000000000000000000000001 \
+ "isInitialized()(bool)" \
+ --rpc-url https://rpc.tempo.xyz
+
+# Returns the block height at which V2 was initialized (0 if not yet initialized)
+cast call 0xCCCCCCCC00000000000000000000000000000001 \
+ "getInitializedAtHeight()(uint64)" \
+ --rpc-url https://rpc.tempo.xyz
+```
+
+If `isInitialized()` returns `true`, V2 is active and all operations on this page are available. If it returns `false`, the network is still on [ValidatorConfig V1](/guide/node/validator-config-v1).
+
+## Reading validator state
+
+### Query active validators
+
+```bash
+cast call 0xCCCCCCCC00000000000000000000000000000001 \
+ "getActiveValidators()" \
+ --rpc-url https://rpc.tempo.xyz
+```
+
+### Look up your validator
+
+You can query your validator by address, public key, or index:
+
+```bash
+# By address
+cast call 0xCCCCCCCC00000000000000000000000000000001 \
+ "validatorByAddress(address)(bytes32,address,string,string,uint64,uint64,uint64,address)" \
+ \
+ --rpc-url https://rpc.tempo.xyz
+
+# By public key
+cast call 0xCCCCCCCC00000000000000000000000000000001 \
+ "validatorByPublicKey(bytes32)(bytes32,address,string,string,uint64,uint64,uint64,address)" \
+ \
+ --rpc-url https://rpc.tempo.xyz
+
+# By index
+cast call 0xCCCCCCCC00000000000000000000000000000001 \
+ "validatorByIndex(uint64)(bytes32,address,string,string,uint64,uint64,uint64,address)" \
+ \
+ --rpc-url https://rpc.tempo.xyz
+```
+
+The returned `Validator` struct fields are:
+
+| Field | Type | Description |
+|-------|------|-------------|
+| `publicKey` | `bytes32` | Ed25519 communication public key |
+| `validatorAddress` | `address` | Validator control address |
+| `ingress` | `string` | Inbound address (`IP:port`) |
+| `egress` | `string` | Outbound address (`IP`) |
+| `index` | `uint64` | Immutable array position |
+| `addedAtHeight` | `uint64` | Block height when added |
+| `deactivatedAtHeight` | `uint64` | Block height when deactivated (`0` = active) |
+| `feeRecipient` | `address` | Address that receives block proposal fees |
+
+## Operator guide
+
+### Update IP addresses
+
+If your node's network endpoints change, update them on-chain. The change takes effect at the next finalized block.
+
+Unlike V1, V2 supports asymmetric ingress and egress IPs — they no longer need to share the same address. If you only want to update one, pass the current value for the other.
+
+```bash
+cast send 0xCCCCCCCC00000000000000000000000000000001 \
+ "setIpAddresses(uint64,string,string)" \
+ \
+ ":" \
+ "" \
+ --rpc-url https://rpc.tempo.xyz \
+ --private-key
+```
+
+`:` and `` may remain unchanged if you only need to update one of the two.
+
+:::warning
+Ingress addresses must be unique across all active validators. The transaction will revert if another active validator already uses the same `IP:port`.
+:::
+
+### Rotate validator identity
+
+V2 lets you rotate to a new ed25519 key while keeping your validator index stable. This is useful for key rotation or recovery without leaving and re-joining the committee.
+
+The simplest way to rotate is using the `tempo` CLI, which handles signature creation and the on-chain transaction in one step:
+
+```bash
+tempo consensus rotate-validator \
+ --signing-key \
+ --rpc-url https://rpc.tempo.xyz
+```
+
+:::info
+Rotation preserves your validator index and active validator count. The old entry is appended to history as deactivated, and the entry at your index is updated in place. You must use a different ingress address (changing the port is sufficient).
+:::
+
+After rotation, your validator goes through the [standard lifecycle](#validator-states) with the new identity.
+
+:::danger[Do not shut down the old validator immediately]
+After rotation, the rotated-out validator is still a member of the current committee until the next successful DKG ceremony completes. Shutting it down early will degrade network liveness.
+
+Keep the old validator running and use `validators-info` to monitor its status:
+
+```bash
+tempo consensus validators-info --rpc-url https://rpc.tempo.xyz
+```
+
+Once the old validator shows `in_committee = false`, it is safe to shut down.
+:::
+
+#### Using raw contract calls
+
+If you prefer to call the precompile directly, first generate the required ed25519 signature proving ownership of the new key:
+
+```bash
+tempo consensus create-rotate-validator-signature \
+ --signing-key \
+ --rpc-url https://rpc.tempo.xyz
+```
+
+Then use the output signature in a `rotateValidator` call via `cast send`.
+
+#### Initial registration
+
+When registering a new validator, generate the add-validator signature and provide it to the Tempo team:
+
+```bash
+tempo consensus create-add-validator-signature \
+ --signing-key \
+ --rpc-url https://rpc.tempo.xyz
+```
+
+### Transfer validator ownership
+
+Rebind your validator entry to a new control address:
+
+```bash
+cast send 0xCCCCCCCC00000000000000000000000000000001 \
+ "transferValidatorOwnership(uint64,address)" \
+ \
+ \
+ --rpc-url https://rpc.tempo.xyz \
+ --private-key
+```
+
+The new address must not already be used by another active validator.
+
+## Differences from V1
+
+| | V1 | V2 |
+|---|---|---|
+| **Key ownership** | No verification | Ed25519 signature required |
+| **History** | Mutable, toggle active/inactive | Append-only, deactivate-once |
+| **Validator index** | Could change | Stable for lifetime |
+| **Self-service ops** | None (owner only) | IP updates, rotation, transfer |
+| **Historical queries** | Required warmup state, bloated snapshots | `addedAtHeight` / `deactivatedAtHeight` fields |
+
+
diff --git a/src/pages/guide/node/validator.mdx b/src/pages/guide/node/validator.mdx
index c09d66d..87619d2 100644
--- a/src/pages/guide/node/validator.mdx
+++ b/src/pages/guide/node/validator.mdx
@@ -16,7 +16,7 @@ All validators have two kinds of keys:
* signing key - this is an ED25519 keypair used to identify your validator amongst others
* signing share - this is a share of a BLS12-381 keypair used to sign block notarizations and finalizations
-The signing key is static and can only be rotated by removing and re-creating a validator on-chain. The signing share is dynamic and is updated periodically on each DKG ceremony. Once updated, it will be saved to disk. Currently, the DKG ceremony is scheduled to run on-chain every ~3 hours.
+The signing key is static. Pre-T2, it can only be rotated by removing and re-creating a validator on-chain with the Tempo team. Post-T2, [ValidatorConfig V2](/guide/node/validator-config-v2) enables self-service rotation via the `rotateValidator` precompile. The signing share is dynamic and is updated periodically on each DKG ceremony. Once updated, it will be saved to disk. Currently, the DKG ceremony is scheduled to run on-chain every ~3 hours.
## Generating a signing key
@@ -105,7 +105,7 @@ INFO handle_propose{epoch=18 view=387213 parent.view=387212 parent.digest=0x4388
```
If you do not see logs like these:
-- please check that your validator is part of the active set, and is both [a player and a dealer](https://docs.tempo.xyz/guide/node/operate-validator#validator-states)
+- please check that your validator is part of the active set, and is both a player and a dealer (see validator states under [V2](/guide/node/validator-config-v2#validator-states) or [V1](/guide/node/validator-config-v1#validator-states))
- please check that your node is synced up to the [latest block height](https://explorer.tempo.xyz/).
- please check that your outgoing IP address matches the one whitelisted on the validator smart contract:
diff --git a/vocs.config.ts b/vocs.config.ts
index d6e574f..89c4f54 100644
--- a/vocs.config.ts
+++ b/vocs.config.ts
@@ -15,8 +15,7 @@ export default defineConfig({
banner: {
dismissable: false,
backgroundColor: '#5B4CDB',
- content:
- 'Tempo Mainnet is live. [Read our announcement.](https://tempo.xyz/blog/mainnet) →',
+ content: 'Tempo Mainnet is live. [Read our announcement.](https://tempo.xyz/blog/mainnet) →',
height: '40px',
textColor: 'white',
},
@@ -655,7 +654,21 @@ export default defineConfig({
},
{
text: 'Operating your validator',
- link: '/guide/node/operate-validator',
+ collapsed: true,
+ items: [
+ {
+ text: 'Overview',
+ link: '/guide/node/operate-validator',
+ },
+ {
+ text: 'ValidatorConfig V2',
+ link: '/guide/node/validator-config-v2',
+ },
+ {
+ text: 'ValidatorConfig V1 (Legacy)',
+ link: '/guide/node/validator-config-v1',
+ },
+ ],
},
{
text: 'Network Upgrades and Releases',