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 }