Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Consensus] Decoupling the Pacemaker and Consensus modules (Synchronous method) #427

Merged
merged 71 commits into from
Jan 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
606fdb5
consensus (refactor): new shared interface of consensus for pacemaker
gokutheengineer Jan 3, 2023
91b8b32
refactor (consensus): WIP, seperate interfaces, remove consensusMod f…
gokutheengineer Jan 4, 2023
7ffd4fe
refactor (consensus): create pacemaker submodule
gokutheengineer Jan 4, 2023
a82f0a9
refactor (consensus): clean some comments
gokutheengineer Jan 4, 2023
467c81e
consensus (refactor): WIP cleanup
gokutheengineer Jan 5, 2023
8339d95
refactor (consensus): WIP more cleanup
gokutheengineer Jan 5, 2023
e68b9ac
consensus (refactor): address remaining comments on PR
gokutheengineer Jan 5, 2023
8411b85
rafactor: remove unused function
gokutheengineer Jan 7, 2023
5c9e28c
refactor: address PR comments
gokutheengineer Jan 7, 2023
4ab88d2
Update shared/modules/consensus_module.go
gokutheengineer Jan 7, 2023
db8350d
Update shared/modules/consensus_module.go
gokutheengineer Jan 7, 2023
b803a38
Update consensus/pacemaker_consensus.go
gokutheengineer Jan 7, 2023
f6e81d9
Update shared/modules/consensus_module.go
gokutheengineer Jan 7, 2023
d3d479c
refactor (consensus): return error in GetPrepareQC
gokutheengineer Jan 7, 2023
e1a454c
Update shared/modules/consensus_module.go
gokutheengineer Jan 10, 2023
5795d08
initial rebased version, WIP
gokutheengineer Jan 11, 2023
1a4a682
refactor (consensus): clean and add some comments
gokutheengineer Jan 12, 2023
b05a7b5
WIP: clean some comments, start updating CHANGELOG
gokutheengineer Jan 12, 2023
c57197e
clean few comments, update CHANGELOGS, remove incomplete byzantine te…
gokutheengineer Jan 13, 2023
193786c
Update consensus/pacemaker/pacemaker.go
gokutheengineer Jan 14, 2023
3e518f0
Update consensus/doc/CHANGELOG.md
gokutheengineer Jan 14, 2023
cc8705f
clean, address comments
gokutheengineer Jan 14, 2023
ad80249
move pacemaker
gokutheengineer Jan 15, 2023
01f2efd
refactor: bring back pacemaker impl
gokutheengineer Jan 15, 2023
bd603a1
fix comments
gokutheengineer Jan 16, 2023
59e1ac7
remove pacemaker
gokutheengineer Jan 16, 2023
760ce07
add updated pacemaker
gokutheengineer Jan 16, 2023
bfed5c1
Bring back old pacemaker
Olshansk Jan 16, 2023
fc1bcfb
Move file
Olshansk Jan 16, 2023
aacef7e
Apply changes
Olshansk Jan 16, 2023
907f5df
refactor: remove shouldHandleHotstuffMessage
gokutheengineer Jan 17, 2023
1887c02
Update consensus/module.go
gokutheengineer Jan 17, 2023
3351d9b
refactor: update prepareQC
gokutheengineer Jan 17, 2023
38798ee
refactor: address comments
gokutheengineer Jan 17, 2023
cfece55
Update consensus/pacemaker/pacemaker.go
gokutheengineer Jan 17, 2023
8e0b9a9
fix comment
gokutheengineer Jan 17, 2023
dbf3775
merge
gokutheengineer Jan 17, 2023
cd9c74e
update changelog in consensus
gokutheengineer Jan 17, 2023
81fa9e2
fix
gokutheengineer Jan 17, 2023
d038950
fix localnet issue
gokutheengineer Jan 19, 2023
398ba44
refactor: add comments, fix
gokutheengineer Jan 19, 2023
9b5c396
Merge branch 'main' into issue/395-decouple-consensus-and-pacemaker
gokutheengineer Jan 19, 2023
6c9ba7e
Revert "Merge branch 'main' into issue/395-decouple-consensus-and-pac…
gokutheengineer Jan 19, 2023
92e9a8d
update changelogs
gokutheengineer Jan 19, 2023
bfe8adc
update changelog of persistance
gokutheengineer Jan 19, 2023
988aad1
merge: recent main
gokutheengineer Jan 20, 2023
205fd45
fix changelog date
gokutheengineer Jan 20, 2023
5c8f1c5
checkout makefile from master branch
gokutheengineer Jan 21, 2023
244cd66
add block.proto
gokutheengineer Jan 21, 2023
82ef4d8
add consensus state_sync.proto
gokutheengineer Jan 21, 2023
405b231
rm persistance block_persistance.proto
gokutheengineer Jan 21, 2023
fbfb238
update block type
gokutheengineer Jan 21, 2023
ef38cbe
update CHANGELOGs
gokutheengineer Jan 21, 2023
4d5d8d7
fix hotstuff_leader
gokutheengineer Jan 21, 2023
5bb8f14
fix hotstuff_replica
gokutheengineer Jan 21, 2023
6b95583
fix messages
gokutheengineer Jan 21, 2023
06a4cf5
fix state_sync module
gokutheengineer Jan 21, 2023
5061efe
remove extra comment line added by viscose
gokutheengineer Jan 21, 2023
1e727b2
fix changes of vscode
gokutheengineer Jan 21, 2023
ef7bf90
fix pacemaker test
gokutheengineer Jan 21, 2023
89b226e
fix persistance state test
gokutheengineer Jan 21, 2023
b1bcad0
add persistance files
gokutheengineer Jan 21, 2023
f8a12a3
merge main
gokutheengineer Jan 21, 2023
18632fb
add learning doc
gokutheengineer Jan 21, 2023
e96561d
udpate outdated file
gokutheengineer Jan 21, 2023
e49b2e2
udpate changelog date
gokutheengineer Jan 21, 2023
75f24b6
remove extra space
gokutheengineer Jan 21, 2023
0060696
Fix issue in CHANGELOG
Olshansk Jan 23, 2023
a654190
A few minor nits
Olshansk Jan 24, 2023
fed9f8b
Update changelog
Olshansk Jan 24, 2023
c9b61fa
Merge branch 'main' into issue/395-decouple-consensus-and-pacemaker
Olshansk Jan 24, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 2 additions & 30 deletions consensus/debugging.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func (m *consensusModule) GetNodeState() typesCons.ConsensusNodeState {
Height: m.height,
Round: uint8(m.round),
Step: uint8(m.step),
IsLeader: m.isLeader(),
IsLeader: m.IsLeader(),
LeaderId: leaderId,
}
}
Expand All @@ -46,7 +46,7 @@ func (m *consensusModule) resetToGenesis(_ *messaging.DebugMessage) {
m.nodeLog(typesCons.DebugResetToGenesis)

m.height = 0
m.resetForNewHeight()
m.ResetForNewHeight()
m.clearLeader()
m.clearMessagesPool()
m.GetBus().GetPersistenceModule().HandleDebugMessage(&messaging.DebugMessage{
Expand Down Expand Up @@ -86,31 +86,3 @@ func (m *consensusModule) togglePacemakerManualMode(_ *messaging.DebugMessage) {
}
m.paceMaker.SetManualMode(newMode)
}

// This Pacemaker interface is only used for development & debugging purposes.
type PacemakerDebug interface {
SetManualMode(bool)
IsManualMode() bool
ForceNextView()
}

type paceMakerDebug struct {
manualMode bool
debugTimeBetweenStepsMsec uint64

// IMPROVE: Consider renaming to `previousRoundQC`
quorumCertificate *typesCons.QuorumCertificate
}

func (p *paceMaker) IsManualMode() bool {
return p.manualMode
}

func (p *paceMaker) SetManualMode(manualMode bool) {
p.manualMode = manualMode
}

func (p *paceMaker) ForceNextView() {
lastQC := p.quorumCertificate
p.startNextView(lastQC, true)
}
7 changes: 7 additions & 0 deletions consensus/doc/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.0.0.21] - 2023-01-24

- Decouple consensus module and pacemaker module
- Add `pacemaker` submodule
- Update pacemaker struct to remove consensus module field, and related functions
- Create new `pacemaker_consensus.go` source file that consists ConsensusPacemaker function implementations

## [0.0.0.20] - 2023-01-19

- Rewrite `interface{}` to `any`
Expand Down
2 changes: 1 addition & 1 deletion consensus/e2e_tests/pacemaker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ func TestPacemakerCatchupSameStepDifferentRounds(t *testing.T) {

// Starting point
testHeight := uint64(3)
testStep := consensus.NewRound
testStep := uint8(consensus.NewRound)

// UnitTestNet configs
paceMakerTimeoutMsec := uint64(500) // Set a small pacemaker timeout
Expand Down
21 changes: 3 additions & 18 deletions consensus/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,13 +130,6 @@ func (m *consensusModule) isOptimisticThresholdMet(numSignatures int, validators
return nil
}

func (m *consensusModule) resetForNewHeight() {
m.round = 0
m.block = nil
m.highPrepareQC = nil
m.lockedQC = nil
}

func protoHash(m proto.Message) string {
b, err := codec.GetCodec().Marshal(m)
if err != nil {
Expand Down Expand Up @@ -208,17 +201,8 @@ func (m *consensusModule) clearMessagesPool() {
}

/*** Leader Election Helpers ***/

func (m *consensusModule) isLeaderUnknown() bool {
return m.leaderId == nil
}

func (m *consensusModule) isLeader() bool {
return m.leaderId != nil && *m.leaderId == m.nodeId
}

func (m *consensusModule) isReplica() bool {
return !m.isLeader()
return !m.IsLeader()
}

func (m *consensusModule) clearLeader() {
Expand All @@ -242,7 +226,7 @@ func (m *consensusModule) electNextLeader(message *typesCons.HotstuffMessage) er

idToValAddrMap := typesCons.NewActorMapper(validators).GetIdToValAddrMap()

if m.isLeader() {
if m.IsLeader() {
m.setLogPrefix("LEADER")
m.nodeLog(typesCons.ElectedSelfAsNewLeader(idToValAddrMap[*m.leaderId], *m.leaderId, m.height, m.round))
} else {
Expand All @@ -267,6 +251,7 @@ func (m *consensusModule) nodeLogError(s string, err error) {

func (m *consensusModule) setLogPrefix(logPrefix string) {
m.logPrefix = logPrefix
m.paceMaker.SetLogPrefix(logPrefix)
}

func (m *consensusModule) getValidatorsAtHeight(height uint64) ([]*coreTypes.Actor, error) {
Expand Down
18 changes: 9 additions & 9 deletions consensus/hotstuff_leader.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func (handler *HotstuffLeaderMessageHandler) HandleNewRoundMessage(m *consensusM
}

// Likely to be `nil` if blockchain is progressing well.
// TECHDEBT: How do we properly validate `highPrepareQC` here?
// TECHDEBT: How do we properly validate `prepareQC` here?
highPrepareQC := m.findHighQC(m.messagePool[NewRound])

// TODO: Add test to make sure same block is not applied twice if round is interrupted after being 'Applied'.
Expand All @@ -64,7 +64,7 @@ func (handler *HotstuffLeaderMessageHandler) HandleNewRoundMessage(m *consensusM
}
m.block = block
} else {
// Leader acts like a replica if `highPrepareQC` is not `nil`
// Leader acts like a replica if `prepareQC` is not `nil`
// TODO: Do we need to call `validateProposal` here similar to how replicas does it
if err := m.applyBlock(highPrepareQC.Block); err != nil {
m.nodeLogError(typesCons.ErrApplyBlock.Error(), err)
Expand Down Expand Up @@ -118,7 +118,7 @@ func (handler *HotstuffLeaderMessageHandler) HandlePrepareMessage(m *consensusMo
}

m.step = PreCommit
m.highPrepareQC = prepareQC
m.prepareQC = prepareQC
m.messagePool[Prepare] = nil

preCommitProposeMessage, err := CreateProposeMessage(m.height, m.round, PreCommit, m.block, prepareQC)
Expand Down Expand Up @@ -400,19 +400,19 @@ func (m *consensusModule) prepareAndApplyBlock(qc *typesCons.QuorumCertificate)
// ADDTEST: Add more tests for all the different scenarios here
func (m *consensusModule) shouldPrepareNewBlock(highPrepareQC *typesCons.QuorumCertificate) bool {
if highPrepareQC == nil {
m.nodeLog("Preparing a new block - no highPrepareQC found")
m.nodeLog("Preparing a new block - no prepareQC found")
return true
} else if m.isHighPrepareQCFromPast(highPrepareQC) {
m.nodeLog("Preparing a new block - highPrepareQC is from the past")
} else if m.isPrepareQCFromPast(highPrepareQC) {
m.nodeLog("Preparing a new block - prepareQC is from the past")
return true
} else if highPrepareQC.Block == nil {
m.nodeLog("[WARN] Preparing a new block - highPrepareQC SHOULD be used but block is nil")
m.nodeLog("[WARN] Preparing a new block - prepareQC SHOULD be used but block is nil")
return true
}
return false
}

// The `highPrepareQC` is from the past so we can safely ignore it
func (m *consensusModule) isHighPrepareQCFromPast(highPrepareQC *typesCons.QuorumCertificate) bool {
// The `prepareQC` is from the past so we can safely ignore it
func (m *consensusModule) isPrepareQCFromPast(highPrepareQC *typesCons.QuorumCertificate) bool {
return highPrepareQC.Height < m.height || highPrepareQC.Round < m.round
}
2 changes: 1 addition & 1 deletion consensus/hotstuff_replica.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ func (handler *HotstuffReplicaMessageHandler) HandlePrecommitMessage(m *consensu
}

m.step = Commit
m.highPrepareQC = quorumCert // INVESTIGATE: Why are we never using this for validation?
m.prepareQC = quorumCert // INVESTIGATE: Why are we never using this for validation?

preCommitVoteMessage, err := CreateVoteMessage(m.height, m.round, PreCommit, m.block, m.privateKey)
if err != nil {
Expand Down
54 changes: 29 additions & 25 deletions consensus/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"sync"

"github.com/pokt-network/pocket/consensus/leader_election"
"github.com/pokt-network/pocket/consensus/pacemaker"
consensusTelemetry "github.com/pokt-network/pocket/consensus/telemetry"
typesCons "github.com/pokt-network/pocket/consensus/types"
"github.com/pokt-network/pocket/runtime/configs"
Expand Down Expand Up @@ -49,9 +50,8 @@ type consensusModule struct {
// TODO(#315): Move the statefulness of `TxResult` to the persistence module
TxResults []modules.TxResult // The current block applied transaction results / voted on; it has not been committed to finality

// IMPROVE: Consider renaming `highPrepareQC` to simply `prepareQC`
highPrepareQC *typesCons.QuorumCertificate // Highest QC for which replica voted PRECOMMIT
lockedQC *typesCons.QuorumCertificate // Highest QC for which replica voted COMMIT
prepareQC *typesCons.QuorumCertificate // Highest QC for which replica voted PRECOMMIT
gokutheengineer marked this conversation as resolved.
Show resolved Hide resolved
lockedQC *typesCons.QuorumCertificate // Highest QC for which replica voted COMMIT

// Leader Election
leaderId *typesCons.NodeId
Expand All @@ -63,7 +63,7 @@ type consensusModule struct {
// to streamline how its accessed in the module (see the ticket).

utilityContext modules.UtilityContext
paceMaker Pacemaker
paceMaker pacemaker.Pacemaker
leaderElectionMod leader_election.LeaderElectionModule

// DEPRECATE: Remove later when we build a shared/proper/injected logger
Expand All @@ -78,34 +78,42 @@ type consensusModule struct {
type ConsensusDebugModule interface {
SetHeight(uint64)
SetRound(uint64)
SetStep(typesCons.HotstuffStep)
// REFACTOR: This should accept typesCons.HotstuffStep.
SetStep(uint8)
gokutheengineer marked this conversation as resolved.
Show resolved Hide resolved
SetBlock(*coreTypes.Block)
SetLeaderId(*typesCons.NodeId)
SetUtilityContext(modules.UtilityContext)
}

func (c *consensusModule) SetHeight(height uint64) {
c.height = height
func (m *consensusModule) SetHeight(height uint64) {
m.height = height
}

func (c *consensusModule) SetRound(round uint64) {
c.round = round
func (m *consensusModule) SetRound(round uint64) {
m.round = round
}

func (c *consensusModule) SetStep(step typesCons.HotstuffStep) {
c.step = step
func (m *consensusModule) SetStep(step uint8) {
m.step = typesCons.HotstuffStep(step)
}

func (c *consensusModule) SetBlock(block *coreTypes.Block) {
c.block = block
func (m *consensusModule) SetBlock(block *coreTypes.Block) {
m.block = block
}

func (c *consensusModule) SetLeaderId(leaderId *typesCons.NodeId) {
c.leaderId = leaderId
func (m *consensusModule) SetLeaderId(leaderId *typesCons.NodeId) {
m.leaderId = leaderId
}

func (c *consensusModule) SetUtilityContext(utilityContext modules.UtilityContext) {
c.utilityContext = utilityContext
func (m *consensusModule) SetUtilityContext(utilityContext modules.UtilityContext) {
m.utilityContext = utilityContext
}

// Implementations of the type PaceMakerAccessModule interface
gokutheengineer marked this conversation as resolved.
Show resolved Hide resolved
// SetHeight, SeetRound, SetStep are implemented for ConsensusDebugModule
func (m *consensusModule) ClearLeaderMessagesPool() {
m.clearLeader()
m.clearMessagesPool()
}

func Create(bus modules.Bus) (modules.Module, error) {
Expand All @@ -118,13 +126,12 @@ func (*consensusModule) Create(bus modules.Bus) (modules.Module, error) {
return nil, err
}

// TODO(olshansky): Can we make this a submodule?
paceMakerMod, err := CreatePacemaker(bus)
paceMakerMod, err := pacemaker.CreatePacemaker(bus)
if err != nil {
return nil, err
}

pacemaker := paceMakerMod.(Pacemaker)
pacemaker := paceMakerMod.(pacemaker.Pacemaker)
m := &consensusModule{
paceMaker: pacemaker,
leaderElectionMod: leaderElectionMod.(leader_election.LeaderElectionModule),
Expand All @@ -134,8 +141,8 @@ func (*consensusModule) Create(bus modules.Bus) (modules.Module, error) {
step: NewRound,
block: nil,

highPrepareQC: nil,
lockedQC: nil,
prepareQC: nil,
lockedQC: nil,

leaderId: nil,

Expand All @@ -147,9 +154,6 @@ func (*consensusModule) Create(bus modules.Bus) (modules.Module, error) {
}
bus.RegisterModule(m)

// TODO(#395): Decouple the pacemaker and consensus modules
pacemaker.SetConsensusModule(m)

runtimeMgr := bus.GetRuntimeMgr()

consensusCfg := runtimeMgr.GetConfig().Consensus
Expand Down
Loading