Search Apps Documentation Source Content File Folder Download Copy Actions Download

v3 package

Overview

Package validators implements on-chain validator set management through Proof of Authority. The realm exposes a public proposal constructor for GovDAO; on approval, the proposal callback applies the captured deltas to the chain's effective valset and publishes the new full set via gno.land/r/sys/params. The chain's EndBlocker reads the result on the next block and propagates to consensus.

No in-realm validator state. All reads go through sysparams.GetValsetEffective (proposed-if-dirty, else current).

Functions

AssertGenesisValopersConsistent

func AssertGenesisValopersConsistent(cur realm)

AssertGenesisValopersConsistent panics if any entry in valset:current (the seeded genesis valset) lacks a corresponding valoperCache profile whose SigningAddress matches.

**Genesis-mode only.** The function refuses to run unless runtime.ChainHeight() == 0. This is the documented intended usage (last migration .jsonl tx, before any block has been produced) and also closes a post-genesis MsgCall DoS surface — without the guard, an attacker could pay gas to repeatedly invoke an O(N) iteration over valoperCache + valset:current after the chain is live.

gnoland's InitChainer auto-runs this assertion at end of genesis-mode replay when GnoGenesisState.PastChainIDs is non-empty; failure aborts the boot unconditionally. valoper-seed and hand-crafted migration .jsonls do NOT need to emit the call themselves.

Crossing function: callable via MsgCall (only at genesis-mode). Doesn't mutate state — pure invariant check. Inverse direction (every valoperCache entry must have a corresponding valset:current entry) is intentionally NOT checked: extra valoper profiles registered without immediate valset inclusion are a normal post-genesis state.

Command

# WARNING: This command is running in an INSECURE mode.
# It is strongly recommended to use a hardware device for signing
# and avoid trusting any computer connected to the internet,
# as your private keys could be exposed.

gnokey maketx call -pkgpath "gno.land/r/sys/validators/v3" -func "AssertGenesisValopersConsistent" -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -chainid "dev" -remote "https://api.gno.berty.io:443" ADDRESSgnokey query -remote "https://api.gno.berty.io:443" auth/accounts/ADDRESS
gnokey maketx call -pkgpath "gno.land/r/sys/validators/v3" -func "AssertGenesisValopersConsistent" -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -broadcast=false ADDRESS > call.tx
gnokey sign -tx-path call.tx -chainid "dev" -account-number ACCOUNTNUMBER -account-sequence SEQUENCENUMBER ADDRESS
gnokey broadcast -remote "https://api.gno.berty.io:443" call.tx
  

GetCooldown

func GetCooldown() uint64

