github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/execution/state/validators.go (about) 1 package state 2 3 import ( 4 "math/big" 5 6 "github.com/hyperledger/burrow/encoding" 7 "github.com/hyperledger/burrow/genesis" 8 9 "github.com/hyperledger/burrow/acm/validator" 10 "github.com/hyperledger/burrow/storage" 11 12 "github.com/hyperledger/burrow/crypto" 13 ) 14 15 // Initialises the validator Ring from the validator storage in forest 16 func LoadValidatorRing(version int64, ringSize int, 17 getImmutable func(version int64) (*storage.ImmutableForest, error)) (*validator.Ring, error) { 18 19 // In this method we have to page through previous version of the tree in order to reconstruct the in-memory 20 // ring structure. The corner cases are a little subtle but printing the buckets helps 21 22 // The basic idea is to load each version of the tree ringSize back, work out the difference that must have occurred 23 // between each bucket in the ring, and apply each diff to the ring. Once the ring is full it is symmetrical (up to 24 // a reindexing). If we are loading a chain whose height is less than the ring size we need to get the initial state 25 // correct 26 27 startVersion := version - int64(ringSize) 28 if startVersion < 1 { 29 // The ring will not be fully populated 30 startVersion = 1 31 } 32 var err error 33 // Read state to pull immutable forests from 34 rs := &ReadState{} 35 // Start with an empty ring - we want the initial bucket to have no cumulative power 36 ring := validator.NewRing(nil, ringSize) 37 // Load the IAVL state 38 rs.Forest, err = getImmutable(startVersion) 39 if err != nil { 40 return nil, err 41 } 42 // Write the validator state at startVersion from IAVL tree into the ring's current bucket delta 43 err = validator.Write(ring, rs) 44 if err != nil { 45 return nil, err 46 } 47 // Rotate, now we have [ {bucket 0: cum: {}, delta: {start version changes} }, {bucket 1: cum: {start version changes}, delta {}, ... ] 48 // which is what we need (in particular we need this initial state if we are loading into a incompletely populated ring 49 _, _, err = ring.Rotate() 50 if err != nil { 51 return nil, err 52 } 53 54 // Rebuild validator Ring 55 for v := startVersion + 1; v <= version; v++ { 56 // Update IAVL read state to version of interest 57 rs.Forest, err = getImmutable(v) 58 if err != nil { 59 return nil, err 60 } 61 // Calculate the difference between the rings current cum and what is in state at this version 62 diff, err := validator.Diff(ring.CurrentSet(), rs) 63 if err != nil { 64 return nil, err 65 } 66 // Write that diff into the ring (just like it was when it was originally written to setPower) 67 err = validator.Write(ring, diff) 68 if err != nil { 69 return nil, err 70 } 71 // Rotate just like it was on the original commit 72 _, _, err = ring.Rotate() 73 if err != nil { 74 return nil, err 75 } 76 } 77 // Our ring should be the same up to symmetry in its index so we reindex to regain equality with the version we are loading 78 // This is the head index we would have had if we had started from version 1 like the chain did 79 ring.ReIndex(int(version % int64(ringSize))) 80 return ring, err 81 } 82 83 func (ws *writeState) MakeGenesisValidators(genesisDoc *genesis.GenesisDoc) error { 84 for _, gv := range genesisDoc.Validators { 85 _, err := ws.SetPower(gv.PublicKey, new(big.Int).SetUint64(gv.Amount)) 86 if err != nil { 87 return err 88 } 89 } 90 return nil 91 } 92 93 func (s *ImmutableState) Power(id crypto.Address) (*big.Int, error) { 94 tree, err := s.Forest.Reader(keys.Validator.Prefix()) 95 if err != nil { 96 return nil, err 97 } 98 bs, err := tree.Get(keys.Validator.KeyNoPrefix(id)) 99 if err != nil { 100 return nil, err 101 } else if len(bs) == 0 { 102 return new(big.Int), nil 103 } 104 v := new(validator.Validator) 105 err = encoding.Decode(bs, v) 106 if err != nil { 107 return nil, err 108 } 109 return v.BigPower(), nil 110 } 111 112 func (s *ImmutableState) IterateValidators(fn func(id crypto.Addressable, power *big.Int) error) error { 113 tree, err := s.Forest.Reader(keys.Validator.Prefix()) 114 if err != nil { 115 return err 116 } 117 return tree.Iterate(nil, nil, true, func(_, value []byte) error { 118 v := new(validator.Validator) 119 err = encoding.Decode(value, v) 120 if err != nil { 121 return err 122 } 123 return fn(v, v.BigPower()) 124 }) 125 } 126 127 func (ws *writeState) SetPower(id *crypto.PublicKey, power *big.Int) (*big.Int, error) { 128 // SetPower in ring 129 flow, err := ws.ring.SetPower(id, power) 130 if err != nil { 131 return nil, err 132 } 133 // Set power in versioned state 134 return flow, ws.setPower(id, power) 135 } 136 137 func (ws *writeState) setPower(id *crypto.PublicKey, power *big.Int) error { 138 return ws.forest.Write(keys.Validator.Prefix(), func(tree *storage.RWTree) error { 139 key := keys.Validator.KeyNoPrefix(id.GetAddress()) 140 if power.Sign() == 0 { 141 tree.Delete(key) 142 return nil 143 } 144 bs, err := encoding.Encode(validator.New(id, power)) 145 if err != nil { 146 return err 147 } 148 tree.Set(key, bs) 149 return nil 150 }) 151 }