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 }