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
  • batch.gnogno
    1package governor23import (4	"strings"56	ufmt "gno.land/p/nt/ufmt/v0"7)8

    Functions

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

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

    9// batchKind runs several adopted kinds as one decision.
    10//
    11// govern:batch "treasury/spend 100\nfee 250"
    12//
    13// One member per line, the kind first and the rest its payload. Members must
    14// already be adopted: a batch decides several things at once and smuggles in
    15// nothing.
    16//
    17// All or nothing, because there is no halfway. A member's Do returning an error
    18// makes this panic, aborting the transaction and unwinding what earlier members
    19// did — the only atomicity gno offers.
    20//
    21// So a failed batch leaves the proposal Succeeded rather than Failed: the
    22// transaction wrote nothing, including the failure. It can be run again and
    23// will fail identically until the world changes or the grace period ends it.
    24//
    25// Single-member kinds keep the other behaviour — record the failure and finish
    26// — since there is nothing to be atomic with respect to.
    27type batchKind struct{}
    28
    29// maxBatch bounds a batch, because Describe and Check both walk it and a
    30// proposal nobody can render is a proposal nobody can vote on.
    31const maxBatch = 16
    32
    33func (k batchKind) Name() string { return reserved + "batch" }
    34
    35func (k batchKind) describe(g *Governor, payload string) string {
    36 members, err := parseBatch(payload)
    37 if err != nil {
    38 return "malformed batch: " + err.Error()
    39 }
    40 out := ufmt.Sprintf("do all %d of these, or none of them:\n", len(members))
    41 for i, m := range members {
    42 // Each member described by its own kind, from its own payload — the
    43 // same strings their Do will be handed. A batch that summarised its
    44 // members in its own words would be the description gap this design
    45 // exists to avoid, reintroduced one level up.
    46 out += ufmt.Sprintf("\n%d. **%s** — %s", i+1, m.kind, g.describeMember(m))
    47 }
    48 return out
    49}
    50
    51func (g *Governor) describeMember(m member) string {
    52 k := g.anyKind(m.kind)
    53 if k == nil {
    54 return "_no kind by that name_"
    55 }
    56 return g.describeKind(k, m.payload)
    57}
    58
    59func (k batchKind) check(g *Governor, payload string) error {
    60 members, err := parseBatch(payload)
    61 if err != nil {
    62 return err
    63 }
    64 for _, m := range members {
    65 e := g.entryOf(m.kind)
    66 if e == nil {
    67 return govErr("no kind called " + m.kind)
    68 }
    69 if !e.live {
    70 // A batch cannot reach a power the holders have not granted.
    71 return govErr(m.kind + " is not adopted")
    72 }
    73 if m.kind == (batchKind{}).Name() {
    74 // No batches of batches. Nesting makes the rendered description a
    75 // tree of unbounded depth, and the point of the description is
    76 // that somebody reads it.
    77 return govErr("a batch cannot contain a batch")
    78 }
    79 if err := g.checkKind(e.kind, m.payload); err != nil {
    80 return govErr(m.kind + ": " + err.Error())
    81 }
    82 }
    83 return nil
    84}
    85
    86func (k batchKind) run(g *Governor, dispatch Dispatch, payload string) error {
    87 members, err := parseBatch(payload)
    88 if err != nil {
    89 return err
    90 }
    91 for i, m := range members {
    92 e := g.entryOf(m.kind)
    93 if e == nil || !e.live {
    94 panic("govern: batch member " + m.kind + " is no longer adopted")
    95 }
    96 var err error
    97 if b, ok := asBuiltin(e.kind); ok {
    98 err = b.run(g, dispatch, m.payload)
    99 } else {
    100 // Each member gets its OWN sub-realm, named for the power it is,
    101 // rather than the batch's. A batch is a way to decide several
    102 // things at once, not a way to launder one kind's authority into
    103 // another's.
    104 err = dispatch(e.kind, subPathOf(m.kind), m.payload)
    105 }
    106 if err != nil {
    107 // Panic, not return. Returning would record a failure and keep
    108 // whatever the earlier members already did, which is the one
    109 // outcome a batch promises cannot happen.
    110 panic(ufmt.Sprintf("govern: batch member %d (%s) failed: %s",
    111 i+1, m.kind, err.Error()))
    112 }
    113 }
    114 return nil
    115}
    116
    117type member struct {
    118 kind string
    119 payload string
    120}
    121
    122func parseBatch(payload string) ([]member, error) {
    123 var out []member
    124 for _, line := range strings.Split(payload, "\n") {
    125 line = strings.TrimSpace(line)
    126 if line == "" {
    127 continue
    128 }
    129 sp := strings.Index(line, " ")
    130 if sp <= 0 {
    131 // A member with no payload is almost always a typo, and a batch is
    132 // the wrong place to find out.
    133 return nil, govErr("expected `<kind> <payload>`, got: " + line)
    134 }
    135 out = append(out, member{kind: line[:sp], payload: strings.TrimSpace(line[sp+1:])})
    136 }
    137 if len(out) < 2 {
    138 return nil, govErr("a batch needs at least two members; propose the kind directly")
    139 }
    140 if len(out) > maxBatch {
    141 return nil, govErr("too many members in one batch")
    142 }
    143 return out, nil
    144}
    145