github.com/Blockdaemon/celo-blockchain@v0.0.0-20200129231733-e667f6b08419/consensus/istanbul/backend/backend.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 backend
    18  
    19  import (
    20  	"errors"
    21  	"fmt"
    22  	blscrypto "github.com/ethereum/go-ethereum/crypto/bls"
    23  	"math/big"
    24  	"sync"
    25  	"time"
    26  
    27  	"github.com/ethereum/go-ethereum/accounts"
    28  	"github.com/ethereum/go-ethereum/common"
    29  	"github.com/ethereum/go-ethereum/consensus"
    30  	"github.com/ethereum/go-ethereum/consensus/istanbul"
    31  	"github.com/ethereum/go-ethereum/consensus/istanbul/backend/internal/enodes"
    32  	istanbulCore "github.com/ethereum/go-ethereum/consensus/istanbul/core"
    33  	"github.com/ethereum/go-ethereum/consensus/istanbul/validator"
    34  	"github.com/ethereum/go-ethereum/contract_comm/election"
    35  	comm_errors "github.com/ethereum/go-ethereum/contract_comm/errors"
    36  	"github.com/ethereum/go-ethereum/contract_comm/random"
    37  	"github.com/ethereum/go-ethereum/contract_comm/validators"
    38  	"github.com/ethereum/go-ethereum/core"
    39  	"github.com/ethereum/go-ethereum/core/state"
    40  	"github.com/ethereum/go-ethereum/core/types"
    41  	"github.com/ethereum/go-ethereum/crypto"
    42  	"github.com/ethereum/go-ethereum/ethdb"
    43  	"github.com/ethereum/go-ethereum/event"
    44  	"github.com/ethereum/go-ethereum/log"
    45  	"github.com/ethereum/go-ethereum/metrics"
    46  	"github.com/ethereum/go-ethereum/p2p"
    47  	"github.com/ethereum/go-ethereum/p2p/enode"
    48  	"github.com/ethereum/go-ethereum/rlp"
    49  	lru "github.com/hashicorp/golang-lru"
    50  )
    51  
    52  const (
    53  	// fetcherID is the ID indicates the block is from Istanbul engine
    54  	fetcherID = "istanbul"
    55  )
    56  
    57  var (
    58  	// errInvalidSigningFn is returned when the consensus signing function is invalid.
    59  	errInvalidSigningFn = errors.New("invalid signing function for istanbul messages")
    60  
    61  	// errProxyAlreadySet is returned if a user tries to add a proxy that is already set.
    62  	// TODO - When we support multiple sentries per validator, this error will become irrelevant.
    63  	errProxyAlreadySet = errors.New("proxy already set")
    64  
    65  	// errNoProxyConnection is returned when a proxied validator is not connected to a proxy
    66  	errNoProxyConnection = errors.New("proxied validator not connected to a proxy")
    67  
    68  	// errNoBlockHeader is returned when the requested block header could not be found.
    69  	errNoBlockHeader = errors.New("failed to retrieve block header")
    70  
    71  	// errOldAnnounceMessage is returned when the received announce message's block number is earlier
    72  	// than a previous received message
    73  	errOldAnnounceMessage = errors.New("old announce message")
    74  )
    75  
    76  // Entries for the recent announce messages
    77  type AnnounceGossipTimestamp struct {
    78  	enodeURLHash      common.Hash
    79  	destAddressesHash common.Hash
    80  	timestamp         time.Time
    81  }
    82  
    83  // Information about the proxy for a proxied validator
    84  type proxyInfo struct {
    85  	node         *enode.Node    // Enode for the internal network interface
    86  	externalNode *enode.Node    // Enode for the external network interface
    87  	peer         consensus.Peer // Connected proxy peer.  Is nil if this node is not connected to the proxy
    88  }
    89  
    90  // New creates an Ethereum backend for Istanbul core engine.
    91  func New(config *istanbul.Config, db ethdb.Database) consensus.Istanbul {
    92  	// Allocate the snapshot caches and create the engine
    93  	logger := log.New()
    94  	recentSnapshots, err := lru.NewARC(inmemorySnapshots)
    95  	if err != nil {
    96  		logger.Crit("Failed to create recent snapshots cache", "err", err)
    97  	}
    98  	recentMessages, err := lru.NewARC(inmemoryPeers)
    99  	if err != nil {
   100  		logger.Crit("Failed to create recent messages cache", "err", err)
   101  	}
   102  	knownMessages, err := lru.NewARC(inmemoryMessages)
   103  	if err != nil {
   104  		logger.Crit("Failed to create known messages cache", "err", err)
   105  	}
   106  	backend := &Backend{
   107  		config:                  config,
   108  		istanbulEventMux:        new(event.TypeMux),
   109  		logger:                  logger,
   110  		db:                      db,
   111  		commitCh:                make(chan *types.Block, 1),
   112  		recentSnapshots:         recentSnapshots,
   113  		coreStarted:             false,
   114  		recentMessages:          recentMessages,
   115  		knownMessages:           knownMessages,
   116  		announceWg:              new(sync.WaitGroup),
   117  		announceQuit:            make(chan struct{}),
   118  		lastAnnounceGossiped:    make(map[common.Address]*AnnounceGossipTimestamp),
   119  		valEnodesShareWg:        new(sync.WaitGroup),
   120  		valEnodesShareQuit:      make(chan struct{}),
   121  		finalizationTimer:       metrics.NewRegisteredTimer("consensus/istanbul/backend/finalize", nil),
   122  		rewardDistributionTimer: metrics.NewRegisteredTimer("consensus/istanbul/backend/rewards", nil),
   123  	}
   124  	backend.core = istanbulCore.New(backend, backend.config)
   125  
   126  	backend.logger = istanbul.NewIstLogger(
   127  		func() *big.Int {
   128  			if backend.core != nil && backend.core.CurrentView() != nil {
   129  				return backend.core.CurrentView().Round
   130  			}
   131  			return common.Big0
   132  		},
   133  	)
   134  
   135  	vph := &validatorPeerHandler{sb: backend}
   136  	table, err := enodes.OpenValidatorEnodeDB(config.ValidatorEnodeDBPath, vph)
   137  	if err != nil {
   138  		logger.Crit("Can't open ValidatorEnodeDB", "err", err, "dbpath", config.ValidatorEnodeDBPath)
   139  	}
   140  	backend.valEnodeTable = table
   141  
   142  	return backend
   143  }
   144  
   145  // ----------------------------------------------------------------------------
   146  
   147  type Backend struct {
   148  	config           *istanbul.Config
   149  	istanbulEventMux *event.TypeMux
   150  
   151  	address          common.Address           // Ethereum address of the signing key
   152  	signFn           istanbul.SignerFn        // Signer function to authorize hashes with
   153  	signHashBLSFn    istanbul.BLSSignerFn     // Signer function to authorize hashes using BLS with
   154  	signMessageBLSFn istanbul.MessageSignerFn // Signer function to authorize messages using BLS with
   155  	signFnMu         sync.RWMutex             // Protects the signer fields
   156  
   157  	core         istanbulCore.Engine
   158  	logger       log.Logger
   159  	db           ethdb.Database
   160  	chain        consensus.ChainReader
   161  	currentBlock func() *types.Block
   162  	hasBadBlock  func(hash common.Hash) bool
   163  	stateAt      func(hash common.Hash) (*state.StateDB, error)
   164  
   165  	processBlock  func(block *types.Block, statedb *state.StateDB) (types.Receipts, []*types.Log, uint64, error)
   166  	validateState func(block *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas uint64) error
   167  
   168  	// the channels for istanbul engine notifications
   169  	commitCh          chan *types.Block
   170  	proposedBlockHash common.Hash
   171  	sealMu            sync.Mutex
   172  	coreStarted       bool
   173  	coreMu            sync.RWMutex
   174  
   175  	// Snapshots for recent blocks to speed up reorgs
   176  	recentSnapshots *lru.ARCCache
   177  
   178  	// event subscription for ChainHeadEvent event
   179  	broadcaster consensus.Broadcaster
   180  
   181  	// interface to the p2p server
   182  	p2pserver consensus.P2PServer
   183  
   184  	recentMessages *lru.ARCCache // the cache of peer's messages
   185  	knownMessages  *lru.ARCCache // the cache of self messages
   186  
   187  	lastAnnounceGossiped   map[common.Address]*AnnounceGossipTimestamp
   188  	lastAnnounceGossipedMu sync.RWMutex
   189  
   190  	valEnodeTable *enodes.ValidatorEnodeDB
   191  
   192  	announceWg   *sync.WaitGroup
   193  	announceQuit chan struct{}
   194  
   195  	valEnodesShareWg   *sync.WaitGroup
   196  	valEnodesShareQuit chan struct{}
   197  
   198  	proxyNode *proxyInfo
   199  
   200  	// Right now, we assume that there is at most one proxied peer for a proxy
   201  	proxiedPeer consensus.Peer
   202  
   203  	newEpochCh chan struct{}
   204  
   205  	delegateSignFeed  event.Feed
   206  	delegateSignScope event.SubscriptionScope
   207  
   208  	// Metric timer used to record block finalization times.
   209  	finalizationTimer metrics.Timer
   210  	// Metric timer used to record epoch reward distribution times.
   211  	rewardDistributionTimer metrics.Timer
   212  }
   213  
   214  func (sb *Backend) IsProxy() bool {
   215  	return sb.proxiedPeer != nil
   216  }
   217  
   218  func (sb *Backend) IsProxiedValidator() bool {
   219  	return sb.proxyNode != nil && sb.proxyNode.peer != nil
   220  }
   221  
   222  // SendDelegateSignMsgToProxy sends an istanbulDelegateSign message to a proxy
   223  // if one exists
   224  func (sb *Backend) SendDelegateSignMsgToProxy(msg []byte) error {
   225  	if !sb.IsProxiedValidator() {
   226  		err := errors.New("No Proxy found")
   227  		sb.logger.Error("SendDelegateSignMsgToProxy failed", "err", err)
   228  		return err
   229  	}
   230  	return sb.proxyNode.peer.Send(istanbulDelegateSign, msg)
   231  }
   232  
   233  // SendDelegateSignMsgToProxiedValidator sends an istanbulDelegateSign message to a
   234  // proxied validator if one exists
   235  func (sb *Backend) SendDelegateSignMsgToProxiedValidator(msg []byte) error {
   236  	if !sb.IsProxy() {
   237  		err := errors.New("No Proxied Validator found")
   238  		sb.logger.Error("SendDelegateSignMsgToProxiedValidator failed", "err", err)
   239  		return err
   240  	}
   241  	return sb.proxiedPeer.Send(istanbulDelegateSign, msg)
   242  }
   243  
   244  // Authorize implements istanbul.Backend.Authorize
   245  func (sb *Backend) Authorize(address common.Address, signFn istanbul.SignerFn, signHashBLSFn istanbul.BLSSignerFn, signMessageBLSFn istanbul.MessageSignerFn) {
   246  	sb.signFnMu.Lock()
   247  	defer sb.signFnMu.Unlock()
   248  
   249  	sb.address = address
   250  	sb.signFn = signFn
   251  	sb.signHashBLSFn = signHashBLSFn
   252  	sb.signMessageBLSFn = signMessageBLSFn
   253  	sb.core.SetAddress(address)
   254  }
   255  
   256  // Address implements istanbul.Backend.Address
   257  func (sb *Backend) Address() common.Address {
   258  	return sb.address
   259  }
   260  
   261  // Close the backend
   262  func (sb *Backend) Close() error {
   263  	sb.delegateSignScope.Close()
   264  	return sb.valEnodeTable.Close()
   265  }
   266  
   267  // Validators implements istanbul.Backend.Validators
   268  func (sb *Backend) Validators(proposal istanbul.Proposal) istanbul.ValidatorSet {
   269  	return sb.getOrderedValidators(proposal.Number().Uint64(), proposal.Hash())
   270  }
   271  
   272  // ParentBlockValidators implements istanbul.Backend.ParentBlockValidators
   273  func (sb *Backend) ParentBlockValidators(proposal istanbul.Proposal) istanbul.ValidatorSet {
   274  	return sb.getOrderedValidators(proposal.Number().Uint64()-1, proposal.ParentHash())
   275  }
   276  
   277  func (sb *Backend) NextBlockValidators(proposal istanbul.Proposal) (istanbul.ValidatorSet, error) {
   278  	istExtra, err := types.ExtractIstanbulExtra(proposal.Header())
   279  	if err != nil {
   280  		return nil, err
   281  	}
   282  
   283  	// There was no change
   284  	if len(istExtra.AddedValidators) == 0 && istExtra.RemovedValidators.BitLen() == 0 {
   285  		return sb.ParentBlockValidators(proposal), nil
   286  	}
   287  
   288  	snap, err := sb.snapshot(sb.chain, proposal.Number().Uint64()-1, common.Hash{}, nil)
   289  	if err != nil {
   290  		return nil, err
   291  	}
   292  	snap = snap.copy()
   293  
   294  	addedValidators, err := istanbul.CombineIstanbulExtraToValidatorData(istExtra.AddedValidators, istExtra.AddedValidatorsPublicKeys)
   295  	if err != nil {
   296  		return nil, err
   297  	}
   298  
   299  	if !snap.ValSet.RemoveValidators(istExtra.RemovedValidators) {
   300  		return nil, fmt.Errorf("could not obtain next block validators: failed at remove validators")
   301  	}
   302  	if !snap.ValSet.AddValidators(addedValidators) {
   303  		return nil, fmt.Errorf("could not obtain next block validators: failed at add validators")
   304  	}
   305  
   306  	return snap.ValSet, nil
   307  }
   308  
   309  func (sb *Backend) GetValidators(blockNumber *big.Int, headerHash common.Hash) []istanbul.Validator {
   310  	validatorSet := sb.getValidators(blockNumber.Uint64(), headerHash)
   311  	return validatorSet.List()
   312  }
   313  
   314  // This function will return the peers with the addresses in the "destAddresses" parameter.
   315  // If this is a proxied validator, then it will return the proxy.
   316  func (sb *Backend) getPeersForMessage(destAddresses []common.Address) map[enode.ID]consensus.Peer {
   317  	if sb.config.Proxied {
   318  		if sb.proxyNode != nil && sb.proxyNode.peer != nil {
   319  			returnMap := make(map[enode.ID]consensus.Peer)
   320  			returnMap[sb.proxyNode.peer.Node().ID()] = sb.proxyNode.peer
   321  
   322  			return returnMap
   323  		} else {
   324  			return nil
   325  		}
   326  	} else {
   327  		var targets map[enode.ID]bool = nil
   328  
   329  		if destAddresses != nil {
   330  			targets = make(map[enode.ID]bool)
   331  			for _, addr := range destAddresses {
   332  				if valNode, err := sb.valEnodeTable.GetNodeFromAddress(addr); valNode != nil && err == nil {
   333  					targets[valNode.ID()] = true
   334  				}
   335  			}
   336  		}
   337  		return sb.broadcaster.FindPeers(targets, p2p.AnyPurpose)
   338  	}
   339  }
   340  
   341  // Broadcast implements istanbul.Backend.BroadcastConsensusMsg
   342  func (sb *Backend) BroadcastConsensusMsg(destAddresses []common.Address, payload []byte) error {
   343  	sb.logger.Trace("Broadcasting an istanbul message", "destAddresses", common.ConvertToStringSlice(destAddresses))
   344  
   345  	// send to others
   346  	if err := sb.Gossip(destAddresses, payload, istanbulConsensusMsg, false); err != nil {
   347  		return err
   348  	}
   349  
   350  	// send to self
   351  	msg := istanbul.MessageEvent{
   352  		Payload: payload,
   353  	}
   354  	go sb.istanbulEventMux.Post(msg)
   355  	return nil
   356  }
   357  
   358  // Gossip implements istanbul.Backend.Gossip
   359  func (sb *Backend) Gossip(destAddresses []common.Address, payload []byte, ethMsgCode uint64, ignoreCache bool) error {
   360  	// If this is a proxied validator and it wants to send a consensus message,
   361  	// wrap the consensus message in a forward message.
   362  	if sb.config.Proxied && ethMsgCode == istanbulConsensusMsg {
   363  		var err error
   364  
   365  		fwdMessage := &istanbul.ForwardMessage{DestAddresses: destAddresses, Msg: payload}
   366  		fwdMsgBytes, err := rlp.EncodeToBytes(fwdMessage)
   367  		if err != nil {
   368  			sb.logger.Error("Failed to encode", "fwdMessage", fwdMessage)
   369  			return err
   370  		}
   371  
   372  		// Note that we are not signing message.  The message that is being wrapped is already signed.
   373  		msg := istanbul.Message{Code: istanbulFwdMsg, Msg: fwdMsgBytes, Address: sb.Address()}
   374  		payload, err = msg.Payload()
   375  		if err != nil {
   376  			return err
   377  		}
   378  
   379  		ethMsgCode = istanbulFwdMsg
   380  	}
   381  
   382  	peers := sb.getPeersForMessage(destAddresses)
   383  
   384  	var hash common.Hash
   385  	if !ignoreCache {
   386  		hash = istanbul.RLPHash(payload)
   387  		sb.knownMessages.Add(hash, true)
   388  	}
   389  
   390  	if len(peers) > 0 {
   391  		for nodeID, p := range peers {
   392  			if !ignoreCache {
   393  				ms, ok := sb.recentMessages.Get(nodeID)
   394  				var m *lru.ARCCache
   395  				if ok {
   396  					m, _ = ms.(*lru.ARCCache)
   397  					if _, k := m.Get(hash); k {
   398  						// This peer had this event, skip it
   399  						continue
   400  					}
   401  				} else {
   402  					m, _ = lru.NewARC(inmemoryMessages)
   403  				}
   404  
   405  				m.Add(hash, true)
   406  				sb.recentMessages.Add(nodeID, m)
   407  			}
   408  			sb.logger.Trace("Sending istanbul message to peer", "msg_code", ethMsgCode, "nodeID", nodeID)
   409  
   410  			go p.Send(ethMsgCode, payload)
   411  		}
   412  	}
   413  	return nil
   414  }
   415  
   416  // Commit implements istanbul.Backend.Commit
   417  func (sb *Backend) Commit(proposal istanbul.Proposal, aggregatedSeal types.IstanbulAggregatedSeal, aggregatedEpochValidatorSetSeal types.IstanbulEpochValidatorSetSeal) error {
   418  	// Check if the proposal is a valid block
   419  	block := &types.Block{}
   420  	block, ok := proposal.(*types.Block)
   421  	if !ok {
   422  		sb.logger.Error("Invalid proposal, %v", proposal)
   423  		return errInvalidProposal
   424  	}
   425  
   426  	h := block.Header()
   427  	// Append seals into extra-data
   428  	err := writeAggregatedSeal(h, aggregatedSeal, false)
   429  	if err != nil {
   430  		return err
   431  	}
   432  	// update block's header
   433  	block = block.WithSeal(h)
   434  	block = block.WithEpochSnarkData(&types.EpochSnarkData{
   435  		Signature: aggregatedEpochValidatorSetSeal.Signature,
   436  	})
   437  
   438  	sb.logger.Info("Committed", "address", sb.Address(), "round", aggregatedSeal.Round.Uint64(), "hash", proposal.Hash(), "number", proposal.Number().Uint64())
   439  	// - if the proposed and committed blocks are the same, send the proposed hash
   440  	//   to commit channel, which is being watched inside the engine.Seal() function.
   441  	// - otherwise, we try to insert the block.
   442  	// -- if success, the ChainHeadEvent event will be broadcasted, try to build
   443  	//    the next block and the previous Seal() will be stopped.
   444  	// -- otherwise, a error will be returned and a round change event will be fired.
   445  	if sb.proposedBlockHash == block.Hash() {
   446  		// feed block hash to Seal() and wait the Seal() result
   447  		sb.commitCh <- block
   448  		return nil
   449  	}
   450  
   451  	if sb.broadcaster != nil {
   452  		sb.broadcaster.Enqueue(fetcherID, block)
   453  	}
   454  	return nil
   455  }
   456  
   457  // EventMux implements istanbul.Backend.EventMux
   458  func (sb *Backend) EventMux() *event.TypeMux {
   459  	return sb.istanbulEventMux
   460  }
   461  
   462  // Verify implements istanbul.Backend.Verify
   463  func (sb *Backend) Verify(proposal istanbul.Proposal) (time.Duration, error) {
   464  	// Check if the proposal is a valid block
   465  	block := &types.Block{}
   466  	block, ok := proposal.(*types.Block)
   467  	if !ok {
   468  		sb.logger.Error("Invalid proposal, %v", proposal)
   469  		return 0, errInvalidProposal
   470  	}
   471  
   472  	// check bad block
   473  	if sb.hasBadProposal(block.Hash()) {
   474  		return 0, core.ErrBlacklistedHash
   475  	}
   476  
   477  	// check block body
   478  	txnHash := types.DeriveSha(block.Transactions())
   479  	uncleHash := types.CalcUncleHash(block.Uncles())
   480  	if txnHash != block.Header().TxHash {
   481  		return 0, errMismatchTxhashes
   482  	}
   483  	if uncleHash != nilUncleHash {
   484  		return 0, errInvalidUncleHash
   485  	}
   486  
   487  	// The author should be the first person to propose the block to ensure that randomness matches up.
   488  	addr, err := sb.Author(block.Header())
   489  	if err != nil {
   490  		sb.logger.Error("Could not recover orignal author of the block to verify the randomness", "err", err, "func", "Verify")
   491  		return 0, errInvalidProposal
   492  	} else if addr != block.Header().Coinbase {
   493  		sb.logger.Error("Original author of the block does not match the coinbase", "addr", addr, "coinbase", block.Header().Coinbase, "func", "Verify")
   494  		return 0, errInvalidCoinbase
   495  	}
   496  
   497  	err = sb.VerifyHeader(sb.chain, block.Header(), false)
   498  
   499  	// ignore errEmptyAggregatedSeal error because we don't have the committed seals yet
   500  	if err != nil && err != errEmptyAggregatedSeal {
   501  		if err == consensus.ErrFutureBlock {
   502  			return time.Unix(block.Header().Time.Int64(), 0).Sub(now()), consensus.ErrFutureBlock
   503  		} else {
   504  			return 0, err
   505  		}
   506  	}
   507  
   508  	// Process the block to verify that the transactions are valid and to retrieve the resulting state and receipts
   509  	// Get the state from this block's parent.
   510  	state, err := sb.stateAt(block.Header().ParentHash)
   511  	if err != nil {
   512  		sb.logger.Error("verify - Error in getting the block's parent's state", "parentHash", block.Header().ParentHash.Hex(), "err", err)
   513  		return 0, err
   514  	}
   515  
   516  	// Make a copy of the state
   517  	state = state.Copy()
   518  
   519  	// Apply this block's transactions to update the state
   520  	receipts, _, usedGas, err := sb.processBlock(block, state)
   521  	if err != nil {
   522  		sb.logger.Error("verify - Error in processing the block", "err", err)
   523  		return 0, err
   524  	}
   525  
   526  	// Validate the block
   527  	if err := sb.validateState(block, state, receipts, usedGas); err != nil {
   528  		sb.logger.Error("verify - Error in validating the block", "err", err)
   529  		return 0, err
   530  	}
   531  
   532  	// verify the validator set diff if this is the last block of the epoch
   533  	if istanbul.IsLastBlockOfEpoch(block.Header().Number.Uint64(), sb.config.Epoch) {
   534  		if err := sb.verifyValSetDiff(proposal, block, state); err != nil {
   535  			sb.logger.Error("verify - Error in verifying the val set diff", "err", err)
   536  			return 0, err
   537  		}
   538  	}
   539  
   540  	return 0, err
   541  }
   542  
   543  func (sb *Backend) getNewValidatorSet(header *types.Header, state *state.StateDB) ([]istanbul.ValidatorData, error) {
   544  	newValSetAddresses, err := election.GetElectedValidators(header, state)
   545  	if err != nil {
   546  		return nil, err
   547  	}
   548  	newValSet, err := validators.GetValidatorData(header, state, newValSetAddresses)
   549  	return newValSet, err
   550  }
   551  
   552  func (sb *Backend) verifyValSetDiff(proposal istanbul.Proposal, block *types.Block, state *state.StateDB) error {
   553  	header := block.Header()
   554  
   555  	// Ensure that the extra data format is satisfied
   556  	istExtra, err := types.ExtractIstanbulExtra(header)
   557  	if err != nil {
   558  		return err
   559  	}
   560  
   561  	newValSet, err := sb.getNewValidatorSet(block.Header(), state)
   562  	if err != nil {
   563  		if len(istExtra.AddedValidators) != 0 || istExtra.RemovedValidators.BitLen() != 0 {
   564  			sb.logger.Error("verifyValSetDiff - Invalid val set diff.  Non empty diff when it should be empty.", "addedValidators", common.ConvertToStringSlice(istExtra.AddedValidators), "removedValidators", istExtra.RemovedValidators.Text(16))
   565  			return errInvalidValidatorSetDiff
   566  		}
   567  	} else {
   568  		parentValidators := sb.ParentBlockValidators(proposal)
   569  		oldValSet := make([]istanbul.ValidatorData, 0, parentValidators.Size())
   570  
   571  		for _, val := range parentValidators.List() {
   572  			oldValSet = append(oldValSet, istanbul.ValidatorData{
   573  				val.Address(),
   574  				val.BLSPublicKey(),
   575  			})
   576  		}
   577  
   578  		addedValidators, removedValidators := istanbul.ValidatorSetDiff(oldValSet, newValSet)
   579  
   580  		addedValidatorsAddresses := make([]common.Address, 0, len(addedValidators))
   581  		addedValidatorsPublicKeys := make([]blscrypto.SerializedPublicKey, 0, len(addedValidators))
   582  		for _, val := range addedValidators {
   583  			addedValidatorsAddresses = append(addedValidatorsAddresses, val.Address)
   584  			addedValidatorsPublicKeys = append(addedValidatorsPublicKeys, val.BLSPublicKey)
   585  		}
   586  
   587  		if !istanbul.CompareValidatorSlices(addedValidatorsAddresses, istExtra.AddedValidators) || removedValidators.Cmp(istExtra.RemovedValidators) != 0 || !istanbul.CompareValidatorPublicKeySlices(addedValidatorsPublicKeys, istExtra.AddedValidatorsPublicKeys) {
   588  			sb.logger.Error("verifyValSetDiff - Invalid val set diff. Comparison failed. ", "got addedValidators", common.ConvertToStringSlice(istExtra.AddedValidators), "got removedValidators", istExtra.RemovedValidators.Text(16), "got addedValidatorsPublicKeys", istanbul.ConvertPublicKeysToStringSlice(istExtra.AddedValidatorsPublicKeys), "expected addedValidators", common.ConvertToStringSlice(addedValidatorsAddresses), "expected removedValidators", removedValidators.Text(16), "expected addedValidatorsPublicKeys", istanbul.ConvertPublicKeysToStringSlice(addedValidatorsPublicKeys))
   589  			return errInvalidValidatorSetDiff
   590  		}
   591  	}
   592  
   593  	return nil
   594  }
   595  
   596  // Sign implements istanbul.Backend.Sign
   597  func (sb *Backend) Sign(data []byte) ([]byte, error) {
   598  	if sb.signFn == nil {
   599  		return nil, errInvalidSigningFn
   600  	}
   601  	hashData := crypto.Keccak256(data)
   602  	sb.signFnMu.RLock()
   603  	defer sb.signFnMu.RUnlock()
   604  	return sb.signFn(accounts.Account{Address: sb.address}, hashData)
   605  }
   606  
   607  func (sb *Backend) SignBlockHeader(data []byte) (blscrypto.SerializedSignature, error) {
   608  	if sb.signHashBLSFn == nil {
   609  		return blscrypto.SerializedSignature{}, errInvalidSigningFn
   610  	}
   611  	sb.signFnMu.RLock()
   612  	defer sb.signFnMu.RUnlock()
   613  	return sb.signHashBLSFn(accounts.Account{Address: sb.address}, data)
   614  }
   615  
   616  func (sb *Backend) SignBLSWithCompositeHash(data []byte) (blscrypto.SerializedSignature, error) {
   617  	if sb.signMessageBLSFn == nil {
   618  		return blscrypto.SerializedSignature{}, errInvalidSigningFn
   619  	}
   620  	sb.signFnMu.RLock()
   621  	defer sb.signFnMu.RUnlock()
   622  	// Currently, ExtraData is unused. In the future, it could include data that could be used to introduce
   623  	// "firmware-level" protection. Such data could include data that the SNARK doesn't necessarily need,
   624  	// such as the block number, which can be used by a hardware wallet to see that the block number
   625  	// is incrementing, without having to perform the two-level hashing, just one-level fast hashing.
   626  	return sb.signMessageBLSFn(accounts.Account{Address: sb.address}, data, []byte{})
   627  }
   628  
   629  // CheckSignature implements istanbul.Backend.CheckSignature
   630  func (sb *Backend) CheckSignature(data []byte, address common.Address, sig []byte) error {
   631  	signer, err := istanbul.GetSignatureAddress(data, sig)
   632  	if err != nil {
   633  		sb.logger.Error("Failed to get signer address", "err", err)
   634  		return err
   635  	}
   636  	// Compare derived addresses
   637  	if signer != address {
   638  		return errInvalidSignature
   639  	}
   640  	return nil
   641  }
   642  
   643  // HasBlock implements istanbul.Backend.HasBlock
   644  func (sb *Backend) HasBlock(hash common.Hash, number *big.Int) bool {
   645  	return sb.chain.GetHeader(hash, number.Uint64()) != nil
   646  }
   647  
   648  // AuthorForBlock implements istanbul.Backend.AuthorForBlock
   649  func (sb *Backend) AuthorForBlock(number uint64) common.Address {
   650  	if h := sb.chain.GetHeaderByNumber(number); h != nil {
   651  		a, _ := sb.Author(h)
   652  		return a
   653  	}
   654  	return common.ZeroAddress
   655  }
   656  
   657  func (sb *Backend) getValidators(number uint64, hash common.Hash) istanbul.ValidatorSet {
   658  	snap, err := sb.snapshot(sb.chain, number, hash, nil)
   659  	if err != nil {
   660  		sb.logger.Warn("Error getting snapshot", "number", number, "hash", hash, "err", err)
   661  		return validator.NewSet(nil)
   662  	}
   663  	return snap.ValSet
   664  }
   665  
   666  // validatorRandomnessAtBlockNumber calls into the EVM to get the randomness to use in proposer ordering at a given block.
   667  func (sb *Backend) validatorRandomnessAtBlockNumber(number uint64, hash common.Hash) (common.Hash, error) {
   668  	lastBlockInPreviousEpoch := number
   669  	if number > 0 {
   670  		lastBlockInPreviousEpoch = number - istanbul.GetNumberWithinEpoch(number, sb.config.Epoch)
   671  	}
   672  	header := sb.chain.GetHeaderByNumber(lastBlockInPreviousEpoch)
   673  	if header == nil {
   674  		return common.Hash{}, errNoBlockHeader
   675  	}
   676  	state, err := sb.stateAt(header.Hash())
   677  	if err != nil {
   678  		return common.Hash{}, err
   679  	}
   680  	return random.Random(header, state)
   681  }
   682  
   683  func (sb *Backend) getOrderedValidators(number uint64, hash common.Hash) istanbul.ValidatorSet {
   684  	valSet := sb.getValidators(number, hash)
   685  	if valSet.Size() == 0 {
   686  		return valSet
   687  	}
   688  
   689  	if sb.config.ProposerPolicy == istanbul.ShuffledRoundRobin {
   690  		seed, err := sb.validatorRandomnessAtBlockNumber(number, hash)
   691  		if err != nil {
   692  			if err == comm_errors.ErrRegistryContractNotDeployed {
   693  				sb.logger.Debug("Failed to set randomness for proposer selection", "block_number", number, "hash", hash, "error", err)
   694  			} else {
   695  				sb.logger.Warn("Failed to set randomness for proposer selection", "block_number", number, "hash", hash, "error", err)
   696  			}
   697  		}
   698  		valSet.SetRandomness(seed)
   699  	}
   700  
   701  	return valSet
   702  }
   703  
   704  // GetCurrentHeadBlock retrieves the last block
   705  func (sb *Backend) GetCurrentHeadBlock() istanbul.Proposal {
   706  	return sb.currentBlock()
   707  }
   708  
   709  // GetCurrentHeadBlockAndAuthor retrieves the last block alongside the coinbase address for it
   710  func (sb *Backend) GetCurrentHeadBlockAndAuthor() (istanbul.Proposal, common.Address) {
   711  	block := sb.currentBlock()
   712  
   713  	if block.Number().Cmp(common.Big0) == 0 {
   714  		return block, common.ZeroAddress
   715  	}
   716  
   717  	proposer, err := sb.Author(block.Header())
   718  
   719  	if err != nil {
   720  		sb.logger.Error("Failed to get block proposer", "err", err)
   721  		return nil, common.ZeroAddress
   722  	}
   723  
   724  	// Return header only block here since we don't need block body
   725  	return block, proposer
   726  }
   727  
   728  func (sb *Backend) LastSubject() (istanbul.Subject, error) {
   729  	lastProposal, _ := sb.GetCurrentHeadBlockAndAuthor()
   730  	istExtra, err := types.ExtractIstanbulExtra(lastProposal.Header())
   731  	if err != nil {
   732  		return istanbul.Subject{}, err
   733  	}
   734  	lastView := &istanbul.View{Sequence: lastProposal.Number(), Round: istExtra.AggregatedSeal.Round}
   735  	return istanbul.Subject{View: lastView, Digest: lastProposal.Hash()}, nil
   736  }
   737  
   738  func (sb *Backend) hasBadProposal(hash common.Hash) bool {
   739  	if sb.hasBadBlock == nil {
   740  		return false
   741  	}
   742  	return sb.hasBadBlock(hash)
   743  }
   744  
   745  func (sb *Backend) addProxy(node, externalNode *enode.Node) error {
   746  	if sb.proxyNode != nil {
   747  		return errProxyAlreadySet
   748  	}
   749  
   750  	sb.p2pserver.AddPeer(node, p2p.ProxyPurpose)
   751  
   752  	sb.proxyNode = &proxyInfo{node: node, externalNode: externalNode}
   753  	return nil
   754  }
   755  
   756  func (sb *Backend) removeProxy(node *enode.Node) {
   757  	if sb.proxyNode != nil && sb.proxyNode.node.ID() == node.ID() {
   758  		sb.p2pserver.RemovePeer(node, p2p.ProxyPurpose)
   759  		sb.proxyNode = nil
   760  	}
   761  }
   762  
   763  // RefreshValPeers will create 'validator' type peers to all the valset validators, and disconnect from the
   764  // peers that are not part of the valset.
   765  // It will also disconnect all validator connections if this node is not a validator.
   766  // Note that adding and removing validators are idempotent operations.  If the validator
   767  // being added or removed is already added or removed, then a no-op will be done.
   768  func (sb *Backend) RefreshValPeers(valset istanbul.ValidatorSet) {
   769  	sb.logger.Trace("Called RefreshValPeers", "valset length", valset.Size())
   770  
   771  	if sb.broadcaster == nil {
   772  		return
   773  	}
   774  
   775  	sb.valEnodeTable.RefreshValPeers(valset, sb.ValidatorAddress())
   776  }
   777  
   778  func (sb *Backend) ValidatorAddress() common.Address {
   779  	var localAddress common.Address
   780  	if sb.config.Proxy {
   781  		localAddress = sb.config.ProxiedValidatorAddress
   782  	} else {
   783  		localAddress = sb.Address()
   784  	}
   785  	return localAddress
   786  }
   787  
   788  func (sb *Backend) ConnectToVals() {
   789  	// If this is a proxy, then refresh the val peers.  Note that this will be done within Backend.Start
   790  	// for non proxied validators
   791  	if sb.config.Proxy {
   792  		headBlock := sb.GetCurrentHeadBlock()
   793  		valset := sb.getValidators(headBlock.Number().Uint64(), headBlock.Hash())
   794  		sb.RefreshValPeers(valset)
   795  	}
   796  }