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  }