From fb630dbcca9b023668f920c02d62f6a3596e68be Mon Sep 17 00:00:00 2001 From: Minh Doan Date: Thu, 31 Jan 2019 09:20:04 -0800 Subject: [PATCH] finish logic of new block service --- api/service/newblock/service.go | 28 +++-------- node/node_newblock.go | 89 ++++++++++++++++++--------------- 2 files changed, 55 insertions(+), 62 deletions(-) diff --git a/api/service/newblock/service.go b/api/service/newblock/service.go index 60de272e8..d324beaba 100644 --- a/api/service/newblock/service.go +++ b/api/service/newblock/service.go @@ -6,13 +6,15 @@ import ( // Service is the new block service. type Service struct { - stopChan chan struct{} - stoppedChan chan struct{} + stopChan chan struct{} + stoppedChan chan struct{} + readySignal chan struct{} + waitForConsensusReady func(readySignal chan struct{}, stopChan chan struct{}, stoppedChan chan struct{}) } // NewService returns new block service. -func NewService() *Service { - return &Service{} +func NewService(readySignal chan struct{}, waitForConsensusReady func(readySignal chan struct{}, stopChan chan struct{}, stoppedChan chan struct{})) *Service { + return &Service{readySignal: readySignal, waitForConsensusReady: waitForConsensusReady} } // StartService starts new block service. @@ -30,23 +32,7 @@ func (s *Service) Init() { // Run runs new block. func (s *Service) Run(stopChan chan struct{}, stoppedChan chan struct{}) { - go func() { - defer close(stoppedChan) - for { - select { - default: - utils.GetLogInstance().Info("Running new block") - // TODO: Write some logic here. - s.DoService() - case <-stopChan: - return - } - } - }() -} - -// DoService does new block. -func (s *Service) DoService() { + s.waitForConsensusReady(s.readySignal, s.stopChan, s.stoppedChan) } // StopService stops new block service. diff --git a/node/node_newblock.go b/node/node_newblock.go index 331e51845..68af780ec 100644 --- a/node/node_newblock.go +++ b/node/node_newblock.go @@ -8,53 +8,60 @@ import ( ) // WaitForConsensusReady listen for the readiness signal from consensus and generate new block for consensus. -func (node *Node) WaitForConsensusReady(readySignal chan struct{}) { - utils.GetLogInstance().Debug("Waiting for Consensus ready", "node", node) - time.Sleep(15 * time.Second) // Wait for other nodes to be ready (test-only) +func (node *Node) WaitForConsensusReady(readySignal chan struct{}, stopChan chan struct{}, stoppedChan chan struct{}) { + go func() { + // Setup stoppedChan + defer close(stoppedChan) - firstTime := true - var newBlock *types.Block - timeoutCount := 0 - for { - // keep waiting for Consensus ready - select { - case <-readySignal: - time.Sleep(100 * time.Millisecond) // Delay a bit so validator is catched up (test-only). - case <-time.After(200 * time.Second): - node.Consensus.ResetState() - timeoutCount++ - utils.GetLogInstance().Debug("Consensus timeout, retry!", "count", timeoutCount, "node", node) - } + utils.GetLogInstance().Debug("Waiting for Consensus ready", "node", node) + time.Sleep(15 * time.Second) // Wait for other nodes to be ready (test-only) + firstTime := true + var newBlock *types.Block + timeoutCount := 0 for { - // threshold and firstTime are for the test-only built-in smart contract tx. TODO: remove in production - threshold := 1 - if firstTime { - threshold = 2 - firstTime = false + // keep waiting for Consensus ready + select { + case <-readySignal: + time.Sleep(100 * time.Millisecond) // Delay a bit so validator is catched up (test-only). + case <-time.After(200 * time.Second): + node.Consensus.ResetState() + timeoutCount++ + utils.GetLogInstance().Debug("Consensus timeout, retry!", "count", timeoutCount, "node", node) + case <-stopChan: + return } - utils.GetLogInstance().Debug("STARTING BLOCK", "threshold", threshold, "pendingTransactions", len(node.pendingTransactions)) - if len(node.pendingTransactions) >= threshold { - // Normal tx block consensus - selectedTxs := node.getTransactionsForNewBlock(MaxNumberOfTransactionsPerBlock) - if len(selectedTxs) != 0 { - node.Worker.CommitTransactions(selectedTxs) - block, err := node.Worker.Commit() - if err != nil { - utils.GetLogInstance().Debug("Failed commiting new block", "Error", err) - } else { - newBlock = block - break + + for { + // threshold and firstTime are for the test-only built-in smart contract tx. TODO: remove in production + threshold := 1 + if firstTime { + threshold = 2 + firstTime = false + } + utils.GetLogInstance().Debug("STARTING BLOCK", "threshold", threshold, "pendingTransactions", len(node.pendingTransactions)) + if len(node.pendingTransactions) >= threshold { + // Normal tx block consensus + selectedTxs := node.getTransactionsForNewBlock(MaxNumberOfTransactionsPerBlock) + if len(selectedTxs) != 0 { + node.Worker.CommitTransactions(selectedTxs) + block, err := node.Worker.Commit() + if err != nil { + utils.GetLogInstance().Debug("Failed commiting new block", "Error", err) + } else { + newBlock = block + break + } } } + // If not enough transactions to run Consensus, + // periodically check whether we have enough transactions to package into block. + time.Sleep(1 * time.Second) + } + // Send the new block to Consensus so it can be confirmed. + if newBlock != nil { + node.BlockChannel <- newBlock } - // If not enough transactions to run Consensus, - // periodically check whether we have enough transactions to package into block. - time.Sleep(1 * time.Second) - } - // Send the new block to Consensus so it can be confirmed. - if newBlock != nil { - node.BlockChannel <- newBlock } - } + }() }