diff --git a/consensus/README.md b/consensus/README.md index 46d33032f..182e30bfa 100644 --- a/consensus/README.md +++ b/consensus/README.md @@ -1,4 +1,18 @@ -The core consensus algorithm. +# The core consensus algorithm. * state.go - The state machine as detailed in the whitepaper * reactor.go - A reactor that connects the state machine to the gossip network + +# Go-routine summary + +The reactor runs 2 go-routines for each added peer: gossipDataRoutine and gossipVotesRoutine. + +The consensus state runs two persistent go-routines: timeoutRoutine and receiveRoutine. +Go-routines are also started to trigger timeouts and to avoid blocking when the internalMsgQueue is really backed up. + +# Replay/WAL + +A write-ahead log is used to record all messages processed by the receiveRoutine, +which amounts to all inputs to the consensus state machine: +messages from peers, messages from ourselves, and timeouts. +They can be played back deterministically at startup or using the replay console. diff --git a/consensus/state.go b/consensus/state.go index f89de3921..192253192 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -432,7 +432,7 @@ func (cs *ConsensusState) sendInternalMessage(mi msgInfo) { // be processed out of order. // TODO: use CList here for strict determinism and // attempt push to internalMsgQueue in receiveRoutine - log.Debug("Internal msg queue is full. Using a go-routine") + log.Warn("Internal msg queue is full. Using a go-routine") go func() { cs.internalMsgQueue <- mi }() } } diff --git a/rpc/core/consensus.go b/rpc/core/consensus.go index 92ea4edfc..2a0b43614 100644 --- a/rpc/core/consensus.go +++ b/rpc/core/consensus.go @@ -11,6 +11,8 @@ func Validators() (*ctypes.ResultValidators, error) { var blockHeight int var validators []*types.Validator + // XXX: this is racy. + // Either use state.LoadState(db) or make state atomic (see #165) state := consensusState.GetState() blockHeight = state.LastBlockHeight state.Validators.Iterate(func(index int, val *types.Validator) bool {