github.com/phillinzzz/newBsc@v1.1.6/consensus/parlia/snapshot.go (about) 1 // Copyright 2017 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package parlia 18 19 import ( 20 "bytes" 21 "encoding/hex" 22 "encoding/json" 23 "errors" 24 "math/big" 25 "sort" 26 27 "github.com/phillinzzz/newBsc/common" 28 "github.com/phillinzzz/newBsc/consensus" 29 "github.com/phillinzzz/newBsc/core/types" 30 "github.com/phillinzzz/newBsc/ethdb" 31 "github.com/phillinzzz/newBsc/internal/ethapi" 32 "github.com/phillinzzz/newBsc/params" 33 lru "github.com/hashicorp/golang-lru" 34 ) 35 36 // Snapshot is the state of the validatorSet at a given point. 37 type Snapshot struct { 38 config *params.ParliaConfig // Consensus engine parameters to fine tune behavior 39 ethAPI *ethapi.PublicBlockChainAPI 40 sigCache *lru.ARCCache // Cache of recent block signatures to speed up ecrecover 41 42 Number uint64 `json:"number"` // Block number where the snapshot was created 43 Hash common.Hash `json:"hash"` // Block hash where the snapshot was created 44 Validators map[common.Address]struct{} `json:"validators"` // Set of authorized validators at this moment 45 Recents map[uint64]common.Address `json:"recents"` // Set of recent validators for spam protections 46 RecentForkHashes map[uint64]string `json:"recent_fork_hashes"` // Set of recent forkHash 47 } 48 49 // newSnapshot creates a new snapshot with the specified startup parameters. This 50 // method does not initialize the set of recent validators, so only ever use it for 51 // the genesis block. 52 func newSnapshot( 53 config *params.ParliaConfig, 54 sigCache *lru.ARCCache, 55 number uint64, 56 hash common.Hash, 57 validators []common.Address, 58 ethAPI *ethapi.PublicBlockChainAPI, 59 ) *Snapshot { 60 snap := &Snapshot{ 61 config: config, 62 ethAPI: ethAPI, 63 sigCache: sigCache, 64 Number: number, 65 Hash: hash, 66 Recents: make(map[uint64]common.Address), 67 RecentForkHashes: make(map[uint64]string), 68 Validators: make(map[common.Address]struct{}), 69 } 70 for _, v := range validators { 71 snap.Validators[v] = struct{}{} 72 } 73 return snap 74 } 75 76 // validatorsAscending implements the sort interface to allow sorting a list of addresses 77 type validatorsAscending []common.Address 78 79 func (s validatorsAscending) Len() int { return len(s) } 80 func (s validatorsAscending) Less(i, j int) bool { return bytes.Compare(s[i][:], s[j][:]) < 0 } 81 func (s validatorsAscending) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 82 83 // loadSnapshot loads an existing snapshot from the database. 84 func loadSnapshot(config *params.ParliaConfig, sigCache *lru.ARCCache, db ethdb.Database, hash common.Hash, ethAPI *ethapi.PublicBlockChainAPI) (*Snapshot, error) { 85 blob, err := db.Get(append([]byte("parlia-"), hash[:]...)) 86 if err != nil { 87 return nil, err 88 } 89 snap := new(Snapshot) 90 if err := json.Unmarshal(blob, snap); err != nil { 91 return nil, err 92 } 93 snap.config = config 94 snap.sigCache = sigCache 95 snap.ethAPI = ethAPI 96 97 return snap, nil 98 } 99 100 // store inserts the snapshot into the database. 101 func (s *Snapshot) store(db ethdb.Database) error { 102 blob, err := json.Marshal(s) 103 if err != nil { 104 return err 105 } 106 return db.Put(append([]byte("parlia-"), s.Hash[:]...), blob) 107 } 108 109 // copy creates a deep copy of the snapshot 110 func (s *Snapshot) copy() *Snapshot { 111 cpy := &Snapshot{ 112 config: s.config, 113 ethAPI: s.ethAPI, 114 sigCache: s.sigCache, 115 Number: s.Number, 116 Hash: s.Hash, 117 Validators: make(map[common.Address]struct{}), 118 Recents: make(map[uint64]common.Address), 119 RecentForkHashes: make(map[uint64]string), 120 } 121 122 for v := range s.Validators { 123 cpy.Validators[v] = struct{}{} 124 } 125 for block, v := range s.Recents { 126 cpy.Recents[block] = v 127 } 128 for block, id := range s.RecentForkHashes { 129 cpy.RecentForkHashes[block] = id 130 } 131 return cpy 132 } 133 134 func (s *Snapshot) isMajorityFork(forkHash string) bool { 135 ally := 0 136 for _, h := range s.RecentForkHashes { 137 if h == forkHash { 138 ally++ 139 } 140 } 141 return ally > len(s.RecentForkHashes)/2 142 } 143 144 func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderReader, parents []*types.Header, chainId *big.Int) (*Snapshot, error) { 145 // Allow passing in no headers for cleaner code 146 if len(headers) == 0 { 147 return s, nil 148 } 149 // Sanity check that the headers can be applied 150 for i := 0; i < len(headers)-1; i++ { 151 if headers[i+1].Number.Uint64() != headers[i].Number.Uint64()+1 { 152 return nil, errOutOfRangeChain 153 } 154 if !bytes.Equal(headers[i+1].ParentHash.Bytes(), headers[i].Hash().Bytes()) { 155 return nil, errBlockHashInconsistent 156 } 157 } 158 if headers[0].Number.Uint64() != s.Number+1 { 159 return nil, errOutOfRangeChain 160 } 161 if !bytes.Equal(headers[0].ParentHash.Bytes(), s.Hash.Bytes()) { 162 return nil, errBlockHashInconsistent 163 } 164 // Iterate through the headers and create a new snapshot 165 snap := s.copy() 166 167 for _, header := range headers { 168 number := header.Number.Uint64() 169 // Delete the oldest validator from the recent list to allow it signing again 170 if limit := uint64(len(snap.Validators)/2 + 1); number >= limit { 171 delete(snap.Recents, number-limit) 172 } 173 if limit := uint64(len(snap.Validators)); number >= limit { 174 delete(snap.RecentForkHashes, number-limit) 175 } 176 // Resolve the authorization key and check against signers 177 validator, err := ecrecover(header, s.sigCache, chainId) 178 if err != nil { 179 return nil, err 180 } 181 if _, ok := snap.Validators[validator]; !ok { 182 return nil, errUnauthorizedValidator 183 } 184 for _, recent := range snap.Recents { 185 if recent == validator { 186 return nil, errRecentlySigned 187 } 188 } 189 snap.Recents[number] = validator 190 // change validator set 191 if number > 0 && number%s.config.Epoch == uint64(len(snap.Validators)/2) { 192 checkpointHeader := FindAncientHeader(header, uint64(len(snap.Validators)/2), chain, parents) 193 if checkpointHeader == nil { 194 return nil, consensus.ErrUnknownAncestor 195 } 196 197 validatorBytes := checkpointHeader.Extra[extraVanity : len(checkpointHeader.Extra)-extraSeal] 198 // get validators from headers and use that for new validator set 199 newValArr, err := ParseValidators(validatorBytes) 200 if err != nil { 201 return nil, err 202 } 203 newVals := make(map[common.Address]struct{}, len(newValArr)) 204 for _, val := range newValArr { 205 newVals[val] = struct{}{} 206 } 207 oldLimit := len(snap.Validators)/2 + 1 208 newLimit := len(newVals)/2 + 1 209 if newLimit < oldLimit { 210 for i := 0; i < oldLimit-newLimit; i++ { 211 delete(snap.Recents, number-uint64(newLimit)-uint64(i)) 212 } 213 } 214 oldLimit = len(snap.Validators) 215 newLimit = len(newVals) 216 if newLimit < oldLimit { 217 for i := 0; i < oldLimit-newLimit; i++ { 218 delete(snap.RecentForkHashes, number-uint64(newLimit)-uint64(i)) 219 } 220 } 221 snap.Validators = newVals 222 } 223 snap.RecentForkHashes[number] = hex.EncodeToString(header.Extra[extraVanity-nextForkHashSize : extraVanity]) 224 } 225 snap.Number += uint64(len(headers)) 226 snap.Hash = headers[len(headers)-1].Hash() 227 return snap, nil 228 } 229 230 // validators retrieves the list of validators in ascending order. 231 func (s *Snapshot) validators() []common.Address { 232 validators := make([]common.Address, 0, len(s.Validators)) 233 for v := range s.Validators { 234 validators = append(validators, v) 235 } 236 sort.Sort(validatorsAscending(validators)) 237 return validators 238 } 239 240 // inturn returns if a validator at a given block height is in-turn or not. 241 func (s *Snapshot) inturn(validator common.Address) bool { 242 validators := s.validators() 243 offset := (s.Number + 1) % uint64(len(validators)) 244 return validators[offset] == validator 245 } 246 247 func (s *Snapshot) enoughDistance(validator common.Address, header *types.Header) bool { 248 idx := s.indexOfVal(validator) 249 if idx < 0 { 250 return true 251 } 252 validatorNum := int64(len(s.validators())) 253 if validatorNum == 1 { 254 return true 255 } 256 if validator == header.Coinbase { 257 return false 258 } 259 offset := (int64(s.Number) + 1) % validatorNum 260 if int64(idx) >= offset { 261 return int64(idx)-offset >= validatorNum-2 262 } else { 263 return validatorNum+int64(idx)-offset >= validatorNum-2 264 } 265 } 266 267 func (s *Snapshot) indexOfVal(validator common.Address) int { 268 validators := s.validators() 269 for idx, val := range validators { 270 if val == validator { 271 return idx 272 } 273 } 274 return -1 275 } 276 277 func (s *Snapshot) supposeValidator() common.Address { 278 validators := s.validators() 279 index := (s.Number + 1) % uint64(len(validators)) 280 return validators[index] 281 } 282 283 func ParseValidators(validatorsBytes []byte) ([]common.Address, error) { 284 if len(validatorsBytes)%validatorBytesLength != 0 { 285 return nil, errors.New("invalid validators bytes") 286 } 287 n := len(validatorsBytes) / validatorBytesLength 288 result := make([]common.Address, n) 289 for i := 0; i < n; i++ { 290 address := make([]byte, validatorBytesLength) 291 copy(address, validatorsBytes[i*validatorBytesLength:(i+1)*validatorBytesLength]) 292 result[i] = common.BytesToAddress(address) 293 } 294 return result, nil 295 } 296 297 func FindAncientHeader(header *types.Header, ite uint64, chain consensus.ChainHeaderReader, candidateParents []*types.Header) *types.Header { 298 ancient := header 299 for i := uint64(1); i <= ite; i++ { 300 parentHash := ancient.ParentHash 301 parentHeight := ancient.Number.Uint64() - 1 302 found := false 303 if len(candidateParents) > 0 { 304 index := sort.Search(len(candidateParents), func(i int) bool { 305 return candidateParents[i].Number.Uint64() >= parentHeight 306 }) 307 if index < len(candidateParents) && candidateParents[index].Number.Uint64() == parentHeight && 308 candidateParents[index].Hash() == parentHash { 309 ancient = candidateParents[index] 310 found = true 311 } 312 } 313 if !found { 314 ancient = chain.GetHeader(parentHash, parentHeight) 315 found = true 316 } 317 if ancient == nil || !found { 318 return nil 319 } 320 } 321 return ancient 322 }