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

     1  package state
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"github.com/intfoundation/intchain/consensus"
     7  	ep "github.com/intfoundation/intchain/consensus/ipbft/epoch"
     8  	"github.com/intfoundation/intchain/consensus/ipbft/types"
     9  	"github.com/intfoundation/intchain/core"
    10  	ethTypes "github.com/intfoundation/intchain/core/types"
    11  )
    12  
    13  //--------------------------------------------------
    14  
    15  // return a bit array of validators that signed the last commit
    16  // NOTE: assumes commits have already been authenticated
    17  /*
    18  func commitBitArrayFromBlock(block *types.TdmBlock) *BitArray {
    19  
    20  	signed := NewBitArray(uint64(len(block.TdmExtra.SeenCommit.Precommits)))
    21  	for i, precommit := range block.TdmExtra.SeenCommit.Precommits {
    22  		if precommit != nil {
    23  			signed.SetIndex(uint64(i), true) // val_.LastCommitHeight = block.Height - 1
    24  		}
    25  	}
    26  	return signed
    27  }*/
    28  
    29  //-----------------------------------------------------
    30  // Validate block
    31  
    32  func (s *State) ValidateBlock(block *types.TdmBlock) error {
    33  	return s.validateBlock(block)
    34  }
    35  
    36  //Very current block
    37  func (s *State) validateBlock(block *types.TdmBlock) error {
    38  	// Basic block validation.
    39  	err := block.ValidateBasic(s.TdmExtra)
    40  	if err != nil {
    41  		return err
    42  	}
    43  
    44  	// Validate block SeenCommit.
    45  	epoch := s.Epoch.GetEpochByBlockNumber(block.TdmExtra.Height)
    46  	if epoch == nil || epoch.Validators == nil {
    47  		return errors.New("no epoch for current block height")
    48  	}
    49  
    50  	valSet := epoch.Validators
    51  	err = valSet.VerifyCommit(block.TdmExtra.ChainID, block.TdmExtra.Height,
    52  		block.TdmExtra.SeenCommit)
    53  	if err != nil {
    54  		return err
    55  	}
    56  
    57  	return nil
    58  }
    59  
    60  //-----------------------------------------------------------------------------
    61  
    62  func init() {
    63  	core.RegisterInsertBlockCb("UpdateLocalEpoch", updateLocalEpoch)
    64  	core.RegisterInsertBlockCb("AutoStartMining", autoStartMining)
    65  }
    66  
    67  func updateLocalEpoch(bc *core.BlockChain, block *ethTypes.Block) {
    68  	if block.NumberU64() == 0 {
    69  		return
    70  	}
    71  
    72  	tdmExtra, _ := types.ExtractTendermintExtra(block.Header())
    73  	//here handles the proposed next epoch
    74  	epochInBlock := ep.FromBytes(tdmExtra.EpochBytes)
    75  
    76  	eng := bc.Engine().(consensus.IPBFT)
    77  	currentEpoch := eng.GetEpoch()
    78  
    79  	if epochInBlock != nil {
    80  		if epochInBlock.Number == currentEpoch.Number+1 {
    81  			// Save the next epoch
    82  			if block.NumberU64() == currentEpoch.StartBlock+2 {
    83  				// Propose next epoch
    84  				//epochInBlock.SetEpochValidatorVoteSet(ep.NewEpochValidatorVoteSet())
    85  				epochInBlock.Status = ep.EPOCH_VOTED_NOT_SAVED
    86  				epochInBlock.SetRewardScheme(currentEpoch.GetRewardScheme())
    87  				currentEpoch.SetNextEpoch(epochInBlock)
    88  			} else if block.NumberU64() == currentEpoch.EndBlock-1 {
    89  				// Finalize next epoch
    90  				// Validator set in next epoch will not finalize and send to main chain
    91  				nextEp := currentEpoch.GetNextEpoch()
    92  				nextEp.Validators = epochInBlock.Validators
    93  				//nextEp.Candidates = epochInBlock.Candidates // add at 2021.06.28 by like
    94  				nextEp.Status = ep.EPOCH_VOTED_NOT_SAVED
    95  			}
    96  			currentEpoch.Save()
    97  		} else if epochInBlock.Number == currentEpoch.Number {
    98  			// Update the current epoch Start Time from proposer
    99  			currentEpoch.StartTime = epochInBlock.StartTime
   100  			currentEpoch.Save()
   101  
   102  			// Update the previous epoch End Time
   103  			if currentEpoch.Number > 0 {
   104  				ep.UpdateEpochEndTime(currentEpoch.GetDB(), currentEpoch.Number-1, epochInBlock.StartTime)
   105  			}
   106  		}
   107  	}
   108  }
   109  
   110  func autoStartMining(bc *core.BlockChain, block *ethTypes.Block) {
   111  	eng := bc.Engine().(consensus.IPBFT)
   112  	currentEpoch := eng.GetEpoch()
   113  
   114  	// At one block before epoch end block, we should able to calculate the new validator
   115  	if block.NumberU64() == currentEpoch.EndBlock-1 {
   116  		fmt.Printf("auto start mining first %v\n", block.Number())
   117  		// Re-Calculate the next epoch validators
   118  		nextEp := currentEpoch.GetNextEpoch()
   119  		state, _ := bc.State()
   120  		nextValidators := currentEpoch.Validators.Copy()
   121  		dryrunErr := ep.DryRunUpdateEpochValidatorSet(state, nextValidators, nextEp.GetEpochValidatorVoteSet())
   122  		if dryrunErr != nil {
   123  			panic("can not update the validator set base on the vote, error: " + dryrunErr.Error())
   124  		}
   125  		nextEp.Validators = nextValidators
   126  
   127  		if nextValidators.HasAddress(eng.PrivateValidator().Bytes()) && !eng.IsStarted() {
   128  			fmt.Printf("auto start mining first, post start mining event")
   129  			bc.PostChainEvents([]interface{}{core.StartMiningEvent{}}, nil)
   130  		}
   131  	}
   132  }