PathrockNetwork Gno Explorer
HomeBlocksTransactionsRealmsPackagesValidators

PathrockNetwork Gno Explorer — an independent explorer for Gno.land Mainnet (gnoland-1), operated by PathrockNetwork. Not an official Gno.land service.

gnowebarchive RPC

gno.land/p/g1ecsuj0q572jr0dhu29q9njtnmw03hyu7tyyvv6/governor/v0

Package
Open in gnoweb ↗

Overview

Kind
Pure package
Name
v0
Namespace
g1ecsuj0q572jr0dhu29q9njtnmw03hyu7tyyvv6 / governor
Files
8 (gnomod.toml)
Exported functions
n/a — not supported for pure packages by the node (vm/qfuncs)
Module
gno.land/p/g1ecsuj0q572jr0dhu29q9njtnmw03hyu7tyyvv6/governor/v0
gno
0.9

Files (8)

  • gnomod.tomltoml
  • batch.gnogno
  • builtin.gnogno
  • electorate.gnogno
  • governor.gnogno
  • introspect.gnogno
  • keys.gnogno
  • rules.gnogno
  • electorate.gnogno
    1package governor23import (4	bptree "gno.land/p/nt/bptree/v0"5)67// Electorate is where voting weight comes from, and the only thing tying this8

    Functions

    not supported for pure packages by the node (vm/qfuncs)

    Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.

    // engine to any particular token. Everything else here is about proposals, so
    9// with this extracted the engine can be driven by anything that can answer
    10// four questions.
    11//
    12// It also makes the governor testable without a ledger. Reaching exactly a
    13// quorum with real balances means solving for the supply, and a test that does
    14// arithmetic to test arithmetic proves nothing.
    15//
    16// EVERY QUESTION HERE IS ABOUT A SEALED PAST EPOCH, which is what keeps the
    17// Token/Electorate split below honest — Electorate about then, Token about now.
    18// A live per-address read (VotesOf) was added here while fixing rented weight and
    19// removed again when the fix was reverted; RENTEDWEIGHT.md records why. Anything
    20// re-adding it is re-opening that decision, not making a small change.
    21//
    22// AND THE FIX THAT SHIPPED DID NOT NEED IT, which is the point worth keeping. The
    23// live figure arrives as a CAP from the consumer (VoteWithCap) instead of as an
    24// interface method the engine calls, so this interface stays entirely about THEN.
    25// The engine cannot read a live balance even if it wanted to, and a supplied
    26// ceiling can only lower what the engine derived — so coherence is structural
    27// rather than something each implementor has to get right.
    28type Electorate interface {
    29 // PastVotes is what an address could vote at a sealed epoch.
    30 PastVotes(who address, at uint32) int64
    31
    32 // PastTotal is everything that existed then, which quorum is a fraction
    33 // of. Taken at the same epoch as the votes it is compared against, or a
    34 // quorum could be met against a supply that no longer exists.
    35 //
    36 // It must be at least the sum of every PastVotes at that epoch. The
    37 // governor subtracts what has been cast from this to decide whether a
    38 // question is already settled, so a roll whose parts exceed its whole
    39 // reports votes that cannot exist and settles early. Measured, not feared:
    40 // one voter reporting a hundred against a claimed total of ten carried a
    41 // proposal at a 99% threshold.
    42 //
    43 // This realm's token satisfies it exactly, and a test says so after every
    44 // operation that moves power. Anything swapped in here needs its own. The
    45 // governor cannot check it and cannot recover from it — a clamp was tried.
    46 //
    47 // It must also stay at or below maxWeighable (MaxInt64/bps): the tally
    48 // computes yes*bps, and a supply above that overflows int64 into a negative
    49 // tally — a won vote reported as lost. grc20votes caps its supply there
    50 // exactly; the governor refuses a proposal whose snapshot supply exceeds it,
    51 // so a swapped-in electorate that ignores the ceiling fails loudly at the door.
    52 PastTotal(at uint32) int64
    53
    54 // EngagedTotal is the part of PastTotal that quorum is measured against.
    55 //
    56 // It exists so a realm can drop idle weight out of the denominator without
    57 // touching anything in the governor: a fixed low bar is unreachable at
    58 // launch and trivial later, and moving the denominator is the fix that
    59 // keeps the bar meaningful at both ends.
    60 //
    61 // Should be <= PastTotal at the same epoch. Weight outside it can still vote
    62 // — it simply is not counted in the bar — so the governor keeps using
    63 // PastTotal for how many votes could still be cast. If it exceeds PastTotal
    64 // the governor clamps it down to PastTotal, so an electorate that over-reports
    65 // engagement makes the bar unreachable-but-valid rather than aborting.
    66 //
    67 // This realm's token returns PastTotal unchanged: every holder is engaged
    68 // by definition, since power is self-delegated by default.
    69 EngagedTotal(at uint32) int64
    70
    71 // Epoch is now. A proposal snapshots Epoch()-1 and stores it; nothing
    72 // re-derives it later.
    73 Epoch() uint32
    74
    75 // Height is the block height the governor gates on: when voting opens and
    76 // closes, when a delay has elapsed, when a proposal may execute.
    77 //
    78 // It comes from the electorate rather than from the chain so that a realm
    79 // whose clock can be fast-forwarded moves the VOTES with it. Reading
    80 // runtime.ChainHeight() here instead would leave a test chain able to age
    81 // everything except the one thing a dispute waits on, and would let the
    82 // governor and the ledger disagree about what epoch it is.
    83 Height() int64
    84
    85 // Now is the block's wall-clock time in unix seconds, from the same source
    86 // as Height and for the same reason: a realm that can fast-forward its clock
    87 // must move the VOTES with it, and a pure package may not read the chain
    88 // directly without leaving a test chain able to age everything except the
    89 // one thing a dispute waits on.
    90 //
    91 // It exists because a voting window is a PROMISE TO A VOTER — "this closes
    92 // in four days" — and a height only means a date if the chain's pace never
    93 // changes. The governor gates on this and keeps the height beside it.
    94 Now() int64
    95}
    96
    97// Token is what a page needs to name the thing being voted: an identity and a
    98// live supply. Separate from Electorate because they answer about different
    99// times — Electorate about a sealed epoch, Token about now — and a realm may
    100// well have one without the other.
    101//
    102// p/kourt/grc20votes.Ledger satisfies both, which is the ordinary case.
    103type Token interface {
    104 Name() string
    105 Symbol() string
    106 Decimals() int
    107 TotalSupply() int64
    108}
    109
    110// New creates a governor with no kinds adopted and nothing proposed, and
    111// installs the built-in kinds that govern the governor itself.
    112//
    113// The minter kind is NOT among them: who may create supply is a policy about a
    114// caller, and a pure package has no caller. A realm wanting one registers it
    115// with InstallBuiltin.
    116func New(voters Electorate, token Token) *Governor {
    117 if voters == nil || token == nil {
    118 panic("governor: a governor needs an electorate and a token")
    119 }
    120 g := &Governor{
    121 voters: voters,
    122 token: token,
    123 kinds: bptree.NewBPTree32(),
    124 proposals: bptree.NewBPTree32(),
    125 openIdx: bptree.NewBPTree32(),
    126 }
    127 g.installBuiltins()
    128 return g
    129}
    130
    131// InstallBuiltin adopts a kind under the reserved prefix, which Offer refuses.
    132//
    133// For the consuming realm only, and it is unexported state that makes that
    134// true: reaching this needs the *Governor, which the realm keeps to itself.
    135// A realm uses it for a power that is its own rather than the engine's — the
    136// mint being the example.
    137func (g *Governor) InstallBuiltin(k Kind, r Rules) {
    138 name := k.Name()
    139 if !isReserved(name) {
    140 panic("governor: a built-in has to carry the reserved prefix")
    141 }
    142 mustBeUsableName(name)
    143 g.mustBeSaneRules(r)
    144 g.kinds.Set(name, &entry{kind: k, rules: r, live: true})
    145}
    146