valopersRealmPath
untyped stringvalopersRealmPath is the only realm allowed to refresh valoperCache or invoke RotateValoperSigningKey. Both auth checks below depend on being called via \`cross\` from a crossing function in valopers.
Value
"gno.land/r/gnops/valopers"
valoperCache
*v0.BPTreevaloperCache mirrors the (operator -> current signing key) view from r/gnops/valopers. Written by valopers via NotifyValoperChanged. Read by future operator-keyed proposal flow (step 5). Pushing (valopers passes the values as args) rather than pulling (v3 imports valopers and reads them) — pulling would create an import cycle, since valopers already imports v3 for IsValidator.
- OID
- 0f6113…50e1:4
valoperCache details
cacheEntry
typeValue
v3.cacheEntry
assertValopersCaller
func(int, rlm .uverse.realm)assertValopersCaller panics if the caller realm is not r/gnops/valopers. Per docs/resources/gno-interrealm.md, this check works only when (a) the host function is a crossing function (\`cur realm\`) and (b) it's invoked via \`cross\` from a crossing function in valopers. Then PreviousRealm() shifts exactly one frame to valopers. A user MsgCall would see PreviousRealm() == UserRealm (pkgpath ""); a third realm cross-call would see its own pkgpath. Either fails this check.
- OID
- 0f6113…50e1:6
assertValopersCaller details
NotifyValoperChanged
func(op .uverse.address, signingPubKey string, signingAddress .uverse.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.
- OID
- 0f6113…50e1:8
NotifyValoperChanged details
RotateValoperSigningKey
func(op .uverse.address, oldPubKey string, 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.
- OID
- 0f6113…50e1:9
RotateValoperSigningKey details
AssertGenesisValopersConsistent
func()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.
- OID
- 0f6113…50e1:10
AssertGenesisValopersConsistent details
ValoperChange
typeValoperChange is the operator-keyed input shape for the v3 valset proposal builder. Power=0 removes; Power>0 adds (or upserts the power on an op already in the active set — Tendermint's natural ValidatorUpdate semantics). Each operator may appear AT MOST ONCE per proposal; duplicates are rejected at create-time.
Value
v3.ValoperChange
NewValoperChange
func(operatorAddress .uverse.address, power uint64) v3.ValoperChange- OID
- 0f6113…50e1:11
NewValoperChange details
errNoValoperChanges
untyped stringValue
"no valoper changes proposed"
NewValidatorProposalRequest
func(changes []v3.ValoperChange, title string, description string) dao.ProposalRequestNewValidatorProposalRequest 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.)
- OID
- 0f6113…50e1:13
NewValidatorProposalRequest details
newValoperChangeExecutor
func(changes []v3.ValoperChange) dao.ExecutornewValoperChangeExecutor builds the GovDAO executor that, on approval, applies the captured ValoperChange deltas. Resolves operator → signing addr/pubkey via valoperCache at execution time for adds (so a mid-flight rotation doesn't publish a stale key). Removes resolve the operator's CURRENT signing address (also via cache) — operator-keyed removes are immune to rotation churn. Power>0 is an upsert against the effective valset map (keyed on signing address): if the op is already present under that signing address, the entry's voting power is overwritten. Tendermint natively handles ValidatorUpdates as upserts, so a single-entry power change is the canonical form.
- OID
- 0f6113…50e1:14
newValoperChangeExecutor details
IsValidator
func(addr .uverse.address) boolIsValidator returns true if addr is part of the effective validator set (proposed if a v3 proposal is awaiting EndBlocker, else current).
- OID
- 0f6113…50e1:15
IsValidator details
GetValidator
func(addr .uverse.address) validators.ValidatorGetValidator returns the validator with the given address from the effective set; panics if absent.
- OID
- 0f6113…50e1:17
GetValidator details
GetValidators
func() []validators.ValidatorGetValidators returns the effective validator set.
- OID
- 0f6113…50e1:18
GetValidators details
Render
func(string) stringRender displays the effective validator set.
- OID
- 0f6113…50e1:19