github.com/Gessiux/neatchain@v1.3.1/chain/consensus/neatcon/state/execution.go (about)

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