GetCooldown returns the currently configured valset-update cooldown, expressed in seconds. The default is 24h (per the #4829 acceptance criteria); governance can tune it via NewCooldownPropRequest.

Command

gnokey query vm/qeval -remote "https://api.gno.berty.io:443" -data "gno.land/r/sys/validators/v3.GetCooldown()"

Result

GetTrustLevel

func GetTrustLevel() (uint64, uint64)

GetTrustLevel returns the currently configured trust level as (numerator, denominator).

Command

gnokey query vm/qeval -remote "https://api.gno.berty.io:443" -data "gno.land/r/sys/validators/v3.GetTrustLevel()"

Result

GetValidator

func GetValidator(addr address) validators.Validator

GetValidator returns the validator with the given address from the effective set; panics if absent.

Param

Command

gnokey query vm/qeval -remote "https://api.gno.berty.io:443" -data "gno.land/r/sys/validators/v3.GetValidator()"

Result

GetValidators

func GetValidators() []validators.Validator

GetValidators returns the effective validator set.

Command

gnokey query vm/qeval -remote "https://api.gno.berty.io:443" -data "gno.land/r/sys/validators/v3.GetValidators()"

Result

IsValidator

func IsValidator(addr address) bool

IsValidator returns true if addr is part of the effective validator set (proposed if a v3 proposal is awaiting EndBlocker, else current).

Param

Command

gnokey query vm/qeval -remote "https://api.gno.berty.io:443" -data "gno.land/r/sys/validators/v3.IsValidator()"

Result

NewCooldownPropRequest

func NewCooldownPropRequest(seconds uint64, title, description string) dao.ProposalRequest

NewCooldownPropRequest builds a GovDAO proposal that, when executed, updates valsetUpdateCooldown. The new duration is given in seconds; 0 disables the cooldown entirely (useful for testnets and integration tests). The executor reads the cooldown live (not via snapshot) so a successful proposal takes effect immediately for any valset proposal created after it executes. In-flight valset proposals that passed their own create-time cooldown check are re-checked at execute time against the (now possibly different) live cooldown — this is intentional so governance can both shorten AND lengthen the cooldown without surprises.

Params

Command

gnokey query vm/qeval -remote "https://api.gno.berty.io:443" -data "gno.land/r/sys/validators/v3.NewCooldownPropRequest(,,)"

Result

NewTrustLevelPropRequest

func NewTrustLevelPropRequest(numerator, denominator uint64, title, description string) dao.ProposalRequest

NewTrustLevelPropRequest builds a GovDAO proposal that, when executed, updates trustLevelRatio. The ratio must be in [1/3, 2/3] both at creation and execution time (re-checked in the callback in case bounds change between propose and execute).

Params

Command

gnokey query vm/qeval -remote "https://api.gno.berty.io:443" -data "gno.land/r/sys/validators/v3.NewTrustLevelPropRequest(,,,)"

Result

NewValidatorProposalRequest

func NewValidatorProposalRequest(changes []ValoperChange, title, description string) dao.ProposalRequest

NewValidatorProposalRequest builds a GovDAO proposal that, when executed, applies the deltas to the chain's effective valset and publishes the new full set via SetValsetProposal.

NON-CROSSING (no `cur realm`). Direct MsgCall is unsupported; proposers route through r/gnops/valopers/proposal's facade (which IS crossing and accepts user txs).

Validation at creation time:

  • Each operator may appear AT MOST ONCE in changes; duplicates panic. Power changes for an op already in the active set use a single {op, newPower} entry (upsert), not the legacy remove/re-add pair.
  • Every ValoperChange's OperatorAddress must exist in valoperCache. Unknown operators panic.
  • Adds (Power > 0) require KeepRunning=true. An op that has called UpdateKeepRunning(false) signals opt-out; no proposal can keep them in the active set, period.

Pubkey resolution at execution time: the executor callback re-reads valoperCache for each entry to capture the CURRENT signing pubkey/address — not the creation-time one. Defends against a stale (now-retired) key publication if the operator rotated while the proposal sat in GovDAO. Also re-checks KeepRunning so an operator flipping to KeepRunning=false between propose-create and propose-execute is honored. Removes are unaffected (operator address is the lookup key, not signing address).

Emits ValidatorAdded / ValidatorRemoved events per entry on successful execution. (Power-upsert on an existing op also emits ValidatorAdded with the new power.)

Params

Command

gnokey query vm/qeval -remote "https://api.gno.berty.io:443" -data "gno.land/r/sys/validators/v3.NewValidatorProposalRequest(,,)"

Result

NotifyValoperChanged

func NotifyValoperChanged(cur realm, op address, signingPubKey string, signingAddress address, keepRunning bool)

NotifyValoperChanged refreshes the cached entry for op. Auth: caller realm must be r/gnops/valopers.

READ-ONLY against valopers: by design this function does not call back into valopers (no pull). Valopers pushes the current values in as args. This eliminates the confused-deputy class where v3 → valopers callbacks would make valopers see v3 as PreviousRealm.

Params

Command

# WARNING: This command is running in an INSECURE mode.
# It is strongly recommended to use a hardware device for signing
# and avoid trusting any computer connected to the internet,
# as your private keys could be exposed.

gnokey maketx call -pkgpath "gno.land/r/sys/validators/v3" -func "NotifyValoperChanged" -args $'' -args $'' -args $'' -args $'' -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -chainid "dev" -remote "https://api.gno.berty.io:443" ADDRESSgnokey query -remote "https://api.gno.berty.io:443" auth/accounts/ADDRESS
gnokey maketx call -pkgpath "gno.land/r/sys/validators/v3" -func "NotifyValoperChanged" -args $'' -args $'' -args $'' -args $'' -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -broadcast=false ADDRESS > call.tx
gnokey sign -tx-path call.tx -chainid "dev" -account-number ACCOUNTNUMBER -account-sequence SEQUENCENUMBER ADDRESS
gnokey broadcast -remote "https://api.gno.berty.io:443" call.tx
  

Render

func Render(string) string

Render displays the effective validator set.

Param

Command

gnokey query vm/qeval -remote "https://api.gno.berty.io:443" -data "gno.land/r/sys/validators/v3.Render()"

Result

RotateValoperSigningKey

func RotateValoperSigningKey(cur realm, op address, oldPubKey, newPubKey string)

RotateValoperSigningKey applies a signing-key rotation to the effective valset and publishes the new full set via sysparams. Auth: caller realm must be r/gnops/valopers.

Body is read-modify-write against sysparams.GetValsetEffective so concurrent same-block writers (other rotations or GovDAO executors) accumulate instead of clobbering. Mirrors the executor pattern in validators.gno.

Idempotent: if the rotating operator's old signing address is not currently in the effective valset (e.g., they were removed), the rotation is a no-op at the sysparams level — valopers' profile and signingRegistry already record the new key. Either replays cleanly.

Emits ValoperRotated event with op + old/new addresses + height.

Params

Command

# WARNING: This command is running in an INSECURE mode.
# It is strongly recommended to use a hardware device for signing
# and avoid trusting any computer connected to the internet,
# as your private keys could be exposed.

gnokey maketx call -pkgpath "gno.land/r/sys/validators/v3" -func "RotateValoperSigningKey" -args $'' -args $'' -args $'' -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -chainid "dev" -remote "https://api.gno.berty.io:443" ADDRESSgnokey query -remote "https://api.gno.berty.io:443" auth/accounts/ADDRESS
gnokey maketx call -pkgpath "gno.land/r/sys/validators/v3" -func "RotateValoperSigningKey" -args $'' -args $'' -args $'' -gas-fee 1000000ugnot -gas-wanted 1_000_000_000 -send "" -broadcast=false ADDRESS > call.tx
gnokey sign -tx-path call.tx -chainid "dev" -account-number ACCOUNTNUMBER -account-sequence SEQUENCENUMBER ADDRESS
gnokey broadcast -remote "https://api.gno.berty.io:443" call.tx