github.com/intfoundation/intchain@v0.0.0-20220727031208-4316ad31ca73/consensus/ipbft/engine.go (about)

     1  package ipbft
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"github.com/hashicorp/golang-lru"
     7  	"github.com/intfoundation/go-wire"
     8  	"github.com/intfoundation/intchain/common"
     9  	"github.com/intfoundation/intchain/consensus"
    10  	"github.com/intfoundation/intchain/consensus/ipbft/epoch"
    11  	tdmTypes "github.com/intfoundation/intchain/consensus/ipbft/types"
    12  	"github.com/intfoundation/intchain/core/state"
    13  	"github.com/intfoundation/intchain/core/types"
    14  	"github.com/intfoundation/intchain/params"
    15  	"github.com/intfoundation/intchain/rpc"
    16  	"math/big"
    17  	"time"
    18  )
    19  
    20  const (
    21  	// fetcherID is the ID indicates the block is from Tendermint engine
    22  	fetcherID = "ipbft"
    23  )
    24  
    25  var (
    26  	// errInvalidProposal is returned when a prposal is malformed.
    27  	errInvalidProposal = errors.New("invalid proposal")
    28  	// errInvalidSignature is returned when given signature is not signed by given
    29  	// address.
    30  	errInvalidSignature = errors.New("invalid signature")
    31  	// errUnknownBlock is returned when the list of validators is requested for a block
    32  	// that is not part of the local blockchain.
    33  	errUnknownBlock = errors.New("unknown block")
    34  	// errUnauthorized is returned if a header is signed by a non authorized entity.
    35  	errUnauthorized = errors.New("unauthorized")
    36  	// errInvalidDifficulty is returned if the difficulty of a block is not 1
    37  	errInvalidDifficulty = errors.New("invalid difficulty")
    38  	// errInvalidExtraDataFormat is returned when the extra data format is incorrect
    39  	errInvalidExtraDataFormat = errors.New("invalid extra data format")
    40  	// errInvalidMixDigest is returned if a block's mix digest is not Istanbul digest.
    41  	errInvalidMixDigest = errors.New("invalid Tendermint mix digest")
    42  	// errInvalidNonce is returned if a block's nonce is invalid
    43  	errInvalidNonce = errors.New("invalid nonce")
    44  	// errInvalidUncleHash is returned if a block contains an non-empty uncle list.
    45  	errInvalidUncleHash = errors.New("non empty uncle hash")
    46  	// errInconsistentValidatorSet is returned if the validator set is inconsistent
    47  	errInconsistentValidatorSet = errors.New("inconsistent validator set")
    48  	// errInvalidTimestamp is returned if the timestamp of a block is lower than the previous block's timestamp + the minimum block period.
    49  	errInvalidTimestamp = errors.New("invalid timestamp")
    50  	// errInvalidVotingChain is returned if an authorization list is attempted to
    51  	// be modified via out-of-range or non-contiguous headers.
    52  	errInvalidVotingChain = errors.New("invalid voting chain")
    53  	// errInvalidVote is returned if a nonce value is something else that the two
    54  	// allowed constants of 0x00..0 or 0xff..f.
    55  	errInvalidVote = errors.New("vote nonce not 0x00..0 or 0xff..f")
    56  	// errInvalidCommittedSeals is returned if the committed seal is not signed by any of parent validators.
    57  	errInvalidCommittedSeals = errors.New("invalid committed seals")
    58  	// errEmptyCommittedSeals is returned if the field of committed seals is zero.
    59  	errEmptyCommittedSeals = errors.New("zero committed seals")
    60  	// errMismatchTxhashes is returned if the TxHash in header is mismatch.
    61  	errMismatchTxhashes = errors.New("mismatch transactions hashes")
    62  
    63  	// errInvalidMainChainNumber is returned when child chain block doesn't contain the valid main chain height
    64  	errInvalidMainChainNumber = errors.New("invalid Main Chain Height")
    65  	// errMainChainNotCatchup is returned if child chain wait more than 300 seconds for main chain to catch up
    66  	errMainChainNotCatchup = errors.New("unable proceed the block due to main chain not catch up by waiting for more than 300 seconds, please catch up the main chain first")
    67  )
    68  
    69  var (
    70  	now = time.Now
    71  
    72  	inmemoryAddresses  = 20 // Number of recent addresses from ecrecover
    73  	recentAddresses, _ = lru.NewARC(inmemoryAddresses)
    74  
    75  	_ consensus.Engine = (*backend)(nil)
    76  
    77  	foundationAddress = common.HexToAddress("0x0000000000000000000000000000000000000000")
    78  	feeAddress        = common.HexToAddress("0x0000000000000000000000000000000000000001")
    79  
    80  	// Address for Child Chain Reward
    81  	childChainRewardAddress = common.StringToAddress("0x0000000000000000000000000000000000001003")
    82  )
    83  
    84  // APIs returns the RPC APIs this consensus engine provides.
    85  func (sb *backend) APIs(chain consensus.ChainReader) []rpc.API {
    86  	return []rpc.API{{
    87  		Namespace: "int",
    88  		Version:   "1.0",
    89  		Service:   &API{chain: chain, tendermint: sb},
    90  		Public:    true,
    91  	}}
    92  }
    93  
    94  // Start implements consensus.Tendermint.Start
    95  func (sb *backend) Start(chain consensus.ChainReader, currentBlock func() *types.Block, hasBadBlock func(hash common.Hash) bool) error {
    96  
    97  	sb.logger.Info("IPBFT backend Start")
    98  
    99  	sb.coreMu.Lock()
   100  	defer sb.coreMu.Unlock()
   101  	if sb.coreStarted {
   102  		return ErrStartedEngine
   103  	}
   104  
   105  	// clear previous data
   106  	sb.proposedBlockHash = common.Hash{}
   107  	if sb.commitCh != nil {
   108  		close(sb.commitCh)
   109  	}
   110  	sb.commitCh = make(chan *types.Block, 1)
   111  	if sb.vcommitCh != nil {
   112  		close(sb.vcommitCh)
   113  	}
   114  	sb.vcommitCh = make(chan *tdmTypes.IntermediateBlockResult, 1)
   115  
   116  	sb.chain = chain
   117  	sb.currentBlock = currentBlock
   118  	sb.hasBadBlock = hasBadBlock
   119  
   120  	if _, err := sb.core.Start(); err != nil {
   121  		return err
   122  	}
   123  
   124  	sb.coreStarted = true
   125  
   126  	return nil
   127  }
   128  
   129  // Stop implements consensus.Tendermint.Stop
   130  func (sb *backend) Stop() error {
   131  
   132  	sb.logger.Info("IPBFT backend stop")
   133  
   134  	//debug.PrintStack()
   135  
   136  	sb.coreMu.Lock()
   137  	defer sb.coreMu.Unlock()
   138  	if !sb.coreStarted {
   139  		return ErrStoppedEngine
   140  	}
   141  	if !sb.core.Stop() {
   142  		return errors.New("ipbft stop error")
   143  	}
   144  	sb.coreStarted = false
   145  
   146  	return nil
   147  }
   148  
   149  func (sb *backend) Close() error {
   150  	sb.core.epochDB.Close()
   151  	return nil
   152  }
   153  
   154  // Author retrieves the Ethereum address of the account that minted the given
   155  // block, which may be different from the header's coinbase if a consensus
   156  // engine is based on signatures.
   157  func (sb *backend) Author(header *types.Header) (common.Address, error) {
   158  	return header.Coinbase, nil
   159  }
   160  
   161  // VerifyHeader checks whether a header conforms to the consensus rules of a
   162  // given engine. Verifying the seal may be done optionally here, or explicitly
   163  // via the VerifySeal method.
   164  func (sb *backend) VerifyHeader(chain consensus.ChainReader, header *types.Header, seal bool) error {
   165  
   166  	sb.logger.Info("IPBFT backend verify header")
   167  
   168  	return sb.verifyHeader(chain, header, nil)
   169  }
   170  
   171  // verifyHeader checks whether a header conforms to the consensus rules.The
   172  // caller may optionally pass in a batch of parents (ascending order) to avoid
   173  // looking those up from the database. This is useful for concurrently verifying
   174  // a batch of new headers.
   175  func (sb *backend) verifyHeader(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error {
   176  
   177  	if header.Number == nil {
   178  		return errUnknownBlock
   179  	}
   180  
   181  	//if header.Number.Uint64() == 0 {
   182  	//	return nil // Ignore verify for genesis block
   183  	//}
   184  
   185  	// Don't waste time checking blocks from the future
   186  	if header.Time.Cmp(big.NewInt(now().Unix())) > 0 {
   187  		sb.logger.Warnf("date/time different between different nodes. block from future with time:%v, bigger than now:%v", header.Time.Uint64(), now().Unix())
   188  		//in intchain, avoid the time difference to tolerate time gap between nodes
   189  		//return consensus.ErrFutureBlock
   190  	}
   191  
   192  	// Ensure that the extra data format is satisfied
   193  	if _, err := tdmTypes.ExtractTendermintExtra(header); err != nil {
   194  		return errInvalidExtraDataFormat
   195  	}
   196  
   197  	// Ensure that the coinbase is valid
   198  	if header.Nonce != (types.TendermintEmptyNonce) && !bytes.Equal(header.Nonce[:], types.TendermintNonce) {
   199  		return errInvalidNonce
   200  	}
   201  	// Ensure that the mix digest is zero as we don't have fork protection currently
   202  	if header.MixDigest != types.TendermintDigest {
   203  		return errInvalidMixDigest
   204  	}
   205  	// Ensure that the block doesn't contain any uncles which are meaningless in Istanbul
   206  	if header.UncleHash != types.TendermintNilUncleHash {
   207  		return errInvalidUncleHash
   208  	}
   209  	// Ensure that the block's difficulty is meaningful (may not be correct at this point)
   210  	if header.Difficulty == nil || header.Difficulty.Cmp(types.TendermintDefaultDifficulty) != 0 {
   211  		return errInvalidDifficulty
   212  	}
   213  
   214  	// In case of Epoch switch, we have to wait for the Epoch switched first, then verify the following fields
   215  	if header.Number.Uint64() > sb.GetEpoch().EndBlock {
   216  		for {
   217  			duration := 2 * time.Second
   218  			sb.logger.Infof("IPBFT VerifyHeader, Epoch Switch, wait for %v then try again", duration)
   219  			time.Sleep(duration)
   220  
   221  			if header.Number.Uint64() <= sb.GetEpoch().EndBlock {
   222  				break
   223  			}
   224  		}
   225  	}
   226  
   227  	if fieldError := sb.verifyCascadingFields(chain, header, parents); fieldError != nil {
   228  		return fieldError
   229  	}
   230  
   231  	// Check the MainChainNumber if on Child Chain
   232  	if !sb.chainConfig.IsMainChain() {
   233  		if header.MainChainNumber == nil {
   234  			return errInvalidMainChainNumber
   235  		}
   236  
   237  		tried := 0
   238  		for {
   239  			// Check our main chain has already run ahead
   240  			ourMainChainHeight := sb.core.cch.GetHeightFromMainChain()
   241  			if ourMainChainHeight.Cmp(header.MainChainNumber) >= 0 {
   242  				break
   243  			}
   244  
   245  			if tried == 10 {
   246  				sb.logger.Warnf("IPBFT VerifyHeader, Main Chain Number mismatch, after retried %d times", tried)
   247  				return errMainChainNotCatchup
   248  			}
   249  
   250  			// Sleep for a while and check again
   251  			duration := 30 * time.Second
   252  			tried++
   253  			sb.logger.Infof("IPBFT VerifyHeader, Main Chain Number mismatch, wait for %v then try again (count %d)", duration, tried)
   254  			time.Sleep(duration)
   255  		}
   256  	}
   257  
   258  	return nil
   259  }
   260  
   261  // verifyCascadingFields verifies all the header fields that are not standalone,
   262  // rather depend on a batch of previous headers. The caller may optionally pass
   263  // in a batch of parents (ascending order) to avoid looking those up from the
   264  // database. This is useful for concurrently verifying a batch of new headers.
   265  func (sb *backend) verifyCascadingFields(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error {
   266  	// The genesis block is the always valid dead-end
   267  
   268  	number := header.Number.Uint64()
   269  	if number == 0 {
   270  		return nil
   271  	}
   272  	// Ensure that the block's timestamp isn't too close to it's parent
   273  	var parent *types.Header
   274  	if len(parents) > 0 {
   275  		parent = parents[len(parents)-1]
   276  	} else {
   277  		parent = chain.GetHeader(header.ParentHash, number-1)
   278  	}
   279  	if parent == nil || parent.Number.Uint64() != number-1 || parent.Hash() != header.ParentHash {
   280  		return consensus.ErrUnknownAncestor
   281  	}
   282  
   283  	err := sb.verifyCommittedSeals(chain, header, parents)
   284  	return err
   285  }
   286  
   287  func (sb *backend) VerifyHeaderBeforeConsensus(chain consensus.ChainReader, header *types.Header, seal bool) error {
   288  	sb.logger.Info("IPBFT backend verify header before consensus")
   289  
   290  	if header.Number == nil {
   291  		return errUnknownBlock
   292  	}
   293  
   294  	// Don't waste time checking blocks from the future
   295  	if header.Time.Cmp(big.NewInt(now().Unix())) > 0 {
   296  		sb.logger.Warnf("date/time different between different nodes. block from future with time:%v, bigger than now:%v", header.Time.Uint64(), now().Unix())
   297  		//in intchain, avoid the time difference to tolerate time gap between nodes
   298  		//return consensus.ErrFutureBlock
   299  	}
   300  
   301  	// Ensure that the coinbase is valid
   302  	if header.Nonce != (types.TendermintEmptyNonce) && !bytes.Equal(header.Nonce[:], types.TendermintNonce) {
   303  		return errInvalidNonce
   304  	}
   305  	// Ensure that the mix digest is zero as we don't have fork protection currently
   306  	if header.MixDigest != types.TendermintDigest {
   307  		return errInvalidMixDigest
   308  	}
   309  	// Ensure that the block doesn't contain any uncles which are meaningless in Istanbul
   310  	if header.UncleHash != types.TendermintNilUncleHash {
   311  		return errInvalidUncleHash
   312  	}
   313  	// Ensure that the block's difficulty is meaningful (may not be correct at this point)
   314  	if header.Difficulty == nil || header.Difficulty.Cmp(types.TendermintDefaultDifficulty) != 0 {
   315  		return errInvalidDifficulty
   316  	}
   317  
   318  	return nil
   319  }
   320  
   321  // VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers
   322  // concurrently. The method returns a quit channel to abort the operations and
   323  // a results channel to retrieve the async verifications (the order is that of
   324  // the input slice).
   325  func (sb *backend) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) {
   326  	abort := make(chan struct{})
   327  	results := make(chan error, len(headers))
   328  
   329  	sb.logger.Info("IPBFT backend verify headers")
   330  
   331  	go func() {
   332  		for i, header := range headers {
   333  			err := sb.verifyHeader(chain, header, headers[:i])
   334  			select {
   335  			case <-abort:
   336  				return
   337  			case results <- err:
   338  			}
   339  		}
   340  	}()
   341  
   342  	return abort, results
   343  }
   344  
   345  // VerifyUncles verifies that the given block's uncles conform to the consensus
   346  // rules of a given engine.
   347  func (sb *backend) VerifyUncles(chain consensus.ChainReader, block *types.Block) error {
   348  
   349  	if len(block.Uncles()) > 0 {
   350  		return errInvalidUncleHash
   351  	}
   352  	return nil
   353  }
   354  
   355  // verifyCommittedSeals checks whether every committed seal is signed by one of the parent's validators
   356  func (sb *backend) verifyCommittedSeals(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error {
   357  
   358  	tdmExtra, err := tdmTypes.ExtractTendermintExtra(header)
   359  	if err != nil {
   360  		return errInvalidExtraDataFormat
   361  	}
   362  
   363  	epoch := sb.core.consensusState.Epoch
   364  	if epoch == nil || epoch.Validators == nil {
   365  		sb.logger.Errorf("verifyCommittedSeals error. Epoch %v", epoch)
   366  		return errInconsistentValidatorSet
   367  	}
   368  
   369  	epoch = epoch.GetEpochByBlockNumber(header.Number.Uint64())
   370  	if epoch == nil || epoch.Validators == nil {
   371  		sb.logger.Errorf("verifyCommittedSeals error. Epoch %v", epoch)
   372  		return errInconsistentValidatorSet
   373  	}
   374  
   375  	valSet := epoch.Validators
   376  	if !bytes.Equal(valSet.Hash(), tdmExtra.ValidatorsHash) {
   377  		sb.logger.Errorf("verifyCommittedSeals error. Our Validator Set %x, tdmExtra Valdiator %x", valSet.Hash(), tdmExtra.ValidatorsHash)
   378  		sb.logger.Errorf("verifyCommittedSeals error. epoch validator set %v, extra data %v", valSet.String(), tdmExtra.String())
   379  		return errInconsistentValidatorSet
   380  	}
   381  
   382  	seenCommit := tdmExtra.SeenCommit
   383  	if !bytes.Equal(tdmExtra.SeenCommitHash, seenCommit.Hash()) {
   384  		sb.logger.Errorf("verifyCommittedSeals SeenCommit is %#+v", seenCommit)
   385  		sb.logger.Errorf("verifyCommittedSeals error. Our SeenCommitHash %x, tdmExtra SeenCommitHash %x", seenCommit.Hash(), tdmExtra.SeenCommitHash)
   386  		return errInvalidCommittedSeals
   387  	}
   388  
   389  	if err = valSet.VerifyCommit(tdmExtra.ChainID, tdmExtra.Height, seenCommit); err != nil {
   390  		sb.logger.Errorf("verifyCommittedSeals verify commit err %v", err)
   391  		return errInvalidSignature
   392  	}
   393  
   394  	return nil
   395  }
   396  
   397  // VerifySeal checks whether the crypto seal on a header is valid according to
   398  // the consensus rules of the given engine.
   399  func (sb *backend) VerifySeal(chain consensus.ChainReader, header *types.Header) error {
   400  	// get parent header and ensure the signer is in parent's validator set
   401  	number := header.Number.Uint64()
   402  	if number == 0 {
   403  		return errUnknownBlock
   404  	}
   405  
   406  	// ensure that the difficulty equals to defaultDifficulty
   407  	if header.Difficulty.Cmp(types.TendermintDefaultDifficulty) != 0 {
   408  		return errInvalidDifficulty
   409  	}
   410  
   411  	return nil
   412  }
   413  
   414  // Prepare initializes the consensus fields of a block header according to the
   415  // rules of a particular engine. The changes are executed inline.
   416  func (sb *backend) Prepare(chain consensus.ChainReader, header *types.Header) error {
   417  
   418  	header.Nonce = types.TendermintEmptyNonce
   419  	header.MixDigest = types.TendermintDigest
   420  
   421  	// copy the parent extra data as the header extra data
   422  	number := header.Number.Uint64()
   423  	parent := chain.GetHeader(header.ParentHash, number-1)
   424  	if parent == nil {
   425  		return consensus.ErrUnknownAncestor
   426  	}
   427  	// use the same difficulty for all blocks
   428  	header.Difficulty = types.TendermintDefaultDifficulty
   429  
   430  	// add validators in snapshot to extraData's validators section
   431  	extra, err := prepareExtra(header, nil)
   432  	if err != nil {
   433  		return err
   434  	}
   435  	header.Extra = extra
   436  
   437  	// set header's timestamp
   438  	//header.Time = new(big.Int).Add(parent.Time, new(big.Int).SetUint64(sb.config.BlockPeriod))
   439  	//if header.Time.Int64() < time.Now().Unix() {
   440  	header.Time = big.NewInt(time.Now().Unix())
   441  	//}
   442  
   443  	// Add Main Chain Height if running on Child Chain
   444  	if sb.chainConfig.IntChainId != params.MainnetChainConfig.IntChainId && sb.chainConfig.IntChainId != params.TestnetChainConfig.IntChainId {
   445  		header.MainChainNumber = sb.core.cch.GetHeightFromMainChain()
   446  	}
   447  
   448  	return nil
   449  }
   450  
   451  // Finalize runs any post-transaction state modifications (e.g. block rewards)
   452  // and assembles the final block.
   453  //
   454  // Note, the block header and state database might be updated to reflect any
   455  // consensus rules that happen at finalization (e.g. block rewards).
   456  func (sb *backend) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction,
   457  	totalGasFee *big.Int, uncles []*types.Header, receipts []*types.Receipt, ops *types.PendingOps) (*types.Block, error) {
   458  
   459  	sb.logger.Debugf("IPBFT Finalize, receipts are: %v", receipts)
   460  
   461  	// Check if any Child Chain need to be launch and Update their account balance accordingly
   462  	if sb.chainConfig.IntChainId == params.MainnetChainConfig.IntChainId || sb.chainConfig.IntChainId == params.TestnetChainConfig.IntChainId {
   463  		// Check the Child Chain Start
   464  		readyId, updateBytes, removedId := sb.core.cch.ReadyForLaunchChildChain(header.Number, state)
   465  		if len(readyId) > 0 || updateBytes != nil || len(removedId) > 0 {
   466  			if ok := ops.Append(&types.LaunchChildChainsOp{
   467  				ChildChainIds:       readyId,
   468  				NewPendingIdx:       updateBytes,
   469  				DeleteChildChainIds: removedId,
   470  			}); !ok {
   471  				// This should not happened
   472  				sb.logger.Error("IPBFT Finalize, Fail to append LaunchChildChainsOp, only one LaunchChildChainsOp is allowed in each block")
   473  			}
   474  		}
   475  	}
   476  
   477  	curBlockNumber := header.Number.Uint64()
   478  	epoch := sb.GetEpoch().GetEpochByBlockNumber(curBlockNumber)
   479  
   480  	genesisHeader := chain.GetBlockByNumber(1)
   481  	if genesisHeader != nil {
   482  		genesisCoinbase := genesisHeader.Header().Coinbase
   483  		foundationAddress = state.GetAddress(genesisCoinbase)
   484  	}
   485  
   486  	// Calculate the rewards
   487  	accumulateRewards(sb.chainConfig, state, header, epoch, totalGasFee)
   488  
   489  	// update validator status include participating consensus block times and forbidden
   490  	//if header.Number.Uint64() > 1 {
   491  	//	//TODO slash in the future
   492  	//	prevHeader := chain.GetHeaderByNumber(header.Number.Uint64() - 1)
   493  	//	if prevHeader != nil {
   494  	//		extra, err := tdmTypes.ExtractTendermintExtra(prevHeader)
   495  	//		if err == nil {
   496  	//			epoch.UpdateForbiddenState(header, prevHeader, extra.SeenCommit, state)
   497  	//		}
   498  	//	}
   499  	//}
   500  
   501  	// Check the Epoch switch and update their account balance accordingly (Refund the Locked Balance)
   502  	if ok, newValidators, _ := epoch.ShouldEnterNewEpoch(header.Number.Uint64(), state); ok {
   503  		ops.Append(&tdmTypes.SwitchEpochOp{
   504  			ChainId:       sb.chainConfig.IntChainId,
   505  			NewValidators: newValidators,
   506  			//NewCandidates: newCandidates,
   507  		})
   508  
   509  	}
   510  
   511  	header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number))
   512  	header.UncleHash = types.TendermintNilUncleHash
   513  	// Assemble and return the final block for sealing
   514  	return types.NewBlock(header, txs, nil, receipts), nil
   515  }
   516  
   517  // Seal generates a new block for the given input block with the local miner's
   518  // seal place on top.
   519  func (sb *backend) Seal(chain consensus.ChainReader, block *types.Block, stop <-chan struct{}) (interface{}, error) {
   520  
   521  	sb.logger.Info("IPBFT backend seal")
   522  	// update the block header timestamp and signature and propose the block to core engine
   523  	header := block.Header()
   524  	number := header.Number.Uint64()
   525  	parent := chain.GetHeader(header.ParentHash, number-1)
   526  	if parent == nil {
   527  		return nil, consensus.ErrUnknownAncestor
   528  	}
   529  	block, err := sb.updateBlock(parent, block)
   530  	if err != nil {
   531  		return nil, err
   532  	}
   533  	// wait for the timestamp of header, use this to adjust the block period
   534  	delay := time.Unix(block.Header().Time.Int64(), 0).Sub(now())
   535  	select {
   536  	case <-time.After(delay):
   537  	case <-stop:
   538  		return nil, nil
   539  	}
   540  	// get the proposed block hash and clear it if the seal() is completed.
   541  	sb.sealMu.Lock()
   542  	sb.proposedBlockHash = block.Hash()
   543  	clear := func() {
   544  		sb.proposedBlockHash = common.Hash{}
   545  		sb.sealMu.Unlock()
   546  	}
   547  	defer clear()
   548  
   549  	// post block into IPBFT engine
   550  	sb.logger.Infof("IPBFT Seal, before fire event with block height: %d", block.NumberU64())
   551  	go tdmTypes.FireEventRequest(sb.core.EventSwitch(), tdmTypes.EventDataRequest{Proposal: block})
   552  	//go sb.EventMux().Post(tdmTypes.RequestEvent{
   553  	//	Proposal: block,
   554  	//})
   555  
   556  	for {
   557  		select {
   558  		case result, ok := <-sb.commitCh:
   559  
   560  			if ok {
   561  				sb.logger.Debugf("IPBFT Seal, got result with block.Hash: %x, result.Hash: %x", block.Hash(), result.Hash())
   562  				// if the block hash and the hash from channel are the same,
   563  				// return the result. Otherwise, keep waiting the next hash.
   564  				if block.Hash() == result.Hash() {
   565  					return result, nil
   566  				}
   567  				sb.logger.Debug("IPBFT Seal, hash are different")
   568  			} else {
   569  				sb.logger.Debug("IPBFT Seal, has been restart, just return")
   570  				return nil, nil
   571  			}
   572  
   573  		case iresult, ok := <-sb.vcommitCh:
   574  
   575  			if ok {
   576  				sb.logger.Debugf("IPBFT Seal, v got result with block.Hash: %x, result.Hash: %x", block.Hash(), iresult.Block.Hash())
   577  				if block.Hash() != iresult.Block.Hash() {
   578  					return iresult, nil
   579  				}
   580  				sb.logger.Debug("IPBFT Seal, v hash are the same")
   581  			} else {
   582  				sb.logger.Debug("IPBFT Seal, v has been restart, just return")
   583  				return nil, nil
   584  			}
   585  
   586  		case <-stop:
   587  			sb.logger.Debug("IPBFT Seal, stop")
   588  			return nil, nil
   589  		}
   590  	}
   591  
   592  	return nil, nil
   593  }
   594  
   595  // CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty
   596  // that a new block should have based on the previous blocks in the chain and the
   597  // current signer.
   598  func (sb *backend) CalcDifficulty(chain consensus.ChainReader, time uint64, parent *types.Header) *big.Int {
   599  
   600  	return types.TendermintDefaultDifficulty
   601  }
   602  
   603  // Commit implements istanbul.Backend.Commit
   604  func (sb *backend) Commit(proposal *tdmTypes.TdmBlock, seals [][]byte, isProposer func() bool) error {
   605  	// Check if the proposal is a valid block
   606  	block := proposal.Block
   607  
   608  	h := block.Header()
   609  	// Append seals into extra-data
   610  	err := writeCommittedSeals(h, proposal.TdmExtra)
   611  	if err != nil {
   612  		return err
   613  	}
   614  	// update block's header
   615  	block = block.WithSeal(h)
   616  
   617  	sb.logger.Debugf("IPBFT Commit, hash: %x, number: %v", block.Hash(), block.Number().Int64())
   618  	sb.logger.Debugf("IPBFT Commit, block: %s", block.String())
   619  
   620  	// - if the proposed and committed blocks are the same, send the proposed hash
   621  	//   to commit channel, which is being watched inside the engine.Seal() function.
   622  	// - otherwise, we try to insert the block.
   623  	// -- if success, the ChainHeadEvent event will be broadcasted, try to build
   624  	//    the next block and the previous Seal() will be stopped.
   625  	// -- otherwise, a error will be returned and a round change event will be fired.
   626  	if isProposer() && (sb.proposedBlockHash == block.Hash()) { // for proposer
   627  		// feed block hash to Seal() and wait the Seal() result
   628  		sb.logger.Debugf("IPBFT Commit, proposer | feed to Seal: %x", block.Hash())
   629  		sb.commitCh <- block
   630  		return nil
   631  	} else { // for other validators
   632  		if proposal.IntermediateResult != nil {
   633  			sb.logger.Debugf("IPBFT Commit, validator | feed to Seal: %x", block.Hash())
   634  			proposal.IntermediateResult.Block = block
   635  			sb.vcommitCh <- proposal.IntermediateResult
   636  		} else {
   637  			sb.logger.Debugf("IPBFT Commit, validator | fetcher enqueue: %x", block.Hash())
   638  			if sb.broadcaster != nil {
   639  				sb.broadcaster.Enqueue(fetcherID, block)
   640  			}
   641  		}
   642  		return nil
   643  	}
   644  }
   645  
   646  // Stop implements consensus.Istanbul.Stop
   647  func (sb *backend) ChainReader() consensus.ChainReader {
   648  
   649  	return sb.chain
   650  }
   651  
   652  func (sb *backend) ShouldStart() bool {
   653  	return sb.shouldStart
   654  }
   655  
   656  func (sb *backend) IsStarted() bool {
   657  	sb.coreMu.RLock()
   658  	start := sb.coreStarted
   659  	sb.coreMu.RUnlock()
   660  
   661  	return start
   662  }
   663  
   664  func (sb *backend) ForceStart() {
   665  	sb.shouldStart = true
   666  }
   667  
   668  // GetEpoch Get Epoch from Tendermint Engine
   669  func (sb *backend) GetEpoch() *epoch.Epoch {
   670  	return sb.core.consensusState.Epoch
   671  }
   672  
   673  // SetEpoch Set Epoch to Tendermint Engine
   674  func (sb *backend) SetEpoch(ep *epoch.Epoch) {
   675  	sb.core.consensusState.Epoch = ep
   676  }
   677  
   678  // Return the private validator address of consensus
   679  func (sb *backend) PrivateValidator() common.Address {
   680  	if sb.core.privValidator != nil {
   681  		return sb.core.privValidator.Address
   682  	}
   683  	return common.Address{}
   684  }
   685  
   686  // update timestamp and signature of the block based on its number of transactions
   687  func (sb *backend) updateBlock(parent *types.Header, block *types.Block) (*types.Block, error) {
   688  
   689  	sb.logger.Debug("IPBFT backend update block")
   690  
   691  	header := block.Header()
   692  	/*
   693  		//sign the hash
   694  		seal, err := sb.Sign(sigHash(header).Bytes())
   695  		if err != nil {
   696  		    return nil, err
   697  		}
   698  	*/
   699  	//err := writeSeal(header, seal)
   700  	err := writeSeal(header, []byte{})
   701  	if err != nil {
   702  		return nil, err
   703  	}
   704  
   705  	return block.WithSeal(header), nil
   706  }
   707  
   708  // prepareExtra returns a extra-data of the given header and validators
   709  func prepareExtra(header *types.Header, vals []common.Address) ([]byte, error) {
   710  
   711  	//logger.Info("IPBFT (backend) prepare extra ")
   712  
   713  	header.Extra = types.MagicExtra
   714  	return nil, nil
   715  }
   716  
   717  // writeSeal writes the extra-data field of the given header with the given seals.
   718  // suggest to rename to writeSeal.
   719  func writeSeal(h *types.Header, seal []byte) error {
   720  
   721  	//logger.Info("IPBFT backend write seal")
   722  	if h.Extra == nil {
   723  		payload := types.MagicExtra
   724  		h.Extra = payload
   725  	}
   726  	return nil
   727  }
   728  
   729  // writeCommittedSeals writes the extra-data field of a block header with given committed seals.
   730  func writeCommittedSeals(h *types.Header, tdmExtra *tdmTypes.TendermintExtra) error {
   731  
   732  	//logger.Info("IPBFT backend write committed seals")
   733  	h.Extra = wire.BinaryBytes(*tdmExtra)
   734  	return nil
   735  }
   736  
   737  // AccumulateRewards credits the coinbase of the given block with the mining reward.
   738  // Main Chain:
   739  // The total reward consists of the static block reward of the Epoch and total tx gas fee.
   740  // Child Chain:
   741  // The total reward consists of the static block reward of Owner setup and total tx gas fee.
   742  //
   743  // If the coinbase is Candidate, divide the rewards by weight
   744  func accumulateRewards(config *params.ChainConfig, state *state.StateDB, header *types.Header, ep *epoch.Epoch, totalGasFee *big.Int) {
   745  	halfGasFee := big.NewInt(0).Div(totalGasFee, big.NewInt(2))
   746  	state.AddBalance(feeAddress, halfGasFee)
   747  
   748  	var coinbaseReward *big.Int
   749  	if config.IntChainId == params.MainnetChainConfig.IntChainId || config.IntChainId == params.TestnetChainConfig.IntChainId {
   750  		rewardPerBlock := ep.RewardPerBlock
   751  		if rewardPerBlock != nil && rewardPerBlock.Sign() == 1 {
   752  			zeroAddress := common.Address{}
   753  			if foundationAddress == zeroAddress {
   754  				coinbaseReward = big.NewInt(0)
   755  				coinbaseReward.Add(rewardPerBlock, halfGasFee)
   756  			} else {
   757  				coinbaseReward = new(big.Int).Mul(rewardPerBlock, big.NewInt(8))
   758  				coinbaseReward.Quo(coinbaseReward, big.NewInt(10))
   759  				foundationReward := new(big.Int).Sub(rewardPerBlock, coinbaseReward)
   760  				state.AddBalance(foundationAddress, foundationReward)
   761  				coinbaseReward.Add(coinbaseReward, halfGasFee)
   762  			}
   763  		} else {
   764  			coinbaseReward = halfGasFee
   765  		}
   766  	} else {
   767  		rewardPerBlock := state.GetChildChainRewardPerBlock()
   768  		if rewardPerBlock != nil && rewardPerBlock.Sign() == 1 {
   769  			childChainRewardBalance := state.GetBalance(childChainRewardAddress)
   770  			if childChainRewardBalance.Cmp(rewardPerBlock) == -1 {
   771  				rewardPerBlock = childChainRewardBalance
   772  			}
   773  			// sub balance from childChainRewardAddress, reward per blocks
   774  			state.SubBalance(childChainRewardAddress, rewardPerBlock)
   775  
   776  			coinbaseReward = new(big.Int).Add(rewardPerBlock, halfGasFee)
   777  		} else {
   778  			coinbaseReward = halfGasFee
   779  		}
   780  	}
   781  
   782  	// Coinbase Reward   = Self Reward + Delegate Reward (if Deposit Proxied Balance > 0)
   783  	//
   784  	// IF commission > 0
   785  	// Self Reward       = Self Reward + Commission Reward
   786  	// Commission Reward = Delegate Reward * Commission / 100
   787  
   788  	// Deposit Part
   789  	selfDeposit := state.GetDepositBalance(header.Coinbase)
   790  	totalProxiedDeposit := state.GetTotalDepositProxiedBalance(header.Coinbase)
   791  	totalDeposit := new(big.Int).Add(selfDeposit, totalProxiedDeposit)
   792  
   793  	var selfReward, delegateReward *big.Int
   794  	if totalProxiedDeposit.Sign() == 0 {
   795  		selfReward = coinbaseReward
   796  	} else {
   797  		selfReward = new(big.Int)
   798  		// selfPercent = selfDeposit / totalDeposit
   799  		selfPercent := new(big.Float).Quo(new(big.Float).SetInt(selfDeposit), new(big.Float).SetInt(totalDeposit))
   800  
   801  		// selfReward = coinbaseReward * selfPercent
   802  		new(big.Float).Mul(new(big.Float).SetInt(coinbaseReward), selfPercent).Int(selfReward)
   803  
   804  		// delegateReward = coinbaseReward - selfReward
   805  		delegateReward = new(big.Int).Sub(coinbaseReward, selfReward)
   806  		commission := state.GetCommission(header.Coinbase)
   807  		if commission > 0 {
   808  			// commissionReward = delegateReward * commission / 100
   809  			commissionReward := new(big.Int).Mul(delegateReward, big.NewInt(int64(commission)))
   810  			commissionReward.Quo(commissionReward, big.NewInt(100))
   811  
   812  			// Add the commission to self reward  selfReward = selfReward + commissionReward
   813  			selfReward.Add(selfReward, commissionReward)
   814  
   815  			// Sub the commission from delegate reward  delegateReward = delegateReward - commissionReward
   816  			delegateReward.Sub(delegateReward, commissionReward)
   817  		}
   818  	}
   819  
   820  	// Move the self reward to Reward Trie
   821  	//divideRewardByEpoch(state, header.Coinbase, ep.Number, selfReward)
   822  	state.AddRewardBalanceByDelegateAddress(header.Coinbase, header.Coinbase, selfReward)
   823  	//state.MarkAddressReward(header.Coinbase)
   824  
   825  	// Calculate the Delegate Reward
   826  	if delegateReward != nil && delegateReward.Sign() > 0 {
   827  		totalIndividualReward := big.NewInt(0)
   828  		// Split the reward based on Weight stack
   829  		state.ForEachProxied(header.Coinbase, func(key common.Address, proxiedBalance, depositProxiedBalance, pendingRefundBalance *big.Int) bool {
   830  			if depositProxiedBalance.Sign() == 1 {
   831  				// deposit * delegateReward / total deposit
   832  				individualReward := new(big.Int).Quo(new(big.Int).Mul(depositProxiedBalance, delegateReward), totalProxiedDeposit)
   833  				//divideRewardByEpoch(state, key, ep.Number, individualReward)
   834  				state.AddRewardBalanceByDelegateAddress(key, header.Coinbase, individualReward)
   835  				//state.MarkAddressReward(key)
   836  				totalIndividualReward.Add(totalIndividualReward, individualReward)
   837  			}
   838  			return true
   839  		})
   840  		// Recheck the Total Individual Reward, Float the difference
   841  		cmp := delegateReward.Cmp(totalIndividualReward)
   842  		if cmp == 1 {
   843  			// if delegate reward > actual given reward, give remaining reward to Candidate
   844  			diff := new(big.Int).Sub(delegateReward, totalIndividualReward)
   845  			//state.AddRewardBalanceByEpochNumber(header.Coinbase, ep.Number, diff)
   846  			state.AddRewardBalanceByDelegateAddress(header.Coinbase, header.Coinbase, diff)
   847  		} else if cmp == -1 {
   848  			// if delegate reward < actual given reward, subtract the diff from Candidate
   849  			diff := new(big.Int).Sub(totalIndividualReward, delegateReward)
   850  			//state.SubRewardBalanceByEpochNumber(header.Coinbase, ep.Number, diff)
   851  			state.SubRewardBalanceByDelegateAddress(header.Coinbase, header.Coinbase, diff)
   852  		}
   853  	}
   854  
   855  	//err := state.MarkProposedInEpoch(header.Coinbase, ep.Number)
   856  	//if err != nil {
   857  	//	fmt.Printf("Mark validator proposed failed, error: %v\n", err)
   858  	//}
   859  }
   860  
   861  //func divideRewardByEpoch(state *state.StateDB, addr common.Address, epochNumber uint64, reward *big.Int) {
   862  //	epochReward := new(big.Int).Quo(reward, big.NewInt(12))
   863  //	lastEpochReward := new(big.Int).Set(reward)
   864  //	for i := epochNumber; i < epochNumber+12; i++ {
   865  //		if i == epochNumber+11 {
   866  //			state.AddRewardBalanceByEpochNumber(addr, i, lastEpochReward)
   867  //		} else {
   868  //			state.AddRewardBalanceByEpochNumber(addr, i, epochReward)
   869  //			lastEpochReward.Sub(lastEpochReward, epochReward)
   870  //		}
   871  //	}
   872  //	state.MarkAddressReward(addr)
   873  //}