|
|
@ -8,53 +8,60 @@ import ( |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
// WaitForConsensusReady listen for the readiness signal from consensus and generate new block for consensus.
|
|
|
|
// WaitForConsensusReady listen for the readiness signal from consensus and generate new block for consensus.
|
|
|
|
func (node *Node) WaitForConsensusReady(readySignal chan struct{}) { |
|
|
|
func (node *Node) WaitForConsensusReady(readySignal chan struct{}, stopChan chan struct{}, stoppedChan chan struct{}) { |
|
|
|
utils.GetLogInstance().Debug("Waiting for Consensus ready", "node", node) |
|
|
|
go func() { |
|
|
|
time.Sleep(15 * time.Second) // Wait for other nodes to be ready (test-only)
|
|
|
|
// Setup stoppedChan
|
|
|
|
|
|
|
|
defer close(stoppedChan) |
|
|
|
|
|
|
|
|
|
|
|
firstTime := true |
|
|
|
utils.GetLogInstance().Debug("Waiting for Consensus ready", "node", node) |
|
|
|
var newBlock *types.Block |
|
|
|
time.Sleep(15 * time.Second) // Wait for other nodes to be ready (test-only)
|
|
|
|
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) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
firstTime := true |
|
|
|
|
|
|
|
var newBlock *types.Block |
|
|
|
|
|
|
|
timeoutCount := 0 |
|
|
|
for { |
|
|
|
for { |
|
|
|
// threshold and firstTime are for the test-only built-in smart contract tx. TODO: remove in production
|
|
|
|
// keep waiting for Consensus ready
|
|
|
|
threshold := 1 |
|
|
|
select { |
|
|
|
if firstTime { |
|
|
|
case <-readySignal: |
|
|
|
threshold = 2 |
|
|
|
time.Sleep(100 * time.Millisecond) // Delay a bit so validator is catched up (test-only).
|
|
|
|
firstTime = false |
|
|
|
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 { |
|
|
|
for { |
|
|
|
// Normal tx block consensus
|
|
|
|
// threshold and firstTime are for the test-only built-in smart contract tx. TODO: remove in production
|
|
|
|
selectedTxs := node.getTransactionsForNewBlock(MaxNumberOfTransactionsPerBlock) |
|
|
|
threshold := 1 |
|
|
|
if len(selectedTxs) != 0 { |
|
|
|
if firstTime { |
|
|
|
node.Worker.CommitTransactions(selectedTxs) |
|
|
|
threshold = 2 |
|
|
|
block, err := node.Worker.Commit() |
|
|
|
firstTime = false |
|
|
|
if err != nil { |
|
|
|
} |
|
|
|
utils.GetLogInstance().Debug("Failed commiting new block", "Error", err) |
|
|
|
utils.GetLogInstance().Debug("STARTING BLOCK", "threshold", threshold, "pendingTransactions", len(node.pendingTransactions)) |
|
|
|
} else { |
|
|
|
if len(node.pendingTransactions) >= threshold { |
|
|
|
newBlock = block |
|
|
|
// Normal tx block consensus
|
|
|
|
break |
|
|
|
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 |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
}() |
|
|
|
} |
|
|
|
} |
|
|
|