Search Apps Documentation Source Content File Folder Download Copy Actions Download

validators.gno

2.59 Kb ยท 118 lines
  1package validators
  2
  3import (
  4	"chain"
  5	"chain/runtime"
  6
  7	"gno.land/p/nt/avl"
  8	"gno.land/p/nt/seqid"
  9	"gno.land/p/nt/ufmt"
 10	"gno.land/p/sys/validators"
 11)
 12
 13var (
 14	vp      validators.ValsetProtocol // p is the underlying validator set protocol
 15	changes *avl.Tree                 // 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, exists := changes.Get(id)
 73	if !exists {
 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(size-maxDisplay, 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}