poa.gno

2.48 Kb ยท 106 lines
  1package poa
  2
  3import (
  4	"errors"
  5	"std"
  6
  7	"gno.land/p/nt/avl"
  8	"gno.land/p/sys/validators"
  9)
 10
 11var ErrInvalidVotingPower = errors.New("invalid voting power")
 12
 13// PoA specifies the Proof of Authority validator set, with simple add / remove constraints.
 14//
 15// To add:
 16// - proposed validator must not be part of the set already
 17// - proposed validator voting power must be > 0
 18//
 19// To remove:
 20// - proposed validator must be part of the set already
 21type PoA struct {
 22	validators *avl.Tree // std.Address -> validators.Validator
 23}
 24
 25// NewPoA creates a new empty Proof of Authority validator set
 26func NewPoA(opts ...Option) *PoA {
 27	// Create the empty set
 28	p := &PoA{
 29		validators: avl.NewTree(),
 30	}
 31
 32	// Apply the options
 33	for _, opt := range opts {
 34		opt(p)
 35	}
 36
 37	return p
 38}
 39
 40func (p *PoA) AddValidator(address_XXX std.Address, pubKey string, power uint64) (validators.Validator, error) {
 41	// Validate that the operation is a valid call.
 42	// Check if the validator is already in the set
 43	if p.IsValidator(address_XXX) {
 44		return validators.Validator{}, validators.ErrValidatorExists
 45	}
 46
 47	// Make sure the voting power > 0
 48	if power == 0 {
 49		return validators.Validator{}, ErrInvalidVotingPower
 50	}
 51
 52	v := validators.Validator{
 53		Address:     address_XXX,
 54		PubKey:      pubKey, // TODO: in the future, verify the public key
 55		VotingPower: power,
 56	}
 57
 58	// Add the validator to the set
 59	p.validators.Set(address_XXX.String(), v)
 60
 61	return v, nil
 62}
 63
 64func (p *PoA) RemoveValidator(address_XXX std.Address) (validators.Validator, error) {
 65	// Validate that the operation is a valid call
 66	// Fetch the validator
 67	validator, err := p.GetValidator(address_XXX)
 68	if err != nil {
 69		return validators.Validator{}, err
 70	}
 71
 72	// Remove the validator from the set
 73	p.validators.Remove(address_XXX.String())
 74
 75	return validator, nil
 76}
 77
 78func (p *PoA) IsValidator(address_XXX std.Address) bool {
 79	_, exists := p.validators.Get(address_XXX.String())
 80
 81	return exists
 82}
 83
 84func (p *PoA) GetValidator(address_XXX std.Address) (validators.Validator, error) {
 85	validatorRaw, exists := p.validators.Get(address_XXX.String())
 86	if !exists {
 87		return validators.Validator{}, validators.ErrValidatorMissing
 88	}
 89
 90	validator := validatorRaw.(validators.Validator)
 91
 92	return validator, nil
 93}
 94
 95func (p *PoA) GetValidators() []validators.Validator {
 96	vals := make([]validators.Validator, 0, p.validators.Size())
 97
 98	p.validators.Iterate("", "", func(_ string, value any) bool {
 99		validator := value.(validators.Validator)
100		vals = append(vals, validator)
101
102		return false
103	})
104
105	return vals
106}