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}