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