github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/consense/dpoa/procmode.go (about)

     1  package dpoa
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"time"
     7  
     8  	//"github.com/sixexorg/magnetic-ring/common"
     9  	"github.com/sixexorg/magnetic-ring/core/mainchain/types"
    10  	"github.com/sixexorg/magnetic-ring/log"
    11  
    12  	//"github.com/sixexorg/magnetic-ring/core/ledger"
    13  	//"github.com/sixexorg/magnetic-ring/core/signature"
    14  	//"github.com/ontio/ontology-crypto/keypair"
    15  	"github.com/sixexorg/magnetic-ring/consense/dpoa/comm"
    16  	//"github.com/sixexorg/magnetic-ring/consensus/vbft/config"
    17  	"sync"
    18  
    19  	"github.com/sixexorg/magnetic-ring/account"
    20  )
    21  
    22  type ProcMode struct {
    23  	sync.RWMutex
    24  	dpoaMgr     *DpoaMgr
    25  	msgpool     *MsgPool
    26  	cfg         *Config
    27  	notifyBlock *Feed
    28  	notifyState *Feed
    29  	state       ServerState
    30  	prestate    ServerState
    31  	trans       *TransAction
    32  	excuteSet   map[comm.ExcuteType]*SyncExec
    33  	quitC       chan struct{}
    34  	stopNewHtCh chan struct{}
    35  }
    36  
    37  func NewprocMode(dpoaMgr *DpoaMgr, msgpool *MsgPool, trans *TransAction, notifyBlock, notifyState *Feed, cfg *Config) *ProcMode {
    38  	return &ProcMode{dpoaMgr: dpoaMgr, msgpool: msgpool, notifyBlock: notifyBlock, notifyState: notifyState, cfg: cfg, trans: trans,
    39  		stopNewHtCh: make(chan struct{}), excuteSet: make(map[comm.ExcuteType]*SyncExec, comm.MaxExcuteType)}
    40  }
    41  
    42  func (srv *ProcMode) Start() {
    43  	subCh1 := make(chan stateChange, 100)
    44  	srv.notifyState.Subscribe(subCh1)
    45  
    46  	go func() {
    47  		//fmt.Println("***************ProcMode Start", srv.prestate, srv.state)
    48  		for {
    49  			select {
    50  			case st := <-subCh1:
    51  				fmt.Println("==========---------->>>>>>>>>state", srv.prestate, srv.state, st.currentState)
    52  				srv.Lock()
    53  				srv.prestate = srv.state
    54  				srv.state = st.currentState
    55  				srv.Unlock()
    56  				if st.currentState >= SyncReady {
    57  					if srv.prestate < SyncReady {
    58  						srv.Excute(comm.StartNewHeight, srv.NewEpoch)
    59  					}
    60  				}
    61  			case <-srv.quitC:
    62  				return
    63  			}
    64  		}
    65  	}()
    66  
    67  	for e := comm.MinExcuteType + 1; e < comm.MaxExcuteType; e++ {
    68  		srv.excuteSet[e] = newExcutePool(5)
    69  	}
    70  
    71  	if !srv.dpoaMgr.store.isEarth() {
    72  		go func() {
    73  			for {
    74  				select {
    75  				case m := <-srv.dpoaMgr.RecvCh():
    76  					//log.Info("func dpoa procmode start 01", "recvch type", reflect.TypeOf(m))
    77  					switch v := m.(type) {
    78  					case *SendMsgEvent:
    79  						//log.Info("func dpoa procmode start 02","msg type", v.Msg.Type())
    80  
    81  						srv.trans.sendMsg(v)
    82  					case *comm.Block:
    83  						log.Info("func dpoa procmode start 03", "blockHeight", v.Block.Header.Height, "txlen", v.Block.Transactions.Len())
    84  						srv.dpoaMgr.store.sealBlock(v)
    85  					default:
    86  						//fmt.Println("b1.(type):", "other", v)
    87  					}
    88  				case <-srv.quitC:
    89  					return
    90  				}
    91  			}
    92  		}()
    93  	}
    94  }
    95  
    96  func (srv *ProcMode) currentState() ServerState {
    97  	srv.RLock()
    98  	defer srv.RUnlock()
    99  	return srv.state
   100  }
   101  
   102  func (srv *ProcMode) Process() {
   103  	log.Info("func dpoa procmode Process", "isearth", srv.dpoaMgr.store.isEarth())
   104  	srv.dpoaMgr.Run()
   105  	if srv.dpoaMgr.store.isEarth() {
   106  		srv.Excute(comm.EarthProcess, srv.earthProcess)
   107  	}
   108  }
   109  
   110  func (srv *ProcMode) earthProcess() {
   111  	var exitDesc string
   112  	//srv.stopNewHtCh = make(chan struct{})
   113  	subCh := make(chan types.Block, 100)
   114  	subIns := srv.notifyBlock.Subscribe(subCh)
   115  	log.Info("Server earthProcess start")
   116  	defer func() {
   117  		log.Info("Server earthProcess exit due to", "desc", exitDesc)
   118  		subIns.Unsubscribe()
   119  	}()
   120  
   121  	for {
   122  		//log.Info("-----------------&&&&&&&&&&&&&&&&&&&&&&", "currentState", srv.currentState(), "time", time.Now().String())
   123  		time.Sleep(time.Second)
   124  		stars := srv.dpoaMgr.store.GetCurStars()
   125  		ebgHeight := srv.dpoaMgr.store.EpochBegin()
   126  		blkData, _ := srv.dpoaMgr.store.getSealedBlock(ebgHeight)
   127  		partiNums, epochView := CalcStellar(float64(len(stars)))
   128  		endtime := time.Unix(int64(blkData.Block.Header.Timestamp), 0).Add(time.Duration(srv.cfg.earthCfg.duration) * time.Second).Add(time.Duration(epochView*2*srv.cfg.earthCfg.duration) * time.Second)
   129  		vrfValue := getParticipantSelectionSeed(blkData)
   130  		if vrfValue.IsNil() {
   131  			log.Error("ProcMode earthProcess", "err", fmt.Sprintf("StateMgr earth vrf is nil"))
   132  			return
   133  		}
   134  
   135  		if srv.currentState() <= WaitNetworkReady {
   136  			continue
   137  		}
   138  
   139  		delay := endtime.Sub(time.Now().Add(time.Duration(srv.cfg.earthCfg.duration) * time.Second))
   140  		log.Info("Server earthProcess wait duration",
   141  			"delay", delay, "ebgHeight", ebgHeight, "partiNums", partiNums, "epochView", epochView, "endtime", endtime, "time", time.Unix(int64(blkData.Block.Header.Timestamp), 0).String(), "view", blkData.GetViews())
   142  		fmt.Println("Server earthProcess wait duration",
   143  			"delay", delay, "ebgHeight", ebgHeight, "partiNums", partiNums, "epochView", epochView, "endtime", endtime, "time", time.Unix(int64(blkData.Block.Header.Timestamp), 0).String(), "view", blkData.GetViews())
   144  		select {
   145  		case <-subIns.Err():
   146  			break
   147  		case <-time.After(delay):
   148  			log.Info("Server earthProcess start search earthsigs", "ebgHeight", ebgHeight, "view", blkData.GetViews())
   149  			fmt.Println("Server earthProcess start search earthsigs", "time", time.Now().String(), "ebgHeight", ebgHeight, "view", blkData.GetViews())
   150  			select {
   151  			case <-time.After(time.Second * time.Duration(srv.cfg.earthCfg.duration)):
   152  				log.Info("---.Server earthProcess construct block due to epoch timeout", "ebgHeight", ebgHeight, "getLatestBlockNumber", srv.dpoaMgr.store.getLatestBlockNumber()+1)
   153  				fmt.Println("---.Server earthProcess construct block due to epoch timeout", "time", time.Now().String(), "ebgHeight", ebgHeight, "getLatestBlockNumber", srv.dpoaMgr.store.getLatestBlockNumber()+1)
   154  				failerSigs := make([][]byte, 0)
   155  				for publicKey, sig := range srv.msgpool.GetEarthMsgs(blkData.Block.Hash()) {
   156  					var d []byte
   157  					idx, _ := GetIndex(srv.dpoaMgr.store.GetCurStars(), publicKey)
   158  					//fmt.Println("----------fairSigs", publicKey, idx, blkData.GetBlockNum(), blkData.Block.Hash())
   159  					d = append(d, int2Byte(uint16(idx))...)
   160  					d = append(d, sig...)
   161  					failerSigs = append(failerSigs, d)
   162  				}
   163  				//fmt.Println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!", ebgHeight, time.Now().String(), srv.dpoaMgr.store.getLatestBlockNumber()+1)
   164  				blk, err := srv.dpoaMgr.constructEmptyBlock(srv.dpoaMgr.store.getLatestBlockNumber()+1, &types.SigData{TimeoutSigs: make([][]byte, 0), FailerSigs: failerSigs, ProcSigs: make([][]byte, 0)})
   165  				if err != nil {
   166  					log.Error("Server earthProcess constructBlockMsg", "GetBlockNum", blk.GetBlockNum(), "EmptyBlockNum", "err", err)
   167  					continue
   168  				}
   169  				fmt.Println("🌏  Empty block product,the height is ", blk.Block.Header.Height)
   170  				if err := srv.dpoaMgr.store.sealBlock(blk); err != nil {
   171  					log.Error("Server earthProcess sealBlock", "GetBlockNum", blk.GetBlockNum(), "err", err)
   172  				}
   173  				<-subCh
   174  			}
   175  		case <-srv.quitC:
   176  			exitDesc = "server quit"
   177  			return
   178  		}
   179  	}
   180  }
   181  
   182  func (self *DpoaMgr) constructEmptyBlock(blkNum uint64, sigData *types.SigData) (*comm.Block, error) {
   183  	prevBlk, _ := self.store.getSealedBlock(blkNum - 1)
   184  	//fmt.Println("$$$$$$$$$$$$$$$$$$$$$$$$$$$4", blkNum, prevBlk.Block.Header.Hash().String())
   185  	if prevBlk == nil {
   186  		return nil, fmt.Errorf("failed to get prevBlock (%d)", blkNum-1)
   187  	}
   188  	blocktimestamp := uint64(time.Now().Unix())
   189  	if prevBlk.Block.Header.Timestamp >= blocktimestamp {
   190  		blocktimestamp = prevBlk.Block.Header.Timestamp + 1
   191  	}
   192  	vrfValue, vrfProof, err := computeVrf(self.cfg.account.(*account.NormalAccountImpl).PrivKey, blkNum, prevBlk.GetVrfValue())
   193  	if err != nil {
   194  		return nil, fmt.Errorf("failed to get vrf and proof: %s", err)
   195  	}
   196  
   197  	lastConfigBlkNum := prevBlk.Info.LastConfigBlockNum
   198  	if prevBlk.Info.NewChainConfig != nil {
   199  		lastConfigBlkNum = prevBlk.GetBlockNum()
   200  	}
   201  
   202  	vbftBlkInfo := &comm.VbftBlockInfo{
   203  		View:               self.partiCfg.View,
   204  		Miner:              self.cfg.accountStr,
   205  		VrfValue:           vrfValue,
   206  		VrfProof:           vrfProof,
   207  		LastConfigBlockNum: lastConfigBlkNum,
   208  	}
   209  	consensusPayload, err := json.Marshal(vbftBlkInfo)
   210  	if err != nil {
   211  		return nil, err
   212  	}
   213  
   214  	//fmt.Println("@@@@@@@@@@###########$$$$$$$$$$$$$", string(consensusPayload))
   215  	blkHeader := &types.Header{
   216  		PrevBlockHash: prevBlk.Block.Hash(),
   217  		//TxRoot: txRoot,
   218  		//BlockRoot:        blockRoot,
   219  		Timestamp: blocktimestamp,
   220  		Height:    blkNum,
   221  		//ConsensusData:    common.GetNonce(),
   222  		ConsensusPayload: consensusPayload,
   223  	}
   224  	blk := &types.Block{
   225  		Header: blkHeader,
   226  		Sigs:   sigData,
   227  	}
   228  
   229  	return &comm.Block{
   230  		Block: blk,
   231  		Info:  vbftBlkInfo,
   232  	}, nil
   233  }
   234  
   235  func (srv *ProcMode) epochPorcess(endtime time.Time, epochViews int, lastBlk, curEpoch *comm.Block) {
   236  	var (
   237  		t0, t1, t2   time.Time
   238  		timeOutCount int
   239  		descStr      string
   240  		blkNum       uint64 = lastBlk.GetBlockNum() + 1
   241  		preNum       uint64 = lastBlk.GetBlockNum()
   242  		//lastBlkTime         = time.Unix(int64(lastBlk.Block.Header.Timestamp), 0)
   243  		curEpochTime = time.Unix(int64(curEpoch.Block.Header.Timestamp), 0)
   244  	)
   245  	subCh := make(chan types.Block, 100)
   246  	subIns := srv.notifyBlock.Subscribe(subCh)
   247  
   248  	defer func() {
   249  		log.Debug("--Server epochPorcess exit blknum, cause", "blkNum", blkNum, "cause", descStr)
   250  		subIns.Unsubscribe()
   251  		notice := &comm.ConsenseNotify{BlkNum: srv.dpoaMgr.partiCfg.BlkNum, ProcNodes: srv.dpoaMgr.partiCfg.ProcNodes, Istart: false}
   252  		srv.dpoaMgr.p2pPid.Tell(notice)
   253  	}()
   254  
   255  	log.Info("Server epochPorcess start curblknum, epoch begtime  endtime , epochViews ", "blkNum", blkNum, "begtime", curEpochTime.String(), "endtime", endtime.String(), "epochViews", epochViews)
   256  
   257  	for {
   258  		if srv.trans.stateMgr.getState() != SyncReady {
   259  			descStr = "state is not ready"
   260  			log.Error("Server epochPorcess state is not SyncReady or Synced", "err is %v", srv.trans.stateMgr.getState())
   261  			break
   262  		}
   263  
   264  		if time.Now().After(endtime) {
   265  			descStr = fmt.Sprintf("out epoch endtime %v", endtime.String())
   266  			break
   267  		}
   268  
   269  		if blkNum != srv.dpoaMgr.store.getLatestBlockNumber()+1 {
   270  			lastBlk, _ = srv.dpoaMgr.store.getSealedBlock(srv.dpoaMgr.store.db.GetCurrentBlockHeight())
   271  			//lastBlkTime = time.Unix(int64(lastBlk.Block.Header.Timestamp), 0)
   272  			/*fmt.Println("****************..................update waitEvent", blkNum, lastBlkTime, time.Now().Sub(lastBlkTime).Seconds(),
   273  			srv.dpoaMgr.store.getLatestBlockNumber()+1, srv.dpoaMgr.store.getLatestBlockNumber(), srv.dpoaMgr.store.db.GetCurrentBlockHeight())*/
   274  			blkNum = srv.dpoaMgr.store.getLatestBlockNumber() + 1
   275  		}
   276  
   277  		timeOutCount = srv.msgpool.TimeoutCount(blkNum)
   278  		if blkNum-1 == curEpoch.GetBlockNum() {
   279  			if timeOutCount == epochViews {
   280  				descStr = fmt.Sprintf("generate block compeletes, blknum %v", blkNum)
   281  				break
   282  			}
   283  			t0 = curEpochTime.Add(time.Duration(comm.V_One*srv.cfg.starsCfg.duration) * time.Second).Add(time.Duration(comm.V_Two*srv.cfg.starsCfg.duration*timeOutCount) * time.Second)
   284  			t1 = curEpochTime.Add(time.Duration(comm.V_Two*srv.cfg.starsCfg.duration) * time.Second).Add(time.Duration(comm.V_Two*srv.cfg.starsCfg.duration*timeOutCount) * time.Second)
   285  			t2 = curEpochTime.Add(time.Duration(comm.V_Three*srv.cfg.starsCfg.duration) * time.Second).Add(time.Duration(comm.V_Two*srv.cfg.starsCfg.duration*timeOutCount) * time.Second)
   286  		} else {
   287  			t0 = curEpochTime.Add(time.Duration(comm.V_One*srv.cfg.starsCfg.duration) * time.Second).Add(time.Duration(comm.V_Two*srv.cfg.starsCfg.duration*int(lastBlk.GetViews()+uint32(timeOutCount)+1)) * time.Second)
   288  			t1 = curEpochTime.Add(time.Duration(comm.V_Two*srv.cfg.starsCfg.duration) * time.Second).Add(time.Duration(comm.V_Two*srv.cfg.starsCfg.duration*int(lastBlk.GetViews()+uint32(timeOutCount)+1)) * time.Second)
   289  			t2 = curEpochTime.Add(time.Duration(comm.V_Three*srv.cfg.starsCfg.duration) * time.Second).Add(time.Duration(comm.V_Two*srv.cfg.starsCfg.duration*int(lastBlk.GetViews()+uint32(timeOutCount)+1)) * time.Second)
   290  		}
   291  
   292  		/*	log.Info("==Server epochPorcess loop latest", "blknum", lastBlk.GetBlockNum(), "view", lastBlk.GetViews(), "blktime", lastBlkTime,
   293  			"t0", t0, "t1", t1, "t2", t2, "curblknum", srv.dpoaMgr.store.getLatestBlockNumber()+1, "timeOutCount", timeOutCount)
   294  		*/
   295  		if srv.dpoaMgr.store.inFailers(curEpoch.GetBlockNum(), srv.cfg.accountStr) {
   296  			if time.Now().Before(endtime) && endtime.Sub(time.Now()).Seconds() < float64(srv.cfg.starsCfg.duration) { // 如果本节点是failer 发送签名超时给地球
   297  				//fmt.Println("----------case3 >>>>>>>>>>>>send earthsigs")
   298  				blk, _ := srv.dpoaMgr.store.getLatestBlock()
   299  				hash := blk.Block.Hash()
   300  				sig, err := srv.cfg.account.Sign(hash[:])
   301  				if err != nil {
   302  					log.Error("sign 352 blk.block.hash() occured error", "error", err)
   303  					return
   304  				}
   305  				msg := constructEarthSigsFetchRspMsg(srv.dpoaMgr.store.getLatestBlockNumber()+1, srv.cfg.accountStr, sig, hash)
   306  				srv.trans.sendMsg(&SendMsgEvent{
   307  					ToPeer: srv.dpoaMgr.store.earthNode(),
   308  					Msg:    msg,
   309  				})
   310  				break
   311  			}
   312  		}
   313  		/*
   314  		Case 1 10-20s
   315  		Case 2 0-10s waiting for the block
   316  		Case 3 >20 send timeout
   317  		*/
   318  		// case 1 starts consensus
   319  		if time.Now().After(t0) && time.Now().Before(t1) {
   320  			stopCh := make(chan struct{})
   321  			srv.dpoaMgr.startwork(timeOutCount, blkNum, stopCh)
   322  		Flag:
   323  			delay := t1.Sub(time.Now())
   324  			//fmt.Println(" ---------case1 update waitEvent", delay, timeOutCount)
   325  			select {
   326  			case <-time.After(delay):
   327  				//fmt.Println(" ---------case1 after")
   328  				select {
   329  				case <-stopCh:
   330  				default:
   331  					close(stopCh)
   332  				}
   333  				//fmt.Println(" ---------case1 after!")
   334  				continue
   335  				//case <-srv.store.epochNotify:
   336  				//case <-srv.annNewBlock:
   337  			case <-subCh:
   338  				if blkNum == srv.dpoaMgr.store.getLatestBlockNumber() { //
   339  					//fmt.Println("提前停止!!!!!!!!!!!!!!!")
   340  					select {
   341  					case <-stopCh:
   342  					default:
   343  						close(stopCh)
   344  					}
   345  				}
   346  				goto Flag
   347  			case <-srv.quitC:
   348  			case <-srv.stopNewHtCh:
   349  				descStr = "quitC or stopNewHtCh"
   350  				close(stopCh)
   351  				return
   352  			}
   353  		}
   354  
   355  		// case 2 waiting
   356  		if time.Now().Before(t0) {
   357  			delay := t0.Sub(time.Now()) //time.Now().Sub(t1)
   358  			//fmt.Println(" ---------case2 update waitEvent", delay, timeOutCount, time.Now())
   359  			select {
   360  			case <-time.After(delay):
   361  				//fmt.Println(" 1111---------case2 update waitEvent", delay, timeOutCount, time.Now())
   362  				continue
   363  			case <-srv.quitC:
   364  				//fmt.Println(" 4444---------case2 update waitEvent", delay, timeOutCount, time.Now())
   365  				return
   366  			case <-srv.stopNewHtCh:
   367  				//fmt.Println(" 5555---------case2 update waitEvent", delay, timeOutCount, time.Now())
   368  				descStr = "quitC or stopNewHtCh"
   369  				return
   370  			}
   371  			//fmt.Println(" 77777---------case2 update waitEvent", delay, timeOutCount, time.Now())
   372  		}
   373  
   374  		// case3 timeout
   375  		if time.Now().After(t1) && time.Now().Before(t2) {
   376  			if preNum == srv.dpoaMgr.store.db.GetCurrentBlockHeight() {
   377  				//fmt.Println(" ---------case3 1update waitEvent", preNum, srv.dpoaMgr.store.db.GetCurrentBlockHeight())
   378  				phData := &comm.ViewData{BlkNum: srv.dpoaMgr.partiCfg.BlkNum, View: srv.dpoaMgr.partiCfg.View}
   379  				pb, _ := json.Marshal(phData)
   380  				b, err := srv.cfg.account.Sign(pb)
   381  				if err != nil {
   382  					log.Error("sign procmode433 occured error", "error", err)
   383  					return
   384  				}
   385  				srv.trans.sendMsg(&SendMsgEvent{
   386  					ToPeer: comm.BroadCast,
   387  					Msg:    &comm.ViewtimeoutMsg{RawData: phData, Signature: b, PubKey: srv.cfg.accountStr},
   388  				})
   389  			} else {
   390  				preNum = srv.dpoaMgr.store.db.GetCurrentBlockHeight()
   391  				//fmt.Println(" ---------case3 2update waitEvent", preNum, srv.dpoaMgr.store.db.GetCurrentBlockHeight())
   392  			}
   393  			delay := t2.Sub(time.Now())
   394  			//fmt.Println(" ---------case3 update waitEvent", timeOutCount, delay)
   395  
   396  			select {
   397  			//case <-srv.annNewBlock:
   398  			//	fmt.Println("$$$$$$$$$$$$$$srv.annNewBlock", lastBlkTime, srv.GetCurrentBlockNo(), srv.GetCurrentBlockNo(), srv.store.getLatestBlockNumber(), srv.store.db.GetCurrentBlockHeight())
   399  			case <-time.After(delay):
   400  				//fmt.Println("$$$$$$$$$$$$$$time.After", lastBlkTime, srv.dpoaMgr.store.getLatestBlockNumber()+1, srv.dpoaMgr.store.getLatestBlockNumber()+1, srv.dpoaMgr.store.getLatestBlockNumber(), srv.dpoaMgr.store.db.GetCurrentBlockHeight())
   401  				continue
   402  			case <-srv.quitC:
   403  			case <-srv.stopNewHtCh:
   404  				descStr = "quitC or stopNewHtCh"
   405  				return
   406  			}
   407  		}
   408  
   409  		if time.Now().After(t2) {
   410  			//fmt.Println(" ---------case4 update waitEvent", t2, time.Now())
   411  			select {
   412  			case <-time.After(comm.V_Three * time.Second):
   413  				//fmt.Println("wait timeout or new block", time.Now(), t2, lastBlk.GetViews()+uint32(timeOutCount)+1)
   414  				continue
   415  			case <-srv.quitC:
   416  			case <-srv.stopNewHtCh:
   417  				descStr = "quitC or stopNewHtCh"
   418  				return
   419  			}
   420  		}
   421  	}
   422  }
   423  
   424  func (srv *ProcMode) NewEpoch() {
   425  	var (
   426  		desc        string
   427  		blkNum      uint64 = srv.dpoaMgr.store.getLatestBlockNumber() + 1
   428  		lastBlk, _         = srv.dpoaMgr.store.getSealedBlock(blkNum - 1)
   429  		lastBlkTime        = time.Unix(int64(lastBlk.Block.Header.Timestamp), 0)
   430  		stars              = srv.dpoaMgr.store.GetCurStars()
   431  		ebgHeight          = srv.dpoaMgr.store.EpochBegin()
   432  	)
   433  
   434  	defer func() {
   435  		log.Info("Server NewEpoch exit", "blkNum", blkNum, "cause", desc)
   436  		select {
   437  		case <-srv.stopNewHtCh:
   438  		default:
   439  			close(srv.stopNewHtCh)
   440  		}
   441  	}()
   442  
   443  	blkData, _ := srv.dpoaMgr.store.getSealedBlock(ebgHeight)
   444  	_, epochViews := CalcStellar(float64(len(stars)))
   445  	endtime := time.Unix(int64(blkData.Block.Header.Timestamp), 0).Add(time.Duration(srv.cfg.starsCfg.duration) * time.Second).Add(2 * time.Duration(srv.cfg.starsCfg.duration) * time.Second * time.Duration(epochViews))
   446  	log.Info("Server NewEpoch waitEvent curblkbum, lastblktime, range", "blkNum", blkNum, "lastBlkTime", lastBlkTime, "time", time.Now().Sub(lastBlkTime).Seconds())
   447  	fmt.Println("Server NewEpoch waitEvent curblkbum, lastblktime, range", "blkNum", blkNum, "lastBlkTime", lastBlkTime, "time", time.Now().Sub(lastBlkTime).Seconds())
   448  	srv.stopNewHtCh = make(chan struct{})
   449  
   450  	if srv.trans.stateMgr.getState() != SyncReady {
   451  		log.Error("Server NewEpoch state is not SyncReady or Synced", "err is", srv.trans.stateMgr.getState())
   452  		desc = fmt.Sprintf("Server NewEpoch state is not SyncReady or Synced", "err is", srv.trans.stateMgr.getState())
   453  		return
   454  	}
   455  
   456  	log.Info("Server NewEpoch loop latest blktime, epoch begin height, epoch endtime", "lastBlkTime", lastBlkTime, "ebgHeight", ebgHeight, "endtime", endtime)
   457  
   458  	if time.Now().After(endtime) {
   459  		log.Info("Server NewEpoch waitEvent blknum, latest blknum, out of range", "blkNum", blkNum, "lastBlkTime", lastBlkTime, "time", time.Now().Sub(lastBlkTime).Seconds())
   460  		desc = fmt.Sprintf("Server NewEpoch waitEvent blknum %v, latest blknum %v, out of range %v (s)", blkNum, lastBlkTime, time.Now().Sub(lastBlkTime).Seconds())
   461  		return
   462  	}
   463  
   464  	srv.epochPorcess(endtime, epochViews, lastBlk, blkData)
   465  }