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 }