github.com/klaytn/klaytn@v1.12.1/consensus/istanbul/backend/engine.go (about)

     1  // Modifications Copyright 2018 The klaytn Authors
     2  // Copyright 2017 The go-ethereum Authors
     3  // This file is part of the go-ethereum library.
     4  //
     5  // The go-ethereum library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Lesser General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // The go-ethereum library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13  // GNU Lesser General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Lesser General Public License
    16  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    17  //
    18  // This file is derived from quorum/consensus/istanbul/backend/engine.go (2018/06/04).
    19  // Modified and improved for the klaytn development.
    20  
    21  package backend
    22  
    23  import (
    24  	"bytes"
    25  	"encoding/hex"
    26  	"encoding/json"
    27  	"errors"
    28  	"math/big"
    29  	"time"
    30  
    31  	lru "github.com/hashicorp/golang-lru"
    32  	"github.com/klaytn/klaytn/blockchain/state"
    33  	"github.com/klaytn/klaytn/blockchain/system"
    34  	"github.com/klaytn/klaytn/blockchain/types"
    35  	"github.com/klaytn/klaytn/common"
    36  	"github.com/klaytn/klaytn/consensus"
    37  	"github.com/klaytn/klaytn/consensus/istanbul"
    38  	istanbulCore "github.com/klaytn/klaytn/consensus/istanbul/core"
    39  	"github.com/klaytn/klaytn/consensus/istanbul/validator"
    40  	"github.com/klaytn/klaytn/consensus/misc"
    41  	"github.com/klaytn/klaytn/crypto/sha3"
    42  	"github.com/klaytn/klaytn/networks/rpc"
    43  	"github.com/klaytn/klaytn/params"
    44  	"github.com/klaytn/klaytn/reward"
    45  	"github.com/klaytn/klaytn/rlp"
    46  )
    47  
    48  const (
    49  	// CheckpointInterval = 1024 // Number of blocks after which to save the vote snapshot to the database
    50  	// inmemorySnapshots  = 128  // Number of recent vote snapshots to keep in memory
    51  	// inmemoryPeers      = 40
    52  	// inmemoryMessages   = 1024
    53  
    54  	inmemorySnapshots = 496 // Number of recent vote snapshots to keep in memory
    55  	inmemoryPeers     = 200
    56  	inmemoryMessages  = 4096
    57  
    58  	allowedFutureBlockTime = 1 * time.Second // Max time from current time allowed for blocks, before they're considered future blocks
    59  )
    60  
    61  var (
    62  	// errInvalidProposal is returned when a prposal is malformed.
    63  	errInvalidProposal = errors.New("invalid proposal")
    64  	// errInvalidSignature is returned when given signature is not signed by given
    65  	// address.
    66  	errInvalidSignature = errors.New("invalid signature")
    67  	// errUnknownBlock is returned when the list of validators is requested for a block
    68  	// that is not part of the local blockchain.
    69  	errUnknownBlock = errors.New("unknown block")
    70  	// errUnauthorized is returned if a header is signed by a non authorized entity.
    71  	errUnauthorized = errors.New("unauthorized")
    72  	// errInvalidBlockScore is returned if the BlockScore of a block is not 1
    73  	errInvalidBlockScore = errors.New("invalid blockscore")
    74  	// errInvalidExtraDataFormat is returned when the extra data format is incorrect
    75  	errInvalidExtraDataFormat = errors.New("invalid extra data format")
    76  	// errInvalidTimestamp is returned if the timestamp of a block is lower than the previous block's timestamp + the minimum block period.
    77  	errInvalidTimestamp = errors.New("invalid timestamp")
    78  	// errInvalidVotingChain is returned if an authorization list is attempted to
    79  	// be modified via out-of-range or non-contiguous headers.
    80  	errInvalidVotingChain = errors.New("invalid voting chain")
    81  	// errInvalidCommittedSeals is returned if the committed seal is not signed by any of parent validators.
    82  	errInvalidCommittedSeals = errors.New("invalid committed seals")
    83  	// errEmptyCommittedSeals is returned if the field of committed seals is zero.
    84  	errEmptyCommittedSeals = errors.New("zero committed seals")
    85  	// errMismatchTxhashes is returned if the TxHash in header is mismatch.
    86  	errMismatchTxhashes = errors.New("mismatch transactions hashes")
    87  	// errNoBlsKey is returned if the BLS secret key is not configured.
    88  	errNoBlsKey = errors.New("bls key not configured")
    89  	// errNoBlsPub is returned if the BLS public key is not found for the proposer.
    90  	errNoBlsPub = errors.New("bls pubkey not found for the proposer")
    91  	// errInvalidRandaoFields is returned if the Randao fields randomReveal or mixHash are invalid.
    92  	errInvalidRandaoFields = errors.New("invalid randao fields")
    93  	// errUnexpectedRandao is returned if the Randao fields randomReveal or mixHash are present when must not.
    94  	errUnexpectedRandao = errors.New("unexpected randao fields")
    95  )
    96  
    97  var (
    98  	defaultBlockScore = big.NewInt(1)
    99  	now               = time.Now
   100  
   101  	inmemoryBlocks             = 2048 // Number of blocks to precompute validators' addresses
   102  	inmemoryValidatorsPerBlock = 30   // Approximate number of validators' addresses from ecrecover
   103  	signatureAddresses, _      = lru.NewARC(inmemoryBlocks * inmemoryValidatorsPerBlock)
   104  )
   105  
   106  // cacheSignatureAddresses extracts the address from the given data and signature and cache them for later usage.
   107  func cacheSignatureAddresses(data []byte, sig []byte) (common.Address, error) {
   108  	sigStr := hex.EncodeToString(sig)
   109  	if addr, ok := signatureAddresses.Get(sigStr); ok {
   110  		return addr.(common.Address), nil
   111  	}
   112  	addr, err := istanbul.GetSignatureAddress(data, sig)
   113  	if err != nil {
   114  		return common.Address{}, err
   115  	}
   116  	signatureAddresses.Add(sigStr, addr)
   117  	return addr, err
   118  }
   119  
   120  // Author retrieves the Klaytn address of the account that minted the given block.
   121  func (sb *backend) Author(header *types.Header) (common.Address, error) {
   122  	return ecrecover(header)
   123  }
   124  
   125  // CanVerifyHeadersConcurrently returns true if concurrent header verification possible, otherwise returns false.
   126  func (sb *backend) CanVerifyHeadersConcurrently() bool {
   127  	return false
   128  }
   129  
   130  // PreprocessHeaderVerification prepares header verification for heavy computation before synchronous header verification such as ecrecover.
   131  func (sb *backend) PreprocessHeaderVerification(headers []*types.Header) (chan<- struct{}, <-chan error) {
   132  	abort := make(chan struct{})
   133  	results := make(chan error, inmemoryBlocks)
   134  	go func() {
   135  		for _, header := range headers {
   136  			err := sb.computeSignatureAddrs(header)
   137  
   138  			select {
   139  			case <-abort:
   140  				return
   141  			case results <- err:
   142  			}
   143  		}
   144  	}()
   145  	return abort, results
   146  }
   147  
   148  // computeSignatureAddrs computes the addresses of signer and validators and caches them.
   149  func (sb *backend) computeSignatureAddrs(header *types.Header) error {
   150  	_, err := ecrecover(header)
   151  	if err != nil {
   152  		return err
   153  	}
   154  
   155  	// Retrieve the signature from the header extra-data
   156  	istanbulExtra, err := types.ExtractIstanbulExtra(header)
   157  	if err != nil {
   158  		return err
   159  	}
   160  
   161  	proposalSeal := istanbulCore.PrepareCommittedSeal(header.Hash())
   162  	for _, seal := range istanbulExtra.CommittedSeal {
   163  		_, err := cacheSignatureAddresses(proposalSeal, seal)
   164  		if err != nil {
   165  			return errInvalidSignature
   166  		}
   167  	}
   168  	return nil
   169  }
   170  
   171  // VerifyHeader checks whether a header conforms to the consensus rules of a
   172  // given engine. Verifying the seal may be done optionally here, or explicitly
   173  // via the VerifySeal method.
   174  func (sb *backend) VerifyHeader(chain consensus.ChainReader, header *types.Header, seal bool) error {
   175  	var parent []*types.Header
   176  	if header.Number.Sign() == 0 {
   177  		// If current block is genesis, the parent is also genesis
   178  		parent = append(parent, chain.GetHeaderByNumber(0))
   179  	} else {
   180  		parent = append(parent, chain.GetHeader(header.ParentHash, header.Number.Uint64()-1))
   181  	}
   182  	return sb.verifyHeader(chain, header, parent)
   183  }
   184  
   185  // verifyHeader checks whether a header conforms to the consensus rules.The
   186  // caller may optionally pass in a batch of parents (ascending order) to avoid
   187  // looking those up from the database. This is useful for concurrently verifying
   188  // a batch of new headers.
   189  func (sb *backend) verifyHeader(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error {
   190  	if header.Number == nil {
   191  		return errUnknownBlock
   192  	}
   193  
   194  	// Header verify before/after magma fork
   195  	if chain.Config().IsMagmaForkEnabled(header.Number) {
   196  		// the kip71Config used when creating the block number is a previous block config.
   197  		blockNum := header.Number.Uint64()
   198  		pset, err := sb.governance.EffectiveParams(blockNum)
   199  		if err != nil {
   200  			return err
   201  		}
   202  
   203  		kip71 := pset.ToKIP71Config()
   204  		if err := misc.VerifyMagmaHeader(parents[len(parents)-1], header, kip71); err != nil {
   205  			return err
   206  		}
   207  	} else if header.BaseFee != nil {
   208  		return consensus.ErrInvalidBaseFee
   209  	}
   210  
   211  	// Don't waste time checking blocks from the future
   212  	if header.Time.Cmp(big.NewInt(now().Add(allowedFutureBlockTime).Unix())) > 0 {
   213  		return consensus.ErrFutureBlock
   214  	}
   215  
   216  	// Ensure that the extra data format is satisfied
   217  	if _, err := types.ExtractIstanbulExtra(header); err != nil {
   218  		return errInvalidExtraDataFormat
   219  	}
   220  	// Ensure that the block's blockscore is meaningful (may not be correct at this point)
   221  	if header.BlockScore == nil || header.BlockScore.Cmp(defaultBlockScore) != 0 {
   222  		return errInvalidBlockScore
   223  	}
   224  
   225  	return sb.verifyCascadingFields(chain, header, parents)
   226  }
   227  
   228  // verifyCascadingFields verifies all the header fields that are not standalone,
   229  // rather depend on a batch of previous headers. The caller may optionally pass
   230  // in a batch of parents (ascending order) to avoid looking those up from the
   231  // database. This is useful for concurrently verifying a batch of new headers.
   232  func (sb *backend) verifyCascadingFields(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error {
   233  	// The genesis block is the always valid dead-end
   234  	number := header.Number.Uint64()
   235  	if number == 0 {
   236  		return nil
   237  	}
   238  	// Ensure that the block's timestamp isn't too close to it's parent
   239  	var parent *types.Header
   240  	if len(parents) > 0 {
   241  		parent = parents[len(parents)-1]
   242  	} else {
   243  		parent = chain.GetHeader(header.ParentHash, number-1)
   244  	}
   245  	if parent == nil || parent.Number.Uint64() != number-1 || parent.Hash() != header.ParentHash {
   246  		return consensus.ErrUnknownAncestor
   247  	}
   248  	if parent.Time.Uint64()+sb.config.BlockPeriod > header.Time.Uint64() {
   249  		return errInvalidTimestamp
   250  	}
   251  	if err := sb.verifySigner(chain, header, parents); err != nil {
   252  		return err
   253  	}
   254  
   255  	// VerifyRandao must be after verifySigner because it needs the signer (proposer) address
   256  	if chain.Config().IsRandaoForkEnabled(header.Number) {
   257  		prevMixHash := headerMixHash(chain, parent)
   258  		if err := sb.VerifyRandao(chain, header, prevMixHash); err != nil {
   259  			return err
   260  		}
   261  	} else if header.RandomReveal != nil || header.MixHash != nil {
   262  		return errUnexpectedRandao
   263  	}
   264  
   265  	// At every epoch governance data will come in block header. Verify it.
   266  	pset, err := sb.governance.EffectiveParams(number)
   267  	if err != nil {
   268  		return err
   269  	}
   270  	pendingBlockNum := new(big.Int).Add(chain.CurrentHeader().Number, common.Big1)
   271  	if number%pset.Epoch() == 0 && len(header.Governance) > 0 && pendingBlockNum.Cmp(header.Number) == 0 {
   272  		if err := sb.governance.VerifyGovernance(header.Governance); err != nil {
   273  			return err
   274  		}
   275  	}
   276  	return sb.verifyCommittedSeals(chain, header, parents)
   277  }
   278  
   279  // VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers
   280  // concurrently. The method returns a quit channel to abort the operations and
   281  // a results channel to retrieve the async verifications (the order is that of
   282  // the input slice).
   283  func (sb *backend) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) {
   284  	abort := make(chan struct{})
   285  	results := make(chan error, len(headers))
   286  	go func() {
   287  		for i, header := range headers {
   288  			err := sb.verifyHeader(chain, header, headers[:i])
   289  
   290  			select {
   291  			case <-abort:
   292  				return
   293  			case results <- err:
   294  			}
   295  		}
   296  	}()
   297  	return abort, results
   298  }
   299  
   300  // verifySigner checks whether the signer is in parent's validator set
   301  func (sb *backend) verifySigner(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error {
   302  	// Verifying the genesis block is not supported
   303  	number := header.Number.Uint64()
   304  	if number == 0 {
   305  		return errUnknownBlock
   306  	}
   307  
   308  	// Retrieve the snapshot needed to verify this header and cache it
   309  	snap, err := sb.snapshot(chain, number-1, header.ParentHash, parents, true)
   310  	if err != nil {
   311  		return err
   312  	}
   313  
   314  	// resolve the authorization key and check against signers
   315  	signer, err := ecrecover(header)
   316  	if err != nil {
   317  		return err
   318  	}
   319  
   320  	// Signer should be in the validator set of previous block's extraData.
   321  	if _, v := snap.ValSet.GetByAddress(signer); v == nil {
   322  		return errUnauthorized
   323  	}
   324  	return nil
   325  }
   326  
   327  // verifyCommittedSeals checks whether every committed seal is signed by one of the parent's validators
   328  func (sb *backend) verifyCommittedSeals(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error {
   329  	number := header.Number.Uint64()
   330  	// We don't need to verify committed seals in the genesis block
   331  	if number == 0 {
   332  		return nil
   333  	}
   334  
   335  	// Retrieve the snapshot needed to verify this header and cache it
   336  	snap, err := sb.snapshot(chain, number-1, header.ParentHash, parents, true)
   337  	if err != nil {
   338  		return err
   339  	}
   340  
   341  	extra, err := types.ExtractIstanbulExtra(header)
   342  	if err != nil {
   343  		return err
   344  	}
   345  	// The length of Committed seals should be larger than 0
   346  	if len(extra.CommittedSeal) == 0 {
   347  		return errEmptyCommittedSeals
   348  	}
   349  
   350  	validators := snap.ValSet.Copy()
   351  	// Check whether the committed seals are generated by parent's validators
   352  	validSeal := 0
   353  	proposalSeal := istanbulCore.PrepareCommittedSeal(header.Hash())
   354  	// 1. Get committed seals from current header
   355  	for _, seal := range extra.CommittedSeal {
   356  		// 2. Get the original address by seal and parent block hash
   357  		addr, err := cacheSignatureAddresses(proposalSeal, seal)
   358  		if err != nil {
   359  			return errInvalidSignature
   360  		}
   361  		// Every validator can have only one seal. If more than one seals are signed by a
   362  		// validator, the validator cannot be found and errInvalidCommittedSeals is returned.
   363  		if validators.RemoveValidator(addr) {
   364  			validSeal += 1
   365  		} else {
   366  			return errInvalidCommittedSeals
   367  		}
   368  	}
   369  
   370  	// The length of validSeal should be larger than number of faulty node + 1
   371  	if validSeal <= 2*snap.ValSet.F() {
   372  		return errInvalidCommittedSeals
   373  	}
   374  
   375  	return nil
   376  }
   377  
   378  // VerifySeal checks whether the crypto seal on a header is valid according to
   379  // the consensus rules of the given engine.
   380  func (sb *backend) VerifySeal(chain consensus.ChainReader, header *types.Header) error {
   381  	// get parent header and ensure the signer is in parent's validator set
   382  	number := header.Number.Uint64()
   383  	if number == 0 {
   384  		return errUnknownBlock
   385  	}
   386  
   387  	// ensure that the blockscore equals to defaultBlockScore
   388  	if header.BlockScore.Cmp(defaultBlockScore) != 0 {
   389  		return errInvalidBlockScore
   390  	}
   391  	return sb.verifySigner(chain, header, nil)
   392  }
   393  
   394  // Prepare initializes the consensus fields of a block header according to the
   395  // rules of a particular engine. The changes are executed inline.
   396  func (sb *backend) Prepare(chain consensus.ChainReader, header *types.Header) error {
   397  	// unused fields, force to set to empty
   398  	header.Rewardbase = sb.rewardbase
   399  
   400  	// copy the parent extra data as the header extra data
   401  	number := header.Number.Uint64()
   402  	parent := chain.GetHeader(header.ParentHash, number-1)
   403  	if parent == nil {
   404  		return consensus.ErrUnknownAncestor
   405  	}
   406  	// use the same blockscore for all blocks
   407  	header.BlockScore = defaultBlockScore
   408  
   409  	// Assemble the voting snapshot
   410  	snap, err := sb.snapshot(chain, number-1, header.ParentHash, nil, true)
   411  	if err != nil {
   412  		return err
   413  	}
   414  
   415  	// If it reaches the Epoch, governance config will be added to block header
   416  	pset, err := sb.governance.EffectiveParams(number)
   417  	if err != nil {
   418  		return err
   419  	}
   420  	if number%pset.Epoch() == 0 {
   421  		if g := sb.governance.GetGovernanceChange(); g != nil {
   422  			if data, err := json.Marshal(g); err != nil {
   423  				logger.Error("Failed to encode governance changes!! Possible configuration mismatch!! ")
   424  			} else {
   425  				if header.Governance, err = rlp.EncodeToBytes(data); err != nil {
   426  					logger.Error("Failed to encode governance data for the header", "num", number)
   427  				} else {
   428  					logger.Info("Put governanceData", "num", number, "data", hex.EncodeToString(header.Governance))
   429  				}
   430  			}
   431  		}
   432  	}
   433  
   434  	// if there is a vote to attach, attach it to the header
   435  	header.Vote = sb.governance.GetEncodedVote(sb.address, number)
   436  	if len(header.Vote) > 0 {
   437  		logger.Info("Put voteData", "num", number, "data", hex.EncodeToString(header.Vote))
   438  	}
   439  
   440  	if chain.Config().IsRandaoForkEnabled(header.Number) {
   441  		prevMixHash := headerMixHash(chain, parent)
   442  		randomReveal, mixHash, err := sb.CalcRandao(header.Number, prevMixHash)
   443  		if err != nil {
   444  			return err
   445  		}
   446  		header.RandomReveal = randomReveal
   447  		header.MixHash = mixHash
   448  	}
   449  
   450  	// add validators (council list) in snapshot to extraData's validators section
   451  	extra, err := prepareExtra(header, snap.validators())
   452  	if err != nil {
   453  		return err
   454  	}
   455  	header.Extra = extra
   456  
   457  	// set header's timestamp
   458  	header.Time = new(big.Int).Add(parent.Time, new(big.Int).SetUint64(sb.config.BlockPeriod))
   459  	header.TimeFoS = parent.TimeFoS
   460  	if header.Time.Int64() < time.Now().Unix() {
   461  		t := time.Now()
   462  		header.Time = big.NewInt(t.Unix())
   463  		header.TimeFoS = uint8((t.UnixNano() / 1000 / 1000 / 10) % 100)
   464  	}
   465  	return nil
   466  }
   467  
   468  // Finalize runs any post-transaction state modifications (e.g. block rewards)
   469  // and assembles the final block.
   470  //
   471  // Note, the block header and state database might be updated to reflect any
   472  // consensus rules that happen at finalization (e.g. block rewards).
   473  func (sb *backend) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction,
   474  	receipts []*types.Receipt,
   475  ) (*types.Block, error) {
   476  	// We can assure that if the magma hard forked block should have the field of base fee
   477  	if chain.Config().IsMagmaForkEnabled(header.Number) {
   478  		if header.BaseFee == nil {
   479  			logger.Error("Magma hard forked block should have baseFee", "blockNum", header.Number.Uint64())
   480  			return nil, errors.New("Invalid Magma block without baseFee")
   481  		}
   482  	} else if header.BaseFee != nil {
   483  		logger.Error("A block before Magma hardfork shouldn't have baseFee", "blockNum", header.Number.Uint64())
   484  		return nil, consensus.ErrInvalidBaseFee
   485  	}
   486  
   487  	var rewardSpec *reward.RewardSpec
   488  
   489  	rules := chain.Config().Rules(header.Number)
   490  	pset, err := sb.governance.EffectiveParams(header.Number.Uint64())
   491  	if err != nil {
   492  		return nil, err
   493  	}
   494  
   495  	// If sb.chain is nil, it means backend is not initialized yet.
   496  	if sb.chain != nil && !reward.IsRewardSimple(pset) {
   497  		// TODO-Klaytn Let's redesign below logic and remove dependency between block reward and istanbul consensus.
   498  
   499  		lastHeader := chain.CurrentHeader()
   500  		valSet := sb.getValidators(lastHeader.Number.Uint64(), lastHeader.Hash())
   501  
   502  		// Determine and update Rewardbase when mining. When mining, state root is not yet determined and will be determined at the end of this Finalize below.
   503  		if common.EmptyHash(header.Root) {
   504  			var logMsg string
   505  			_, nodeValidator := valSet.GetByAddress(sb.address)
   506  			if nodeValidator == nil || (nodeValidator.RewardAddress() == common.Address{}) {
   507  				logMsg = "No reward address for nodeValidator. Use node's rewardbase."
   508  			} else {
   509  				// use reward address of current node.
   510  				// only a block made by proposer will be accepted. However, due to round change any node can be the proposer of a block.
   511  				// so need to write reward address of current node to receive reward when it becomes proposer.
   512  				// if current node does not become proposer, the block will be abandoned
   513  				header.Rewardbase = nodeValidator.RewardAddress()
   514  				logMsg = "Use reward address for nodeValidator."
   515  			}
   516  			logger.Trace(logMsg, "header.Number", header.Number.Uint64(), "node address", sb.address, "rewardbase", header.Rewardbase)
   517  		}
   518  
   519  		rewardSpec, err = reward.CalcDeferredReward(header, rules, pset)
   520  	} else {
   521  		rewardSpec, err = reward.CalcDeferredRewardSimple(header, rules, pset)
   522  	}
   523  
   524  	if err != nil {
   525  		return nil, err
   526  	}
   527  
   528  	reward.DistributeBlockReward(state, rewardSpec.Rewards)
   529  
   530  	// Only on the KIP-103 hardfork block, the following logic should be executed
   531  	if chain.Config().IsKIP103ForkBlock(header.Number) {
   532  		// RebalanceTreasury can modify the global state (state),
   533  		// so the existing state db should be used to apply the rebalancing result.
   534  		c := &Kip103ContractCaller{state, chain, header}
   535  		result, err := RebalanceTreasury(state, chain, header, c)
   536  		if err != nil {
   537  			logger.Error("failed to execute treasury rebalancing (KIP-103). State not changed", "err", err)
   538  		} else {
   539  			memo, err := json.Marshal(result)
   540  			if err != nil {
   541  				logger.Warn("failed to marshal KIP-103 result", "err", err, "result", result)
   542  			}
   543  			logger.Info("successfully executed treasury rebalancing (KIP-103)", "memo", string(memo))
   544  		}
   545  	}
   546  
   547  	// The Registry contract must be immediately available from the fork block.
   548  	// So it is installed at block (RandaoCompatibleBlock - 1) which is before the fork block.
   549  	if chain.Config().IsRandaoForkBlock(header.Number) {
   550  		err := system.InstallRegistry(state, chain.Config().RandaoRegistry)
   551  		if err != nil {
   552  			return nil, err
   553  		}
   554  	}
   555  
   556  	header.Root = state.IntermediateRoot(true)
   557  
   558  	// Assemble and return the final block for sealing
   559  	return types.NewBlock(header, txs, receipts), nil
   560  }
   561  
   562  // Seal generates a new block for the given input block with the local miner's
   563  // seal place on top.
   564  func (sb *backend) Seal(chain consensus.ChainReader, block *types.Block, stop <-chan struct{}) (*types.Block, error) {
   565  	// update the block header timestamp and signature and propose the block to core engine
   566  	header := block.Header()
   567  	number := header.Number.Uint64()
   568  
   569  	// Bail out if we're unauthorized to sign a block
   570  	snap, err := sb.snapshot(chain, number-1, header.ParentHash, nil, true)
   571  	if err != nil {
   572  		return nil, err
   573  	}
   574  	if _, v := snap.ValSet.GetByAddress(sb.address); v == nil {
   575  		return nil, errUnauthorized
   576  	}
   577  
   578  	parent := chain.GetHeader(header.ParentHash, number-1)
   579  	if parent == nil {
   580  		return nil, consensus.ErrUnknownAncestor
   581  	}
   582  	block, err = sb.updateBlock(block)
   583  	if err != nil {
   584  		return nil, err
   585  	}
   586  
   587  	// wait for the timestamp of header, use this to adjust the block period
   588  	delay := time.Unix(block.Header().Time.Int64(), 0).Sub(now())
   589  	select {
   590  	case <-time.After(delay):
   591  	case <-stop:
   592  		return nil, nil
   593  	}
   594  
   595  	// get the proposed block hash and clear it if the seal() is completed.
   596  	sb.sealMu.Lock()
   597  	sb.proposedBlockHash = block.Hash()
   598  	clear := func() {
   599  		sb.proposedBlockHash = common.Hash{}
   600  		sb.sealMu.Unlock()
   601  	}
   602  	defer clear()
   603  
   604  	// post block into Istanbul engine
   605  	go sb.EventMux().Post(istanbul.RequestEvent{
   606  		Proposal: block,
   607  	})
   608  
   609  	for {
   610  		select {
   611  		case result := <-sb.commitCh:
   612  			if result == nil {
   613  				return nil, nil
   614  			}
   615  			// if the block hash and the hash from channel are the same,
   616  			// return the result. Otherwise, keep waiting the next hash.
   617  			block = types.SetRoundToBlock(block, result.Round)
   618  			if block.Hash() == result.Block.Hash() {
   619  				return result.Block, nil
   620  			}
   621  		case <-stop:
   622  			return nil, nil
   623  		}
   624  	}
   625  }
   626  
   627  // update timestamp and signature of the block based on its number of transactions
   628  func (sb *backend) updateBlock(block *types.Block) (*types.Block, error) {
   629  	header := block.Header()
   630  	// sign the hash
   631  	seal, err := sb.Sign(sigHash(header).Bytes())
   632  	if err != nil {
   633  		return nil, err
   634  	}
   635  
   636  	err = writeSeal(header, seal)
   637  	if err != nil {
   638  		return nil, err
   639  	}
   640  
   641  	return block.WithSeal(header), nil
   642  }
   643  
   644  func (sb *backend) CalcBlockScore(chain consensus.ChainReader, time uint64, parent *types.Header) *big.Int {
   645  	return big.NewInt(0)
   646  }
   647  
   648  // APIs returns the RPC APIs this consensus engine provides.
   649  func (sb *backend) APIs(chain consensus.ChainReader) []rpc.API {
   650  	return []rpc.API{
   651  		{
   652  			Namespace: "istanbul",
   653  			Version:   "1.0",
   654  			Service:   &API{chain: chain, istanbul: sb},
   655  			Public:    true,
   656  		}, {
   657  			Namespace: "klay",
   658  			Version:   "1.0",
   659  			Service:   &APIExtension{chain: chain, istanbul: sb},
   660  			Public:    true,
   661  		},
   662  	}
   663  }
   664  
   665  // SetChain sets chain of the Istanbul backend
   666  func (sb *backend) SetChain(chain consensus.ChainReader) {
   667  	sb.chain = chain
   668  }
   669  
   670  // Start implements consensus.Istanbul.Start
   671  func (sb *backend) Start(chain consensus.ChainReader, currentBlock func() *types.Block, hasBadBlock func(hash common.Hash) bool) error {
   672  	sb.coreMu.Lock()
   673  	defer sb.coreMu.Unlock()
   674  	if sb.coreStarted {
   675  		return istanbul.ErrStartedEngine
   676  	}
   677  
   678  	// clear previous data
   679  	sb.proposedBlockHash = common.Hash{}
   680  	if sb.commitCh != nil {
   681  		close(sb.commitCh)
   682  	}
   683  	sb.commitCh = make(chan *types.Result, 1)
   684  
   685  	sb.SetChain(chain)
   686  	sb.currentBlock = currentBlock
   687  	sb.hasBadBlock = hasBadBlock
   688  
   689  	if err := sb.core.Start(); err != nil {
   690  		return err
   691  	}
   692  
   693  	sb.coreStarted = true
   694  	return nil
   695  }
   696  
   697  // Stop implements consensus.Istanbul.Stop
   698  func (sb *backend) Stop() error {
   699  	sb.coreMu.Lock()
   700  	defer sb.coreMu.Unlock()
   701  	if !sb.coreStarted {
   702  		return istanbul.ErrStoppedEngine
   703  	}
   704  	if err := sb.core.Stop(); err != nil {
   705  		return err
   706  	}
   707  	sb.coreStarted = false
   708  	return nil
   709  }
   710  
   711  // UpdateParam implements consensus.Istanbul.UpdateParam and it updates the governance parameters
   712  func (sb *backend) UpdateParam(number uint64) error {
   713  	if err := sb.governance.UpdateParams(number); err != nil {
   714  		return err
   715  	}
   716  	return nil
   717  }
   718  
   719  // initSnapshot initializes and stores a new Snapshot.
   720  func (sb *backend) initSnapshot(chain consensus.ChainReader) (*Snapshot, error) {
   721  	genesis := chain.GetHeaderByNumber(0)
   722  	if err := sb.VerifyHeader(chain, genesis, false); err != nil {
   723  		return nil, err
   724  	}
   725  	istanbulExtra, err := types.ExtractIstanbulExtra(genesis)
   726  	if err != nil {
   727  		return nil, err
   728  	}
   729  
   730  	pset, err := sb.governance.EffectiveParams(0)
   731  	if err != nil {
   732  		return nil, err
   733  	}
   734  	valSet := validator.NewValidatorSet(istanbulExtra.Validators, nil,
   735  		istanbul.ProposerPolicy(pset.Policy()),
   736  		pset.CommitteeSize(), chain)
   737  	valSet.SetMixHash(genesis.MixHash)
   738  	snap := newSnapshot(sb.governance, 0, genesis.Hash(), valSet, chain.Config())
   739  
   740  	if err := snap.store(sb.db); err != nil {
   741  		return nil, err
   742  	}
   743  	logger.Trace("Stored genesis voting snapshot to disk")
   744  	return snap, nil
   745  }
   746  
   747  // getPrevHeaderAndUpdateParents returns previous header to find stored Snapshot object and drops the last element of the parents parameter.
   748  func getPrevHeaderAndUpdateParents(chain consensus.ChainReader, number uint64, hash common.Hash, parents *[]*types.Header) *types.Header {
   749  	var header *types.Header
   750  	if len(*parents) > 0 {
   751  		// If we have explicit parents, pick from there (enforced)
   752  		header = (*parents)[len(*parents)-1]
   753  		if header.Hash() != hash || header.Number.Uint64() != number {
   754  			return nil
   755  		}
   756  		*parents = (*parents)[:len(*parents)-1]
   757  	} else {
   758  		// No explicit parents (or no more left), reach out to the database
   759  		header = chain.GetHeader(hash, number)
   760  		if header == nil {
   761  			return nil
   762  		}
   763  	}
   764  	return header
   765  }
   766  
   767  // CreateSnapshot does not return a snapshot but creates a new snapshot if not exists at a given point in time
   768  func (sb *backend) CreateSnapshot(chain consensus.ChainReader, number uint64, hash common.Hash, parents []*types.Header) error {
   769  	if _, err := sb.snapshot(chain, number, hash, parents, true); err != nil {
   770  		return err
   771  	}
   772  	return nil
   773  }
   774  
   775  // GetConsensusInfo returns consensus information regarding the given block number.
   776  func (sb *backend) GetConsensusInfo(block *types.Block) (consensus.ConsensusInfo, error) {
   777  	blockNumber := block.NumberU64()
   778  	if blockNumber == 0 {
   779  		return consensus.ConsensusInfo{}, nil
   780  	}
   781  
   782  	round := block.Header().Round()
   783  	view := &istanbul.View{
   784  		Sequence: new(big.Int).Set(block.Number()),
   785  		Round:    new(big.Int).SetInt64(int64(round)),
   786  	}
   787  
   788  	// get the proposer of this block.
   789  	proposer, err := ecrecover(block.Header())
   790  	if err != nil {
   791  		return consensus.ConsensusInfo{}, err
   792  	}
   793  
   794  	if sb.chain == nil {
   795  		return consensus.ConsensusInfo{}, errNoChainReader
   796  	}
   797  
   798  	// get the snapshot of the previous block.
   799  	parentHash := block.ParentHash()
   800  	snap, err := sb.snapshot(sb.chain, blockNumber-1, parentHash, nil, false)
   801  	if err != nil {
   802  		logger.Error("Failed to get snapshot.", "blockNum", blockNumber, "err", err)
   803  		return consensus.ConsensusInfo{}, errInternalError
   804  	}
   805  
   806  	// get origin proposer at 0 round.
   807  	originProposer := common.Address{}
   808  	lastProposer := sb.GetProposer(blockNumber - 1)
   809  
   810  	newValSet := snap.ValSet.Copy()
   811  	newValSet.CalcProposer(lastProposer, 0)
   812  	originProposer = newValSet.GetProposer().Address()
   813  
   814  	// get the committee list of this block at the view (blockNumber, round)
   815  	committee := snap.ValSet.SubListWithProposer(parentHash, proposer, view)
   816  	committeeAddrs := make([]common.Address, len(committee))
   817  	for i, v := range committee {
   818  		committeeAddrs[i] = v.Address()
   819  	}
   820  
   821  	// get the committers of this block from committed seals
   822  	extra, err := types.ExtractIstanbulExtra(block.Header())
   823  	if err != nil {
   824  		return consensus.ConsensusInfo{}, err
   825  	}
   826  	committers, err := RecoverCommittedSeals(extra, block.Hash())
   827  	if err != nil {
   828  		return consensus.ConsensusInfo{}, err
   829  	}
   830  
   831  	// Uncomment to validate if committers are in the committee
   832  	// for _, recovered := range committers {
   833  	// 	found := false
   834  	// 	for _, calculated := range committeeAddrs {
   835  	// 		if recovered == calculated {
   836  	// 			found = true
   837  	// 		}
   838  	// 	}
   839  	// 	if !found {
   840  	// 		return consensus.ConsensusInfo{}, errInvalidCommittedSeals
   841  	// 	}
   842  	// }
   843  
   844  	cInfo := consensus.ConsensusInfo{
   845  		SigHash:        sigHash(block.Header()),
   846  		Proposer:       proposer,
   847  		OriginProposer: originProposer,
   848  		Committee:      committeeAddrs,
   849  		Committers:     committers,
   850  		Round:          round,
   851  	}
   852  
   853  	return cInfo, nil
   854  }
   855  
   856  func (sb *backend) InitSnapshot() {
   857  	sb.recents.Purge()
   858  	sb.blsPubkeyProvider.ResetBlsCache()
   859  }
   860  
   861  // snapshot retrieves the state of the authorization voting at a given point in time.
   862  // There's in-memory snapshot and on-disk snapshot. On-disk snapshot is stored every checkpointInterval blocks.
   863  // Moreover, if the block has no in-memory or on-disk snapshot, before generating snapshot, it gathers the header and apply the vote in it.
   864  func (sb *backend) snapshot(chain consensus.ChainReader, number uint64, hash common.Hash, parents []*types.Header, writable bool) (*Snapshot, error) {
   865  	// Search for a snapshot in memory or on disk for checkpoints
   866  	var (
   867  		headers []*types.Header
   868  		snap    *Snapshot
   869  	)
   870  
   871  	for snap == nil {
   872  		// If an in-memory snapshot was found, use that
   873  		if s, ok := sb.recents.Get(hash); ok {
   874  			snap = s.(*Snapshot)
   875  			break
   876  		}
   877  		// If an on-disk checkpoint snapshot can be found, use that
   878  		if params.IsCheckpointInterval(number) {
   879  			if s, err := loadSnapshot(sb.db, hash); err == nil {
   880  				logger.Trace("Loaded voting snapshot form disk", "number", number, "hash", hash)
   881  				snap = s
   882  				break
   883  			}
   884  		}
   885  		// If we're at block zero, make a snapshot
   886  		if number == 0 {
   887  			var err error
   888  			if snap, err = sb.initSnapshot(chain); err != nil {
   889  				return nil, err
   890  			}
   891  			break
   892  		}
   893  		// No snapshot for this header, gather the header and move backward
   894  		if header := getPrevHeaderAndUpdateParents(chain, number, hash, &parents); header == nil {
   895  			return nil, consensus.ErrUnknownAncestor
   896  		} else {
   897  			headers = append(headers, header)
   898  			number, hash = number-1, header.ParentHash
   899  		}
   900  	}
   901  	// Previous snapshot found, apply any pending headers on top of it
   902  	for i := 0; i < len(headers)/2; i++ {
   903  		headers[i], headers[len(headers)-1-i] = headers[len(headers)-1-i], headers[i]
   904  	}
   905  	pset, err := sb.governance.EffectiveParams(number)
   906  	if err != nil {
   907  		return nil, err
   908  	}
   909  	snap, err = snap.apply(headers, sb.governance, sb.address, pset.Policy(), chain, writable)
   910  	if err != nil {
   911  		return nil, err
   912  	}
   913  
   914  	// If we've generated a new checkpoint snapshot, save to disk
   915  	if writable && params.IsCheckpointInterval(snap.Number) && len(headers) > 0 {
   916  		if sb.governance.CanWriteGovernanceState(snap.Number) {
   917  			sb.governance.WriteGovernanceState(snap.Number, true)
   918  		}
   919  		if err = snap.store(sb.db); err != nil {
   920  			return nil, err
   921  		}
   922  		logger.Trace("Stored voting snapshot to disk", "number", snap.Number, "hash", snap.Hash)
   923  	}
   924  
   925  	sb.regen(chain, headers)
   926  
   927  	sb.recents.Add(snap.Hash, snap)
   928  	return snap, err
   929  }
   930  
   931  // regen commits snapshot data to database
   932  // regen is triggered if there is any checkpoint block in the `headers`.
   933  // For each checkpoint block, this function verifies the existence of its snapshot in DB and stores one if missing.
   934  /*
   935   Triggered:
   936   |   ^                          ^                          ^                          ^  ...|
   937       SI                 SI*(last snapshot)                 SI                         SI
   938         			   | header1, .. headerN |
   939   Not triggered: (Guaranteed SI* was committed before )
   940   |   ^                          ^                          ^                          ^  ...|
   941       SI                 SI*(last snapshot)                 SI                         SI
   942  	                            | header1, .. headerN |
   943  */
   944  func (sb *backend) regen(chain consensus.ChainReader, headers []*types.Header) {
   945  	// Prevent nested call. Ignore header length one
   946  	// because it was handled before the `regen` called.
   947  	if !sb.isRestoringSnapshots.CompareAndSwap(false, true) || len(headers) <= 1 {
   948  		return
   949  	}
   950  	defer func() {
   951  		sb.isRestoringSnapshots.Store(false)
   952  	}()
   953  
   954  	var (
   955  		from        = headers[0].Number.Uint64()
   956  		to          = headers[len(headers)-1].Number.Uint64()
   957  		start       = time.Now()
   958  		commitTried = false
   959  	)
   960  
   961  	// Shortcut: No missing snapshot data to be processed.
   962  	if to-(to%uint64(params.CheckpointInterval)) < from {
   963  		return
   964  	}
   965  
   966  	for _, header := range headers {
   967  		var (
   968  			hn = header.Number.Uint64()
   969  			hh = header.Hash()
   970  		)
   971  		if params.IsCheckpointInterval(hn) {
   972  			// Store snapshot data if it was not committed before
   973  			if loadSnap, _ := sb.db.ReadIstanbulSnapshot(hh); loadSnap != nil {
   974  				continue
   975  			}
   976  			snap, err := sb.snapshot(chain, hn, hh, nil, false)
   977  			if err != nil {
   978  				logger.Warn("[Snapshot] Snapshot restoring failed", "len(headers)", len(headers), "from", from, "to", to, "headerNumber", hn)
   979  				continue
   980  			}
   981  			if err = snap.store(sb.db); err != nil {
   982  				logger.Warn("[Snapshot] Snapshot restoring failed", "len(headers)", len(headers), "from", from, "to", to, "headerNumber", hn)
   983  			}
   984  			commitTried = true
   985  		}
   986  	}
   987  	if commitTried { // This prevents pushing too many logs by potential DoS attack
   988  		logger.Trace("[Snapshot] Snapshot restoring completed", "len(headers)", len(headers), "from", from, "to", to, "elapsed", time.Since(start))
   989  	}
   990  }
   991  
   992  // FIXME: Need to update this for Istanbul
   993  // sigHash returns the hash which is used as input for the Istanbul
   994  // signing. It is the hash of the entire header apart from the 65 byte signature
   995  // contained at the end of the extra data.
   996  //
   997  // Note, the method requires the extra data to be at least 65 bytes, otherwise it
   998  // panics. This is done to avoid accidentally using both forms (signature present
   999  // or not), which could be abused to produce different hashes for the same header.
  1000  func sigHash(header *types.Header) (hash common.Hash) {
  1001  	hasher := sha3.NewKeccak256()
  1002  
  1003  	// Clean seal is required for calculating proposer seal.
  1004  	rlp.Encode(hasher, types.IstanbulFilteredHeader(header, false))
  1005  	hasher.Sum(hash[:0])
  1006  	return hash
  1007  }
  1008  
  1009  // ecrecover extracts the Klaytn account address from a signed header.
  1010  func ecrecover(header *types.Header) (common.Address, error) {
  1011  	// Retrieve the signature from the header extra-data
  1012  	istanbulExtra, err := types.ExtractIstanbulExtra(header)
  1013  	if err != nil {
  1014  		return common.Address{}, err
  1015  	}
  1016  	addr, err := cacheSignatureAddresses(sigHash(header).Bytes(), istanbulExtra.Seal)
  1017  	if err != nil {
  1018  		return addr, err
  1019  	}
  1020  
  1021  	return addr, nil
  1022  }
  1023  
  1024  // prepareExtra returns a extra-data of the given header and validators
  1025  func prepareExtra(header *types.Header, vals []common.Address) ([]byte, error) {
  1026  	var buf bytes.Buffer
  1027  
  1028  	// compensate the lack bytes if header.Extra is not enough IstanbulExtraVanity bytes.
  1029  	if len(header.Extra) < types.IstanbulExtraVanity {
  1030  		header.Extra = append(header.Extra, bytes.Repeat([]byte{0x00}, types.IstanbulExtraVanity-len(header.Extra))...)
  1031  	}
  1032  	buf.Write(header.Extra[:types.IstanbulExtraVanity])
  1033  
  1034  	ist := &types.IstanbulExtra{
  1035  		Validators:    vals,
  1036  		Seal:          []byte{},
  1037  		CommittedSeal: [][]byte{},
  1038  	}
  1039  
  1040  	payload, err := rlp.EncodeToBytes(&ist)
  1041  	if err != nil {
  1042  		return nil, err
  1043  	}
  1044  
  1045  	return append(buf.Bytes(), payload...), nil
  1046  }
  1047  
  1048  // writeSeal writes the extra-data field of the given header with the given seals.
  1049  // suggest to rename to writeSeal.
  1050  func writeSeal(h *types.Header, seal []byte) error {
  1051  	if len(seal)%types.IstanbulExtraSeal != 0 {
  1052  		return errInvalidSignature
  1053  	}
  1054  
  1055  	istanbulExtra, err := types.ExtractIstanbulExtra(h)
  1056  	if err != nil {
  1057  		return err
  1058  	}
  1059  
  1060  	istanbulExtra.Seal = seal
  1061  	payload, err := rlp.EncodeToBytes(&istanbulExtra)
  1062  	if err != nil {
  1063  		return err
  1064  	}
  1065  
  1066  	h.Extra = append(h.Extra[:types.IstanbulExtraVanity], payload...)
  1067  	return nil
  1068  }
  1069  
  1070  // writeCommittedSeals writes the extra-data field of a block header with given committed seals.
  1071  func writeCommittedSeals(h *types.Header, committedSeals [][]byte) error {
  1072  	if len(committedSeals) == 0 {
  1073  		return errInvalidCommittedSeals
  1074  	}
  1075  
  1076  	for _, seal := range committedSeals {
  1077  		if len(seal) != types.IstanbulExtraSeal {
  1078  			return errInvalidCommittedSeals
  1079  		}
  1080  	}
  1081  
  1082  	istanbulExtra, err := types.ExtractIstanbulExtra(h)
  1083  	if err != nil {
  1084  		return err
  1085  	}
  1086  
  1087  	istanbulExtra.CommittedSeal = make([][]byte, len(committedSeals))
  1088  	copy(istanbulExtra.CommittedSeal, committedSeals)
  1089  
  1090  	payload, err := rlp.EncodeToBytes(&istanbulExtra)
  1091  	if err != nil {
  1092  		return err
  1093  	}
  1094  
  1095  	h.Extra = append(h.Extra[:types.IstanbulExtraVanity], payload...)
  1096  	return nil
  1097  }