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