Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

validators.gno

2.59 Kb · 118 lines
  1package validators
  2
  3import (
  4	"chain"
  5	"chain/runtime"
  6
  7	"gno.land/p/nt/bptree/v0"
  8	"gno.land/p/nt/seqid/v0"
  9	"gno.land/p/nt/ufmt/v0"
 10	"gno.land/p/sys/validators/v0"
 11)
 12
 13var (
 14	vp      validators.ValsetProtocol // p is the underlying validator set protocol
 15	changes *bptree.BPTree            // changes holds any valset changes; seqid(block number) -> []change
 16)
 17
 18// change represents a single valset change, tied to a specific block number
 19type change struct {
 20	blockNum  int64                // the block number associated with the valset change
 21	validator validators.Validator // the validator update
 22}
 23
 24// addValidator adds a new validator to the validator set.
 25// If the validator is already present, the method errors out
 26func addValidator(validator validators.Validator) {
 27	val, err := vp.AddValidator(validator.Address, validator.PubKey, validator.VotingPower)
 28	if err != nil {
 29		panic(err)
 30	}
 31
 32	// Validator added, note the change
 33	ch := change{
 34		blockNum:  runtime.ChainHeight(),
 35		validator: val,
 36	}
 37
 38	saveChange(ch)
 39
 40	// Emit the validator set change
 41	chain.Emit(validators.ValidatorAddedEvent)
 42}
 43
 44// removeValidator removes the given validator from the set.
 45// If the validator is not present in the set, the method errors out
 46func removeValidator(address_XXX address) {
 47	val, err := vp.RemoveValidator(address_XXX)
 48	if err != nil {
 49		panic(err)
 50	}
 51
 52	// Validator removed, note the change
 53	ch := change{
 54		blockNum: runtime.ChainHeight(),
 55		validator: validators.Validator{
 56			Address:     val.Address,
 57			PubKey:      val.PubKey,
 58			VotingPower: 0, // nullified the voting power indicates removal
 59		},
 60	}
 61
 62	saveChange(ch)
 63
 64	// Emit the validator set change
 65	chain.Emit(validators.ValidatorRemovedEvent)
 66}
 67
 68// saveChange saves the valset change
 69func saveChange(ch change) {
 70	id := getBlockID(ch.blockNum)
 71
 72	setRaw := changes.Get(id)
 73	if setRaw == nil {
 74		changes.Set(id, []change{ch})
 75
 76		return
 77	}
 78
 79	// Save the change
 80	set := setRaw.([]change)
 81	set = append(set, ch)
 82
 83	changes.Set(id, set)
 84}
 85
 86// getBlockID converts the block number to a sequential ID
 87func getBlockID(blockNum int64) string {
 88	return seqid.ID(uint64(blockNum)).String()
 89}
 90
 91func Render(_ string) string {
 92	var (
 93		size       = changes.Size()
 94		maxDisplay = 10
 95	)
 96
 97	if size == 0 {
 98		return "No valset changes to apply."
 99	}
100
101	output := "Valset changes:\n"
102	changes.ReverseIterateByOffset(0, maxDisplay, func(_ string, value any) bool {
103		chs := value.([]change)
104
105		for _, ch := range chs {
106			output += ufmt.Sprintf(
107				"- #%d: %s (%d)\n",
108				ch.blockNum,
109				ch.validator.Address.String(),
110				ch.validator.VotingPower,
111			)
112		}
113
114		return false
115	})
116
117	return output
118}