github.com/gochain-io/gochain@v2.2.26+incompatible/consensus/clique/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 clique
    18  
    19  import (
    20  	"bytes"
    21  	"context"
    22  	"encoding/json"
    23  	"fmt"
    24  
    25  	"github.com/gochain-io/gochain/common"
    26  	"github.com/gochain-io/gochain/core/types"
    27  	"github.com/gochain-io/gochain/params"
    28  	"github.com/hashicorp/golang-lru"
    29  )
    30  
    31  // Vote represents a single vote that an authorized signer made to modify the
    32  // list of authorizations.
    33  type Vote struct {
    34  	Signer    common.Address `json:"signer"`    // Authorized signer that cast this vote
    35  	Block     uint64         `json:"block"`     // Block number the vote was cast in (expire old votes)
    36  	Address   common.Address `json:"address"`   // Account being voted on to change its authorization
    37  	Authorize bool           `json:"authorize"` // Whether to authorize or deauthorize the voted account
    38  }
    39  
    40  // Tally is a simple vote tally to keep the current score of votes. Votes that
    41  // go against the proposal aren't counted since it's equivalent to not voting.
    42  type Tally struct {
    43  	Authorize bool `json:"authorize"` // Whether the vote is about authorizing or kicking someone
    44  	Votes     int  `json:"votes"`     // Number of votes until now wanting to pass the proposal
    45  }
    46  
    47  // Snapshot is the state of the authorization voting at a given point in time.
    48  type Snapshot struct {
    49  	config   *params.CliqueConfig // Consensus engine parameters to fine tune behavior
    50  	sigcache *lru.ARCCache        // Cache of recent block signatures to speed up ecrecover
    51  
    52  	Number  uint64                      `json:"number"`  // Block number where the snapshot was created
    53  	Hash    common.Hash                 `json:"hash"`    // Block hash where the snapshot was created
    54  	Signers map[common.Address]uint64   `json:"signers"` // Each authorized signer at this moment and their most recently signed block
    55  	Voters  map[common.Address]struct{} `json:"voters"`  // Set of authorized voters at this moment
    56  	Votes   []*Vote                     `json:"votes"`   // List of votes cast in chronological order
    57  	Tally   map[common.Address]Tally    `json:"tally"`   // Current vote tally to avoid recalculating
    58  }
    59  
    60  // newGenesisSnapshot creates a new snapshot with the specified startup parameters. This
    61  // method does not initialize the signers most recently signed blocks, so only ever use if for
    62  // the genesis block.
    63  func newGenesisSnapshot(config *params.CliqueConfig, sigcache *lru.ARCCache, number uint64, hash common.Hash, signers, voters []common.Address) *Snapshot {
    64  	snap := &Snapshot{
    65  		config:   config,
    66  		sigcache: sigcache,
    67  		Number:   number,
    68  		Hash:     hash,
    69  		Signers:  make(map[common.Address]uint64),
    70  		Voters:   make(map[common.Address]struct{}),
    71  		Tally:    make(map[common.Address]Tally),
    72  	}
    73  	for _, signer := range signers {
    74  		snap.Signers[signer] = 0
    75  	}
    76  	for _, voter := range voters {
    77  		snap.Voters[voter] = struct{}{}
    78  	}
    79  	return snap
    80  }
    81  
    82  // loadSnapshot loads an existing snapshot from the database.
    83  func loadSnapshot(config *params.CliqueConfig, sigcache *lru.ARCCache, db common.Database, hash common.Hash) (*Snapshot, error) {
    84  	blob, err := db.GlobalTable().Get(append([]byte("clique-"), hash[:]...))
    85  	if err != nil {
    86  		return nil, err
    87  	}
    88  	snap := new(Snapshot)
    89  	if err := json.Unmarshal(blob, snap); err != nil {
    90  		return nil, err
    91  	}
    92  	snap.config = config
    93  	snap.sigcache = sigcache
    94  
    95  	return snap, nil
    96  }
    97  
    98  // store inserts the snapshot into the database.
    99  func (s *Snapshot) store(db common.Database) error {
   100  	blob, err := json.Marshal(s)
   101  	if err != nil {
   102  		return err
   103  	}
   104  	return db.GlobalTable().Put(append([]byte("clique-"), s.Hash[:]...), blob)
   105  }
   106  
   107  // copy creates a deep copy of the snapshot, though not the individual votes.
   108  func (s *Snapshot) copy() *Snapshot {
   109  	cpy := &Snapshot{
   110  		config:   s.config,
   111  		sigcache: s.sigcache,
   112  		Number:   s.Number,
   113  		Hash:     s.Hash,
   114  		Signers:  make(map[common.Address]uint64),
   115  		Voters:   make(map[common.Address]struct{}),
   116  		Votes:    make([]*Vote, len(s.Votes)),
   117  		Tally:    make(map[common.Address]Tally),
   118  	}
   119  	for signer, signed := range s.Signers {
   120  		cpy.Signers[signer] = signed
   121  	}
   122  	for voter := range s.Voters {
   123  		cpy.Voters[voter] = struct{}{}
   124  	}
   125  	for address, tally := range s.Tally {
   126  		cpy.Tally[address] = tally
   127  	}
   128  	copy(cpy.Votes, s.Votes)
   129  
   130  	return cpy
   131  }
   132  
   133  // validVote returns whether it makes sense to cast the specified vote in the
   134  // given snapshot context (e.g. don't try to add an already authorized voter or
   135  // remove an not authorized signer).
   136  func (s *Snapshot) validVote(address common.Address, authorize bool, voterElection bool) bool {
   137  	if voterElection {
   138  		_, voter := s.Voters[address]
   139  		return (voter && !authorize) || (!voter && authorize)
   140  	}
   141  	_, signer := s.Signers[address]
   142  	return (signer && !authorize) || (!signer && authorize)
   143  }
   144  
   145  // cast adds a new vote into the tally.
   146  func (s *Snapshot) cast(address common.Address, authorize bool, voterElection bool) bool {
   147  	// Ensure the vote is meaningful
   148  	if !s.validVote(address, authorize, voterElection) {
   149  		return false
   150  	}
   151  	// Cast the vote into an existing or new tally
   152  	if old, ok := s.Tally[address]; ok {
   153  		old.Votes++
   154  		s.Tally[address] = old
   155  	} else {
   156  		s.Tally[address] = Tally{Authorize: authorize, Votes: 1}
   157  	}
   158  	return true
   159  }
   160  
   161  // uncast removes a previously cast vote from the tally.
   162  func (s *Snapshot) uncast(address common.Address, authorize bool) bool {
   163  	// If there's no tally, it's a dangling vote, just drop
   164  	tally, ok := s.Tally[address]
   165  	if !ok {
   166  		return false
   167  	}
   168  	// Ensure we only revert counted votes
   169  	if tally.Authorize != authorize {
   170  		return false
   171  	}
   172  	// Otherwise revert the vote
   173  	if tally.Votes > 1 {
   174  		tally.Votes--
   175  		s.Tally[address] = tally
   176  	} else {
   177  		delete(s.Tally, address)
   178  	}
   179  	return true
   180  }
   181  
   182  // apply creates a new authorization snapshot by applying the given headers to
   183  // the original one.
   184  func (s *Snapshot) apply(ctx context.Context, headers []*types.Header) (*Snapshot, error) {
   185  	// Allow passing in no headers for cleaner code
   186  	if len(headers) == 0 {
   187  		return s, nil
   188  	}
   189  	// Sanity check that the headers can be applied
   190  	for i := 0; i < len(headers)-1; i++ {
   191  		if headers[i+1].Number.Uint64() != headers[i].Number.Uint64()+1 {
   192  			return nil, errInvalidVotingChain
   193  		}
   194  	}
   195  	if headers[0].Number.Uint64() != s.Number+1 {
   196  		return nil, errInvalidVotingChain
   197  	}
   198  	// Iterate through the headers and create a new snapshot
   199  	snap := s.copy()
   200  
   201  	for _, header := range headers {
   202  		// Remove any votes on checkpoint blocks
   203  		number := header.Number.Uint64()
   204  		if number%s.config.Epoch == 0 {
   205  			snap.Votes = nil
   206  			snap.Tally = make(map[common.Address]Tally)
   207  		}
   208  		// Resolve the authorization key and check against signers
   209  		signer, err := ecrecover(header, s.sigcache)
   210  		if err != nil {
   211  			return nil, err
   212  		}
   213  		lastBlockSigned, authorized := snap.Signers[signer]
   214  		if !authorized {
   215  			return nil, fmt.Errorf("%s not authorized to sign", signer.Hex())
   216  		}
   217  		if lastBlockSigned > 0 {
   218  			if next := snap.nextSignableBlockNumber(lastBlockSigned); number < next {
   219  				return nil, fmt.Errorf("%s not authorized to sign %d: signed recently %d, next eligible signature %d", signer.Hex(), number, lastBlockSigned, next)
   220  			}
   221  		}
   222  		snap.Signers[signer] = number
   223  
   224  		// Verify if signer can vote
   225  		if _, ok := snap.Voters[signer]; ok {
   226  
   227  			var voterElection bool
   228  			var candidate common.Address
   229  
   230  			if ExtraHasVote(header.Extra) {
   231  				candidate = ExtraCandidate(header.Extra)
   232  				voterElection = ExtraIsVoterElection(header.Extra)
   233  			}
   234  			// Header authorized, discard any previous votes from the voter
   235  			for i, vote := range snap.Votes {
   236  				if vote.Signer == signer && vote.Address == candidate {
   237  					// Uncast the vote from the cached tally
   238  					snap.uncast(vote.Address, vote.Authorize)
   239  
   240  					// Uncast the vote from the chronological list
   241  					snap.Votes = append(snap.Votes[:i], snap.Votes[i+1:]...)
   242  					break // only one vote allowed
   243  				}
   244  			}
   245  			// Tally up the new vote from the signer
   246  			var authorize bool
   247  			switch {
   248  			case bytes.Equal(header.Nonce[:], nonceAuthVote):
   249  				authorize = true
   250  			case bytes.Equal(header.Nonce[:], nonceDropVote):
   251  				authorize = false
   252  			default:
   253  				return nil, errInvalidVote
   254  			}
   255  
   256  			if snap.cast(candidate, authorize, voterElection) {
   257  				snap.Votes = append(snap.Votes, &Vote{
   258  					Signer:    signer,
   259  					Block:     number,
   260  					Address:   candidate,
   261  					Authorize: authorize,
   262  				})
   263  			}
   264  			// If the vote passed, update the list of signers or voters
   265  			if tally := snap.Tally[candidate]; tally.Votes > len(snap.Voters)/2 {
   266  				if tally.Authorize {
   267  					_, signer := snap.Signers[candidate]
   268  					if !signer {
   269  						snap.Signers[candidate] = 0
   270  					} else {
   271  						snap.Voters[candidate] = struct{}{}
   272  					}
   273  				} else {
   274  					_, voter := snap.Voters[candidate]
   275  					if !voter {
   276  						delete(snap.Signers, candidate)
   277  					} else {
   278  						delete(snap.Voters, candidate)
   279  						// Discard any previous votes the deauthorized voter cast
   280  						for i := 0; i < len(snap.Votes); i++ {
   281  							if snap.Votes[i].Signer == candidate {
   282  								// Uncast the vote from the cached tally
   283  								snap.uncast(snap.Votes[i].Address, snap.Votes[i].Authorize)
   284  
   285  								// Uncast the vote from the chronological list
   286  								snap.Votes = append(snap.Votes[:i], snap.Votes[i+1:]...)
   287  
   288  								i--
   289  							}
   290  						}
   291  					}
   292  				}
   293  				// Discard any previous votes around the just changed account
   294  				for i := 0; i < len(snap.Votes); i++ {
   295  					if snap.Votes[i].Address == candidate {
   296  						snap.Votes = append(snap.Votes[:i], snap.Votes[i+1:]...)
   297  						i--
   298  					}
   299  				}
   300  				delete(snap.Tally, candidate)
   301  			}
   302  		}
   303  	}
   304  
   305  	snap.Number += uint64(len(headers))
   306  	snap.Hash = headers[len(headers)-1].Hash()
   307  
   308  	return snap, nil
   309  }
   310  
   311  // signers retrieves the list of authorized signers in ascending order.
   312  func (s *Snapshot) signers() []common.Address {
   313  	signers := make([]common.Address, 0, len(s.Signers))
   314  	for signer := range s.Signers {
   315  		signers = append(signers, signer)
   316  	}
   317  	for i := 0; i < len(signers); i++ {
   318  		for j := i + 1; j < len(signers); j++ {
   319  			if bytes.Compare(signers[i][:], signers[j][:]) > 0 {
   320  				signers[i], signers[j] = signers[j], signers[i]
   321  			}
   322  		}
   323  	}
   324  	return signers
   325  }
   326  
   327  // voters retrieves the list of authorized voters in ascending order.
   328  func (s *Snapshot) voters() []common.Address {
   329  	voters := make([]common.Address, 0, len(s.Voters))
   330  	for voter := range s.Voters {
   331  		voters = append(voters, voter)
   332  	}
   333  	for i := 0; i < len(voters); i++ {
   334  		for j := i + 1; j < len(voters); j++ {
   335  			if bytes.Compare(voters[i][:], voters[j][:]) > 0 {
   336  				voters[i], voters[j] = voters[j], voters[i]
   337  			}
   338  		}
   339  	}
   340  	return voters
   341  }
   342  
   343  // nextSignableBlockNumber returns the number of the next block legal for signature by the signer of
   344  // lastSignedBlockNumber, based on the current number of signers.
   345  func (s *Snapshot) nextSignableBlockNumber(lastSignedBlockNumber uint64) uint64 {
   346  	n := uint64(len(s.Signers))
   347  	return lastSignedBlockNumber + n/2 + 1
   348  }