github.com/palisadeinc/bor@v0.0.0-20230615125219-ab7196213d15/consensus/bor/snapshot.go (about) 1 package bor 2 3 import ( 4 "encoding/json" 5 6 "github.com/ethereum/go-ethereum/consensus/bor/valset" 7 8 lru "github.com/hashicorp/golang-lru" 9 10 "github.com/ethereum/go-ethereum/common" 11 "github.com/ethereum/go-ethereum/core/types" 12 "github.com/ethereum/go-ethereum/ethdb" 13 "github.com/ethereum/go-ethereum/params" 14 ) 15 16 // Snapshot is the state of the authorization voting at a given point in time. 17 type Snapshot struct { 18 config *params.BorConfig // Consensus engine parameters to fine tune behavior 19 sigcache *lru.ARCCache // Cache of recent block signatures to speed up ecrecover 20 21 Number uint64 `json:"number"` // Block number where the snapshot was created 22 Hash common.Hash `json:"hash"` // Block hash where the snapshot was created 23 ValidatorSet *valset.ValidatorSet `json:"validatorSet"` // Validator set at this moment 24 Recents map[uint64]common.Address `json:"recents"` // Set of recent signers for spam protections 25 } 26 27 // newSnapshot creates a new snapshot with the specified startup parameters. This 28 // method does not initialize the set of recent signers, so only ever use if for 29 // the genesis block. 30 func newSnapshot( 31 config *params.BorConfig, 32 sigcache *lru.ARCCache, 33 number uint64, 34 hash common.Hash, 35 validators []*valset.Validator, 36 ) *Snapshot { 37 snap := &Snapshot{ 38 config: config, 39 sigcache: sigcache, 40 Number: number, 41 Hash: hash, 42 ValidatorSet: valset.NewValidatorSet(validators), 43 Recents: make(map[uint64]common.Address), 44 } 45 46 return snap 47 } 48 49 // loadSnapshot loads an existing snapshot from the database. 50 func loadSnapshot(config *params.BorConfig, sigcache *lru.ARCCache, db ethdb.Database, hash common.Hash) (*Snapshot, error) { 51 blob, err := db.Get(append([]byte("bor-"), hash[:]...)) 52 if err != nil { 53 return nil, err 54 } 55 56 snap := new(Snapshot) 57 58 if err := json.Unmarshal(blob, snap); err != nil { 59 return nil, err 60 } 61 62 snap.ValidatorSet.UpdateValidatorMap() 63 64 snap.config = config 65 snap.sigcache = sigcache 66 67 // update total voting power 68 if err := snap.ValidatorSet.UpdateTotalVotingPower(); err != nil { 69 return nil, err 70 } 71 72 return snap, nil 73 } 74 75 // store inserts the snapshot into the database. 76 func (s *Snapshot) store(db ethdb.Database) error { 77 blob, err := json.Marshal(s) 78 if err != nil { 79 return err 80 } 81 82 return db.Put(append([]byte("bor-"), s.Hash[:]...), blob) 83 } 84 85 // copy creates a deep copy of the snapshot, though not the individual votes. 86 func (s *Snapshot) copy() *Snapshot { 87 cpy := &Snapshot{ 88 config: s.config, 89 sigcache: s.sigcache, 90 Number: s.Number, 91 Hash: s.Hash, 92 ValidatorSet: s.ValidatorSet.Copy(), 93 Recents: make(map[uint64]common.Address), 94 } 95 for block, signer := range s.Recents { 96 cpy.Recents[block] = signer 97 } 98 99 return cpy 100 } 101 102 func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) { 103 // Allow passing in no headers for cleaner code 104 if len(headers) == 0 { 105 return s, nil 106 } 107 // Sanity check that the headers can be applied 108 for i := 0; i < len(headers)-1; i++ { 109 if headers[i+1].Number.Uint64() != headers[i].Number.Uint64()+1 { 110 return nil, errOutOfRangeChain 111 } 112 } 113 114 if headers[0].Number.Uint64() != s.Number+1 { 115 return nil, errOutOfRangeChain 116 } 117 // Iterate through the headers and create a new snapshot 118 snap := s.copy() 119 120 for _, header := range headers { 121 // Remove any votes on checkpoint blocks 122 number := header.Number.Uint64() 123 124 // Delete the oldest signer from the recent list to allow it signing again 125 if number >= s.config.CalculateSprint(number) { 126 delete(snap.Recents, number-s.config.CalculateSprint(number)) 127 } 128 129 // Resolve the authorization key and check against signers 130 signer, err := ecrecover(header, s.sigcache, s.config) 131 if err != nil { 132 return nil, err 133 } 134 135 // check if signer is in validator set 136 if !snap.ValidatorSet.HasAddress(signer) { 137 return nil, &UnauthorizedSignerError{number, signer.Bytes()} 138 } 139 140 if _, err = snap.GetSignerSuccessionNumber(signer); err != nil { 141 return nil, err 142 } 143 144 // add recents 145 snap.Recents[number] = signer 146 147 // change validator set and change proposer 148 if number > 0 && (number+1)%s.config.CalculateSprint(number) == 0 { 149 if err := validateHeaderExtraField(header.Extra); err != nil { 150 return nil, err 151 } 152 153 validatorBytes := header.Extra[extraVanity : len(header.Extra)-extraSeal] 154 155 // get validators from headers and use that for new validator set 156 newVals, _ := valset.ParseValidators(validatorBytes) 157 v := getUpdatedValidatorSet(snap.ValidatorSet.Copy(), newVals) 158 v.IncrementProposerPriority(1) 159 snap.ValidatorSet = v 160 } 161 } 162 163 snap.Number += uint64(len(headers)) 164 snap.Hash = headers[len(headers)-1].Hash() 165 166 return snap, nil 167 } 168 169 // GetSignerSuccessionNumber returns the relative position of signer in terms of the in-turn proposer 170 func (s *Snapshot) GetSignerSuccessionNumber(signer common.Address) (int, error) { 171 validators := s.ValidatorSet.Validators 172 proposer := s.ValidatorSet.GetProposer().Address 173 proposerIndex, _ := s.ValidatorSet.GetByAddress(proposer) 174 175 if proposerIndex == -1 { 176 return -1, &UnauthorizedProposerError{s.Number, proposer.Bytes()} 177 } 178 179 signerIndex, _ := s.ValidatorSet.GetByAddress(signer) 180 181 if signerIndex == -1 { 182 return -1, &UnauthorizedSignerError{s.Number, signer.Bytes()} 183 } 184 185 tempIndex := signerIndex 186 if proposerIndex != tempIndex { 187 if tempIndex < proposerIndex { 188 tempIndex = tempIndex + len(validators) 189 } 190 } 191 192 return tempIndex - proposerIndex, nil 193 } 194 195 // signers retrieves the list of authorized signers in ascending order. 196 func (s *Snapshot) signers() []common.Address { 197 sigs := make([]common.Address, 0, len(s.ValidatorSet.Validators)) 198 for _, sig := range s.ValidatorSet.Validators { 199 sigs = append(sigs, sig.Address) 200 } 201 202 return sigs 203 } 204 205 // Difficulty returns the difficulty for a particular signer at the current snapshot number 206 func Difficulty(validatorSet *valset.ValidatorSet, signer common.Address) uint64 { 207 // if signer is empty 208 if signer == (common.Address{}) { 209 return 1 210 } 211 212 validators := validatorSet.Validators 213 proposer := validatorSet.GetProposer().Address 214 totalValidators := len(validators) 215 216 proposerIndex, _ := validatorSet.GetByAddress(proposer) 217 signerIndex, _ := validatorSet.GetByAddress(signer) 218 219 // temp index 220 tempIndex := signerIndex 221 if tempIndex < proposerIndex { 222 tempIndex = tempIndex + totalValidators 223 } 224 225 return uint64(totalValidators - (tempIndex - proposerIndex)) 226 }