From 43113ca762d72dabb2df33e715c72dd415f0a370 Mon Sep 17 00:00:00 2001 From: Yacov Manevich Date: Fri, 12 Jun 2026 16:11:30 +0200 Subject: [PATCH] Split root package into common/ and simplex/ packages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split root package into common/ and simplex/ packages Move the files that lived at the repository root into dedicated packages and update all import paths and package declarations to match. No behavioral changes — this is a pure relocation/refactor. - common/: shared protocol types and helpers (api, blacklist, encoding, global, metadata, msg, notarization) plus their tests. - simplex/: the Simplex protocol implementation (epoch, block scheduler, monitor, replication, requestor, sched, timeout handler, util) plus their tests and the long-running/fuzz/recovery/pos test suites. Will now be instantiated as: "simplex.Epoch" as it should. Update references in the msm, testutil, and wal packages to point at the new locations. Signed-off-by: Yacov Manevich --- api.go => common/api.go | 2 +- blacklist.go => common/blacklist.go | 6 +- blacklist_test.go => common/blacklist_test.go | 2 +- encoding.go => common/encoding.go | 2 +- encoding_test.go => common/encoding_test.go | 2 +- global.go => common/global.go | 2 +- global_test.go => common/global_test.go | 5 +- metadata.go => common/metadata.go | 2 +- metadata_test.go => common/metadata_test.go | 2 +- msg.go => common/msg.go | 6 +- msg_test.go => common/msg_test.go | 52 +-- notarization.go => common/notarization.go | 2 +- .../notarization_test.go | 60 +-- msm/approvals.go | 8 +- msm/build_decision.go | 4 +- msm/encoding.go | 14 +- msm/encoding_test.go | 6 +- msm/fake_node_test.go | 22 +- msm/fuzz_test.go | 12 +- msm/msm.go | 40 +- msm/msm_test.go | 62 +-- msm/util_test.go | 32 +- .../block_scheduler.go | 13 +- .../block_scheduler_test.go | 29 +- epoch.go => simplex/epoch.go | 429 +++++++++--------- .../epoch_failover_test.go | 6 +- .../epoch_multinode_test.go | 47 +- epoch_test.go => simplex/epoch_test.go | 34 +- .../fuzz_network_test.go | 0 leak_test.go => simplex/leak_test.go | 0 .../long_running_test.go | 0 monitor.go => simplex/monitor.go | 5 +- monitor_test.go => simplex/monitor_test.go | 0 pos_test.go => simplex/pos_test.go | 9 +- recovery_test.go => simplex/recovery_test.go | 6 +- .../replication_request_test.go | 75 +-- .../replication_state.go | 49 +- .../replication_test.go | 233 +++++----- .../replication_timeout_test.go | 75 +-- requestor.go => simplex/requestor.go | 33 +- sched.go => simplex/sched.go | 7 +- sched_test.go => simplex/sched_test.go | 11 +- .../timeout_handler.go | 5 +- .../timeout_handler_test.go | 2 +- util.go => simplex/util.go | 61 +-- util_test.go => simplex/util_test.go | 3 +- testutil/block.go | 24 +- testutil/block_builder.go | 4 +- testutil/comm.go | 50 +- testutil/controlled.go | 11 +- testutil/long_running/block_builder.go | 10 +- testutil/long_running/network.go | 5 +- testutil/long_running/node.go | 7 +- testutil/network.go | 19 +- testutil/node.go | 29 +- testutil/random_network/block.go | 28 +- testutil/random_network/config.go | 2 +- testutil/random_network/logging.go | 4 +- testutil/random_network/mempool.go | 26 +- testutil/random_network/mempool_test.go | 12 +- testutil/random_network/network.go | 10 +- testutil/random_network/node.go | 13 +- testutil/random_network/storage.go | 4 +- testutil/random_network/utils.go | 6 +- testutil/record.go | 30 +- testutil/storage.go | 22 +- testutil/util.go | 67 +-- testutil/wal.go | 30 +- wal/gc.go | 4 +- 69 files changed, 959 insertions(+), 935 deletions(-) rename api.go => common/api.go (99%) rename blacklist.go => common/blacklist.go (99%) rename blacklist_test.go => common/blacklist_test.go (99%) rename encoding.go => common/encoding.go (99%) rename encoding_test.go => common/encoding_test.go (99%) rename global.go => common/global.go (98%) rename global_test.go => common/global_test.go (96%) rename metadata.go => common/metadata.go (99%) rename metadata_test.go => common/metadata_test.go (98%) rename msg.go => common/msg.go (99%) rename msg_test.go => common/msg_test.go (63%) rename notarization.go => common/notarization.go (99%) rename notarization_test.go => common/notarization_test.go (74%) rename block_scheduler.go => simplex/block_scheduler.go (92%) rename block_scheduler_test.go => simplex/block_scheduler_test.go (93%) rename epoch.go => simplex/epoch.go (88%) rename epoch_failover_test.go => simplex/epoch_failover_test.go (99%) rename epoch_multinode_test.go => simplex/epoch_multinode_test.go (87%) rename epoch_test.go => simplex/epoch_test.go (98%) rename fuzz_network_test.go => simplex/fuzz_network_test.go (100%) rename leak_test.go => simplex/leak_test.go (100%) rename long_running_test.go => simplex/long_running_test.go (100%) rename monitor.go => simplex/monitor.go (95%) rename monitor_test.go => simplex/monitor_test.go (100%) rename pos_test.go => simplex/pos_test.go (93%) rename recovery_test.go => simplex/recovery_test.go (99%) rename replication_request_test.go => simplex/replication_request_test.go (84%) rename replication_state.go => simplex/replication_state.go (88%) rename replication_test.go => simplex/replication_test.go (89%) rename replication_timeout_test.go => simplex/replication_timeout_test.go (90%) rename requestor.go => simplex/requestor.go (88%) rename sched.go => simplex/sched.go (92%) rename sched_test.go => simplex/sched_test.go (81%) rename timeout_handler.go => simplex/timeout_handler.go (92%) rename timeout_handler_test.go => simplex/timeout_handler_test.go (99%) rename util.go => simplex/util.go (84%) rename util_test.go => simplex/util_test.go (99%) diff --git a/api.go b/common/api.go similarity index 99% rename from api.go rename to common/api.go index eef03e5a..2c5b8839 100644 --- a/api.go +++ b/common/api.go @@ -1,7 +1,7 @@ // Copyright (C) 2019-2025, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package simplex +package common import ( "context" diff --git a/blacklist.go b/common/blacklist.go similarity index 99% rename from blacklist.go rename to common/blacklist.go index a80c16d0..7f925490 100644 --- a/blacklist.go +++ b/common/blacklist.go @@ -1,7 +1,7 @@ // Copyright (C) 2019-2025, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package simplex +package common import ( "encoding/binary" @@ -66,11 +66,11 @@ func (bl *Blacklist) String() string { "Blacklist(nodeCount=%d, SuspectedNodes=[%s], updates=[%s])", bl.NodeCount, strings.Join(sn, ","), - blacklistUpdatesAsString(bl.Updates), // helper receives array + BlacklistUpdatesAsString(bl.Updates), // helper receives array ) } -func blacklistUpdatesAsString(updates []BlacklistUpdate) string { +func BlacklistUpdatesAsString(updates []BlacklistUpdate) string { out := make([]string, len(updates)) for i, u := range updates { out[i] = u.String() diff --git a/blacklist_test.go b/common/blacklist_test.go similarity index 99% rename from blacklist_test.go rename to common/blacklist_test.go index 0a477234..b233b84f 100644 --- a/blacklist_test.go +++ b/common/blacklist_test.go @@ -1,7 +1,7 @@ // Copyright (C) 2019-2025, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package simplex +package common import ( "crypto/rand" diff --git a/encoding.go b/common/encoding.go similarity index 99% rename from encoding.go rename to common/encoding.go index 7593798c..9ac7d681 100644 --- a/encoding.go +++ b/common/encoding.go @@ -1,7 +1,7 @@ // Copyright (C) 2019-2025, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package simplex +package common import ( "context" diff --git a/encoding_test.go b/common/encoding_test.go similarity index 99% rename from encoding_test.go rename to common/encoding_test.go index 84adc4b6..b8449529 100644 --- a/encoding_test.go +++ b/common/encoding_test.go @@ -1,7 +1,7 @@ // Copyright (C) 2019-2025, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package simplex +package common import ( "crypto/rand" diff --git a/global.go b/common/global.go similarity index 98% rename from global.go rename to common/global.go index 771da09a..94be176f 100644 --- a/global.go +++ b/common/global.go @@ -1,7 +1,7 @@ // Copyright (C) 2019-2025, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package simplex +package common import ( "bytes" diff --git a/global_test.go b/common/global_test.go similarity index 96% rename from global_test.go rename to common/global_test.go index 66d50ebe..004401db 100644 --- a/global_test.go +++ b/common/global_test.go @@ -1,11 +1,12 @@ // Copyright (C) 2019-2025, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package simplex +package common import ( - "github.com/stretchr/testify/require" "testing" + + "github.com/stretchr/testify/require" ) func TestNodeIDs(t *testing.T) { diff --git a/metadata.go b/common/metadata.go similarity index 99% rename from metadata.go rename to common/metadata.go index 582eaef1..5c3f3c5f 100644 --- a/metadata.go +++ b/common/metadata.go @@ -1,7 +1,7 @@ // Copyright (C) 2019-2025, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package simplex +package common import ( "bytes" diff --git a/metadata_test.go b/common/metadata_test.go similarity index 98% rename from metadata_test.go rename to common/metadata_test.go index 00c85aa2..577a1386 100644 --- a/metadata_test.go +++ b/common/metadata_test.go @@ -1,7 +1,7 @@ // Copyright (C) 2019-2025, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package simplex +package common import ( "crypto/rand" diff --git a/msg.go b/common/msg.go similarity index 99% rename from msg.go rename to common/msg.go index 0456de2b..c54caa41 100644 --- a/msg.go +++ b/common/msg.go @@ -1,7 +1,7 @@ // Copyright (C) 2019-2025, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package simplex +package common import ( "bytes" @@ -357,10 +357,6 @@ type VerifiedFinalizedBlock struct { Finalization Finalization } -type verifiableMessage interface { - Verify() error -} - type BlockDigestRequest struct { Seq uint64 Digest Digest diff --git a/msg_test.go b/common/msg_test.go similarity index 63% rename from msg_test.go rename to common/msg_test.go index 123f9a4b..a2612a31 100644 --- a/msg_test.go +++ b/common/msg_test.go @@ -1,9 +1,9 @@ -package simplex_test +package common_test import ( "testing" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" "github.com/ava-labs/simplex/testutil" "github.com/stretchr/testify/require" @@ -12,18 +12,18 @@ import ( func TestQuorumRoundMalformed(t *testing.T) { tests := []struct { name string - qr simplex.QuorumRound + qr common.QuorumRound expectedErr bool }{ { name: "empty notarization", - qr: simplex.QuorumRound{ - EmptyNotarization: &simplex.EmptyNotarization{}, + qr: common.QuorumRound{ + EmptyNotarization: &common.EmptyNotarization{}, }, expectedErr: false, }, { name: "all nil", - qr: simplex.QuorumRound{ + qr: common.QuorumRound{ EmptyNotarization: nil, Block: nil, Notarization: nil, @@ -32,71 +32,71 @@ func TestQuorumRoundMalformed(t *testing.T) { expectedErr: true, }, { name: "block and notarization", - qr: simplex.QuorumRound{ + qr: common.QuorumRound{ Block: &testutil.TestBlock{}, - Notarization: &simplex.Notarization{}, + Notarization: &common.Notarization{}, }, expectedErr: false, }, { name: "block and finalization", - qr: simplex.QuorumRound{ + qr: common.QuorumRound{ Block: &testutil.TestBlock{}, - Finalization: &simplex.Finalization{}, + Finalization: &common.Finalization{}, }, expectedErr: false, }, { name: "block and empty notarization", - qr: simplex.QuorumRound{ + qr: common.QuorumRound{ Block: &testutil.TestBlock{}, - EmptyNotarization: &simplex.EmptyNotarization{}, + EmptyNotarization: &common.EmptyNotarization{}, }, expectedErr: true, }, { name: "block and notarization and finalization", - qr: simplex.QuorumRound{ + qr: common.QuorumRound{ Block: &testutil.TestBlock{}, - Notarization: &simplex.Notarization{}, - Finalization: &simplex.Finalization{}, + Notarization: &common.Notarization{}, + Finalization: &common.Finalization{}, }, expectedErr: false, }, { name: "notarization and no block", - qr: simplex.QuorumRound{ - Notarization: &simplex.Notarization{}, + qr: common.QuorumRound{ + Notarization: &common.Notarization{}, }, expectedErr: true, }, { name: "finalization and no block", - qr: simplex.QuorumRound{ - Finalization: &simplex.Finalization{}, + qr: common.QuorumRound{ + Finalization: &common.Finalization{}, }, expectedErr: true, }, { name: "just block", - qr: simplex.QuorumRound{ + qr: common.QuorumRound{ Block: &testutil.TestBlock{}, }, expectedErr: true, }, { name: "block and notarization and empty notarization", - qr: simplex.QuorumRound{ + qr: common.QuorumRound{ Block: &testutil.TestBlock{}, - Notarization: &simplex.Notarization{}, - EmptyNotarization: &simplex.EmptyNotarization{}, + Notarization: &common.Notarization{}, + EmptyNotarization: &common.EmptyNotarization{}, }, expectedErr: false, }, { name: "block and finalization and empty notarization", - qr: simplex.QuorumRound{ + qr: common.QuorumRound{ Block: &testutil.TestBlock{}, - Finalization: &simplex.Finalization{}, - EmptyNotarization: &simplex.EmptyNotarization{}, + Finalization: &common.Finalization{}, + EmptyNotarization: &common.EmptyNotarization{}, }, expectedErr: false, }, diff --git a/notarization.go b/common/notarization.go similarity index 99% rename from notarization.go rename to common/notarization.go index 49a7eaea..8b6cbf7d 100644 --- a/notarization.go +++ b/common/notarization.go @@ -1,7 +1,7 @@ // Copyright (C) 2019-2025, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package simplex +package common import ( "bytes" diff --git a/notarization_test.go b/common/notarization_test.go similarity index 74% rename from notarization_test.go rename to common/notarization_test.go index 2db751f6..e93feffd 100644 --- a/notarization_test.go +++ b/common/notarization_test.go @@ -1,14 +1,14 @@ // Copyright (C) 2019-2025, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package simplex_test +package common_test import ( "bytes" "errors" "testing" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" . "github.com/ava-labs/simplex/testutil" "github.com/stretchr/testify/require" @@ -21,16 +21,16 @@ func TestNewNotarization(t *testing.T) { testBlock := &TestBlock{} tests := []struct { name string - votesForCurrentRound map[string]*simplex.Vote - block simplex.VerifiedBlock + votesForCurrentRound map[string]*common.Vote + block common.VerifiedBlock expectError error - signatureAggregator simplex.SignatureAggregator - expectedSigners []simplex.NodeID + signatureAggregator common.SignatureAggregator + expectedSigners []common.NodeID }{ { name: "valid notarization", - votesForCurrentRound: func() map[string]*simplex.Vote { - votes := make(map[string]*simplex.Vote) + votesForCurrentRound: func() map[string]*common.Vote { + votes := make(map[string]*common.Vote) nodeIds := [][]byte{{1}, {2}, {3}, {4}, {5}} for _, nodeId := range nodeIds { vote, err := NewTestVote(testBlock, nodeId) @@ -42,41 +42,41 @@ func TestNewNotarization(t *testing.T) { block: testBlock, signatureAggregator: &TestSignatureAggregator{N: 5}, expectError: nil, - expectedSigners: []simplex.NodeID{ + expectedSigners: []common.NodeID{ {1}, {2}, {3}, {4}, {5}, }, }, { name: "diverging votes", - votesForCurrentRound: func() map[string]*simplex.Vote { - votes := make(map[string]*simplex.Vote) + votesForCurrentRound: func() map[string]*common.Vote { + votes := make(map[string]*common.Vote) nodeIds := [][]byte{{1}, {2}, {3}, {4}, {5}} for _, nodeId := range nodeIds { vote, err := NewTestVote(testBlock, nodeId) require.NoError(t, err) votes[string(nodeId)] = vote } - votes[string(simplex.NodeID{2})].Vote.Digest[0]++ // Diverging vote + votes[string(common.NodeID{2})].Vote.Digest[0]++ // Diverging vote return votes }(), block: testBlock, signatureAggregator: &TestSignatureAggregator{N: 5}, expectError: nil, - expectedSigners: []simplex.NodeID{ + expectedSigners: []common.NodeID{ {1}, {3}, {4}, {5}, }, }, { name: "no votes", - votesForCurrentRound: map[string]*simplex.Vote{}, + votesForCurrentRound: map[string]*common.Vote{}, block: testBlock, signatureAggregator: &TestSignatureAggregator{N: 5}, - expectError: simplex.ErrorNoVotes, + expectError: common.ErrorNoVotes, }, { name: "error aggregating", - votesForCurrentRound: func() map[string]*simplex.Vote { - votes := make(map[string]*simplex.Vote) + votesForCurrentRound: func() map[string]*common.Vote { + votes := make(map[string]*common.Vote) nodeIds := [][]byte{{1}, {2}, {3}, {4}, {5}} for _, nodeId := range nodeIds { vote, err := NewTestVote(testBlock, nodeId) @@ -93,7 +93,7 @@ func TestNewNotarization(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - notarization, err := simplex.NewNotarization(l, tt.signatureAggregator, tt.votesForCurrentRound, tt.block.BlockHeader()) + notarization, err := common.NewNotarization(l, tt.signatureAggregator, tt.votesForCurrentRound, tt.block.BlockHeader()) require.ErrorIs(t, err, tt.expectError, "expected error, got nil") if tt.expectError == nil { @@ -112,15 +112,15 @@ func TestNewNotarization(t *testing.T) { func TestNewFinalization(t *testing.T) { tests := []struct { name string - finalizeVotes []*simplex.FinalizeVote - signatureAggregator simplex.SignatureAggregator - expectedFinalization *simplex.ToBeSignedFinalization - expectedQC *simplex.QuorumCertificate + finalizeVotes []*common.FinalizeVote + signatureAggregator common.SignatureAggregator + expectedFinalization *common.ToBeSignedFinalization + expectedQC *common.QuorumCertificate expectError error }{ { name: "valid finalizations in order", - finalizeVotes: []*simplex.FinalizeVote{ + finalizeVotes: []*common.FinalizeVote{ NewTestFinalizeVote(t, &TestBlock{}, []byte{1}), NewTestFinalizeVote(t, &TestBlock{}, []byte{2}), NewTestFinalizeVote(t, &TestBlock{}, []byte{3}), @@ -131,7 +131,7 @@ func TestNewFinalization(t *testing.T) { }, { name: "unsorted finalizations", - finalizeVotes: []*simplex.FinalizeVote{ + finalizeVotes: []*common.FinalizeVote{ NewTestFinalizeVote(t, &TestBlock{}, []byte{3}), NewTestFinalizeVote(t, &TestBlock{}, []byte{1}), NewTestFinalizeVote(t, &TestBlock{}, []byte{2}), @@ -142,17 +142,17 @@ func TestNewFinalization(t *testing.T) { }, { name: "finalizations with different digests", - finalizeVotes: []*simplex.FinalizeVote{ + finalizeVotes: []*common.FinalizeVote{ NewTestFinalizeVote(t, &TestBlock{Digest: [32]byte{1}}, []byte{1}), NewTestFinalizeVote(t, &TestBlock{Digest: [32]byte{2}}, []byte{2}), NewTestFinalizeVote(t, &TestBlock{Digest: [32]byte{3}}, []byte{3}), }, signatureAggregator: &TestSignatureAggregator{N: 4}, - expectError: simplex.ErrorInvalidFinalizationDigest, + expectError: common.ErrorInvalidFinalizationDigest, }, { name: "signature aggregator errors", - finalizeVotes: []*simplex.FinalizeVote{ + finalizeVotes: []*common.FinalizeVote{ NewTestFinalizeVote(t, &TestBlock{}, []byte{1}), }, signatureAggregator: &TestSignatureAggregator{Err: errorSigAggregation, N: 4}, @@ -160,15 +160,15 @@ func TestNewFinalization(t *testing.T) { }, { name: "no votes", - finalizeVotes: []*simplex.FinalizeVote{}, + finalizeVotes: []*common.FinalizeVote{}, signatureAggregator: &TestSignatureAggregator{N: 4}, - expectError: simplex.ErrorNoVotes, + expectError: common.ErrorNoVotes, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - finalization, err := simplex.NewFinalization(tt.signatureAggregator, tt.finalizeVotes) + finalization, err := common.NewFinalization(tt.signatureAggregator, tt.finalizeVotes) require.ErrorIs(t, err, tt.expectError, "expected error, got nil") if tt.expectError == nil { diff --git a/msm/approvals.go b/msm/approvals.go index 436fe82f..566ba409 100644 --- a/msm/approvals.go +++ b/msm/approvals.go @@ -8,7 +8,7 @@ import ( "encoding/binary" "fmt" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" "go.uber.org/zap" ) @@ -22,13 +22,13 @@ type approvalAndTimestamp struct { type ApprovalStore struct { signatureVerifier SignatureVerifier validators NodeBLSMappings - logger simplex.Logger + logger common.Logger pkByNodeID map[nodeID][]byte approvalsByNodes map[nodeID]approvalsByPChainHeight storedCount int } -func NewApprovalStore(signatureVerifier SignatureVerifier, validators NodeBLSMappings, logger simplex.Logger) *ApprovalStore { +func NewApprovalStore(signatureVerifier SignatureVerifier, validators NodeBLSMappings, logger common.Logger) *ApprovalStore { pkByNodeID := make(map[nodeID][]byte) for _, vdr := range validators { pkByNodeID[vdr.NodeID] = vdr.BLSKey @@ -127,7 +127,7 @@ func (as *ApprovalStore) checkApprovalSignature(approval *ValidatorSetApproval, pChainHeightBuff := make([]byte, 8) binary.BigEndian.PutUint64(pChainHeightBuff, pChainHeight) - signedMsg := simplex.SignedMessage{Payload: pChainHeightBuff, Context: signatureContext} + signedMsg := common.SignedMessage{Payload: pChainHeightBuff, Context: signatureContext} toBeSigned, err := asn1.Marshal(signedMsg) if err != nil { return err diff --git a/msm/build_decision.go b/msm/build_decision.go index f0786114..cfac2d98 100644 --- a/msm/build_decision.go +++ b/msm/build_decision.go @@ -8,7 +8,7 @@ import ( "sync" "time" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" "go.uber.org/zap" ) @@ -27,7 +27,7 @@ type PChainProgressListener interface { } type blockBuildingDecider struct { - logger simplex.Logger + logger common.Logger maxBlockBuildingWaitTime time.Duration pChainListener PChainProgressListener waitForPendingBlock func(ctx context.Context) diff --git a/msm/encoding.go b/msm/encoding.go index f832e89d..866dbbce 100644 --- a/msm/encoding.go +++ b/msm/encoding.go @@ -7,7 +7,7 @@ import ( "bytes" "slices" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" ) //go:generate go run github.com/StephenButtolph/canoto/canoto encoding.go @@ -255,10 +255,10 @@ func (nea *NextEpochApprovals) Equals(other *NextEpochApprovals) bool { type NodeBLSMappings []NodeBLSMapping -func (nbms NodeBLSMappings) NodeWeights() simplex.Nodes { - nodeWeights := make(simplex.Nodes, len(nbms)) +func (nbms NodeBLSMappings) NodeWeights() common.Nodes { + nodeWeights := make(common.Nodes, len(nbms)) for i, nbm := range nbms { - nodeWeights[i] = simplex.Node{ + nodeWeights[i] = common.Node{ Node: nbm.NodeID[:], Weight: nbm.Weight, } @@ -276,8 +276,8 @@ func (nbms NodeBLSMappings) IndexByNodeID() map[nodeID]int { return result } -func (nbms NodeBLSMappings) SelectSubset(bitmask bitmask) []simplex.NodeID { - nodeIDs := make([]simplex.NodeID, 0, len(nbms)) +func (nbms NodeBLSMappings) SelectSubset(bitmask bitmask) []common.NodeID { + nodeIDs := make([]common.NodeID, 0, len(nbms)) for i, nbm := range nbms { if !bitmask.Contains(i) { continue @@ -331,7 +331,7 @@ type ValidatorSetApproval struct { type ValidatorSetApprovals []ValidatorSetApproval -func (vsa ValidatorSetApprovals) Filter(f func(ValidatorSetApproval, simplex.Logger) bool, logger simplex.Logger) ValidatorSetApprovals { +func (vsa ValidatorSetApprovals) Filter(f func(ValidatorSetApproval, common.Logger) bool, logger common.Logger) ValidatorSetApprovals { result := make(ValidatorSetApprovals, 0, len(vsa)) for _, v := range vsa { if f(v, logger) { diff --git a/msm/encoding_test.go b/msm/encoding_test.go index ef259503..23267afb 100644 --- a/msm/encoding_test.go +++ b/msm/encoding_test.go @@ -6,7 +6,7 @@ package metadata import ( "testing" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" "github.com/ava-labs/simplex/testutil" "github.com/stretchr/testify/require" ) @@ -411,7 +411,7 @@ func TestValidatorSetApprovalsFilter(t *testing.T) { {NodeID: nodeID{3}, PChainHeight: 30}, } - filtered := approvals.Filter(func(v ValidatorSetApproval, _ simplex.Logger) bool { + filtered := approvals.Filter(func(v ValidatorSetApproval, _ common.Logger) bool { return v.PChainHeight > 15 }, logger) require.Len(t, filtered, 2) @@ -419,7 +419,7 @@ func TestValidatorSetApprovalsFilter(t *testing.T) { require.Equal(t, uint64(30), filtered[1].PChainHeight) // Filter all - filtered = approvals.Filter(func(ValidatorSetApproval, simplex.Logger) bool { + filtered = approvals.Filter(func(ValidatorSetApproval, common.Logger) bool { return false }, logger) require.Empty(t, filtered) diff --git a/msm/fake_node_test.go b/msm/fake_node_test.go index 7740a34c..3b68139e 100644 --- a/msm/fake_node_test.go +++ b/msm/fake_node_test.go @@ -11,7 +11,7 @@ import ( "testing" "time" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" "github.com/stretchr/testify/require" ) @@ -271,23 +271,23 @@ func newFakeNode(t *testing.T) *fakeNode { fn.sm.BlockBuilder = fn fn.sm.PChainProgressListener = fn - fn.sm.GetBlock = func(seq uint64, digest [32]byte) (StateMachineBlock, *simplex.Finalization, error) { + fn.sm.GetBlock = func(seq uint64, digest [32]byte) (StateMachineBlock, *common.Finalization, error) { if seq == 0 { return genesisBlock, nil, nil } for _, bs := range fn.blocks { match := bs.block.Digest() == digest if !match { - md, err := simplex.ProtocolMetadataFromBytes(bs.block.Metadata.SimplexProtocolMetadata) + md, err := common.ProtocolMetadataFromBytes(bs.block.Metadata.SimplexProtocolMetadata) if err != nil { return StateMachineBlock{}, nil, err } match = md.Seq == seq } if match { - var fin *simplex.Finalization + var fin *common.Finalization if bs.finalized { - fin = &simplex.Finalization{} + fin = &common.Finalization{} } return bs.block, fin, nil } @@ -361,7 +361,7 @@ func (fn *fakeNode) tryFinalizeNextBlock() { fn.blocks[nextIndex].finalized = true block := fn.blocks[nextIndex].block - md, err := simplex.ProtocolMetadataFromBytes(block.Metadata.SimplexProtocolMetadata) + md, err := common.ProtocolMetadataFromBytes(block.Metadata.SimplexProtocolMetadata) require.NoError(fn.t, err) fn.sm.LatestPersistedHeight = md.Seq @@ -414,7 +414,7 @@ func (fn *fakeNode) buildBlock() (VMBlock, *StateMachineBlock) { fn.t.Logf("Building a block on top of %s parent with epoch %d", finalizedString, parentBlock.Metadata.SimplexEpochInfo.EpochNumber) - block, err := fn.sm.BuildBlock(context.Background(), simplex.ProtocolMetadata{ + block, err := fn.sm.BuildBlock(context.Background(), common.ProtocolMetadata{ Seq: lastMD.Seq + 1, Round: lastMD.Round + 1, Epoch: fn.epoch, @@ -425,17 +425,17 @@ func (fn *fakeNode) buildBlock() (VMBlock, *StateMachineBlock) { return block.InnerBlock, block } -func (fn *fakeNode) prepareMetadataAndPrevBlockDigest() (*simplex.ProtocolMetadata, [32]byte) { - var lastMD *simplex.ProtocolMetadata +func (fn *fakeNode) prepareMetadataAndPrevBlockDigest() (*common.ProtocolMetadata, [32]byte) { + var lastMD *common.ProtocolMetadata var err error lastBlockDigest := genesisBlock.Digest() if len(fn.blocks) > 0 { lastBlock := fn.blocks[len(fn.blocks)-1].block lastBlockDigest = lastBlock.Digest() - lastMD, err = simplex.ProtocolMetadataFromBytes(lastBlock.Metadata.SimplexProtocolMetadata) + lastMD, err = common.ProtocolMetadataFromBytes(lastBlock.Metadata.SimplexProtocolMetadata) require.NoError(fn.t, err) } else { - lastMD = &simplex.ProtocolMetadata{ + lastMD = &common.ProtocolMetadata{ Prev: lastBlockDigest, Epoch: 1, } diff --git a/msm/fuzz_test.go b/msm/fuzz_test.go index 90031f8a..cc5b211f 100644 --- a/msm/fuzz_test.go +++ b/msm/fuzz_test.go @@ -9,7 +9,7 @@ import ( "testing" "time" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" "github.com/stretchr/testify/require" "go.uber.org/zap" ) @@ -145,7 +145,7 @@ func cloneBlock(t *testing.T, b *StateMachineBlock) *StateMachineBlock { // block6: sealing block, built while collecting the quorum approval (epoch 1) // block7: stateBuildBlockEpochSealed -> first block of epoch 2 // block8: stateBuildBlockNormalOp (epoch 2) -func buildEpochChain(tb testing.TB, logger simplex.Logger) ([]*StateMachineBlock, *StateMachine) { +func buildEpochChain(tb testing.TB, logger common.Logger) ([]*StateMachineBlock, *StateMachine) { node1 := [20]byte{1} node2 := [20]byte{2} node3 := [20]byte{3} @@ -196,7 +196,7 @@ func buildEpochChain(tb testing.TB, logger simplex.Logger) ([]*StateMachineBlock ctx := context.Background() - addBlock := func(seq uint64, b *StateMachineBlock, fin *simplex.Finalization) { + addBlock := func(seq uint64, b *StateMachineBlock, fin *common.Finalization) { tc.blockStore[seq] = &outerBlock{block: *b, finalization: fin} } nextInner := func(h uint64) *InnerBlock { @@ -213,7 +213,7 @@ func buildEpochChain(tb testing.TB, logger simplex.Logger) ([]*StateMachineBlock } else { prevDigest = genesis.Digest() } - md := simplex.ProtocolMetadata{Seq: seq, Round: round, Epoch: epoch, Prev: prevDigest} + md := common.ProtocolMetadata{Seq: seq, Round: round, Epoch: epoch, Prev: prevDigest} block, err := sm.BuildBlock(ctx, md, nil) require.NoError(tb, err) return block @@ -225,7 +225,7 @@ func buildEpochChain(tb testing.TB, logger simplex.Logger) ([]*StateMachineBlock // the validator-set change and the sealing-block computation. tc.blockBuilder.block = nextInner(1) block1 := build(1, 0, 1, nil) - addBlock(1, block1, &simplex.Finalization{}) + addBlock(1, block1, &common.Finalization{}) sm.LatestPersistedHeight = 1 // block2: a normal in-epoch block. @@ -262,7 +262,7 @@ func buildEpochChain(tb testing.TB, logger simplex.Logger) ([]*StateMachineBlock block6 := build(6, 5, 1, block5) require.Equal(tb, stateBuildBlockEpochSealed, block6.Metadata.SimplexEpochInfo.NextState()) // Finalize the sealing block so the epoch transition can proceed. - addBlock(6, block6, &simplex.Finalization{}) + addBlock(6, block6, &common.Finalization{}) // ----- Epoch 2 (its epoch number is the sealing block's sequence, 6) ----- diff --git a/msm/msm.go b/msm/msm.go index 872acb49..ed1b27c6 100644 --- a/msm/msm.go +++ b/msm/msm.go @@ -13,7 +13,7 @@ import ( "math" "time" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" "go.uber.org/zap" ) @@ -151,7 +151,7 @@ type ValidatorSetRetriever func(pChainHeight uint64) (NodeBLSMappings, error) // BlockRetriever retrieves a block and its finalization status given the block's sequence number and expected digest. // If the block cannot be found it returns ErrBlockNotFound. // If an error occurs during retrieval, it returns a non-nil error. -type BlockRetriever func(seq uint64, digest [32]byte) (StateMachineBlock, *simplex.Finalization, error) +type BlockRetriever func(seq uint64, digest [32]byte) (StateMachineBlock, *common.Finalization, error) // BlockBuilder builds a new VM block with the given observed P-chain height. type BlockBuilder interface { @@ -193,7 +193,7 @@ type Config struct { // BlockBuilder builds new VM blocks. BlockBuilder BlockBuilder // Logger is used for logging state machine operations. - Logger simplex.Logger + Logger common.Logger // GetValidatorSet retrieves the validator set at a given P-chain height. GetValidatorSet ValidatorSetRetriever // GetBlock retrieves a previously built or finalized block. @@ -201,7 +201,7 @@ type Config struct { // ApprovalsRetriever retrieves validator approvals for epoch transitions. ApprovalsRetriever ApprovalsRetriever // SignatureAggregatorCreator creates a new SignatureAggregator for aggregating validator signatures for epoch transitions. - SignatureAggregatorCreator simplex.SignatureAggregatorCreator + SignatureAggregatorCreator common.SignatureAggregatorCreator // KeyAggregator aggregates public keys from validators. KeyAggregator KeyAggregator // SignatureVerifier verifies signatures from validators. @@ -216,9 +216,9 @@ type Config struct { // GenesisValidatorSet is the validator set used for the genesis block. GenesisValidatorSet NodeBLSMappings // MyNodeID - MyNodeID simplex.NodeID + MyNodeID common.NodeID // Signer - Signer simplex.Signer + Signer common.Signer // ComputeICMEpoch computes the ICM epoch information in order to know which P-chain height to encode. ComputeICMEpoch ICMEpochTransition } @@ -245,7 +245,7 @@ func NewStateMachine(config *Config) (*StateMachine, error) { } // BuildBlock constructs the next block on top of the given parent block, and passes in the provided simplex metadata and blacklist. -func (sm *StateMachine) BuildBlock(ctx context.Context, metadata simplex.ProtocolMetadata, blacklist *simplex.Blacklist) (*StateMachineBlock, error) { +func (sm *StateMachine) BuildBlock(ctx context.Context, metadata common.ProtocolMetadata, blacklist *common.Blacklist) (*StateMachineBlock, error) { // The zero sequence number is reserved for the genesis block, which should never be built. if metadata.Seq == 0 { return nil, fmt.Errorf("%w: got %d", errInvalidProtocolMetadataSeq, metadata.Seq) @@ -307,7 +307,7 @@ func (sm *StateMachine) VerifyBlock(ctx context.Context, block *StateMachineBloc return errNilBlock } - pmd, err := simplex.ProtocolMetadataFromBytes(block.Metadata.SimplexProtocolMetadata) + pmd, err := common.ProtocolMetadataFromBytes(block.Metadata.SimplexProtocolMetadata) if err != nil { return fmt.Errorf("failed to parse ProtocolMetadata: %w", err) } @@ -388,7 +388,7 @@ func verifyTimestamp(block *StateMachineBlock, prevBlock *StateMachineBlock, now } func (sm *StateMachine) verifyEpochNumber(block *StateMachineBlock) error { - md, err := simplex.ProtocolMetadataFromBytes(block.Metadata.SimplexProtocolMetadata) + md, err := common.ProtocolMetadataFromBytes(block.Metadata.SimplexProtocolMetadata) if err != nil { return fmt.Errorf("failed to parse ProtocolMetadata: %w", err) } @@ -739,7 +739,7 @@ func (sm *StateMachine) buildBlockZero(parentBlock StateMachineBlock, simplexMet timestamp := sm.LastNonSimplexInnerBlock.Timestamp().UnixMilli() simplexEpochInfo := constructSimplexZeroBlockSimplexEpochInfo(pChainHeight, validatorSet, prevVMBlockSeq) - md, err := simplex.ProtocolMetadataFromBytes(simplexMetadata) + md, err := common.ProtocolMetadataFromBytes(simplexMetadata) if err != nil { return nil, fmt.Errorf("failed to parse simplex metadata: %w", err) } @@ -940,7 +940,7 @@ func (sm *StateMachine) verifyNextEpochApprovalsSignature(prev SimplexEpochInfo, pChainHeightBuff := make([]byte, 8) binary.BigEndian.PutUint64(pChainHeightBuff, pChainHeight) - signedMsg := simplex.SignedMessage{Payload: pChainHeightBuff, Context: signatureContext} + signedMsg := common.SignedMessage{Payload: pChainHeightBuff, Context: signatureContext} toBeSigned, err := asn1.Marshal(signedMsg) if err != nil { return err @@ -1261,9 +1261,9 @@ func computeNewApprovals( prevNextEpochApprovals *NextEpochApprovals, approvalsFromPeers ValidatorSetApprovals, pChainHeight uint64, - sigAggr simplex.SignatureAggregator, + sigAggr common.SignatureAggregator, validators NodeBLSMappings, - logger simplex.Logger, + logger common.Logger, ) (*approvals, error) { if prevNextEpochApprovals == nil { prevNextEpochApprovals = &NextEpochApprovals{} @@ -1304,8 +1304,8 @@ func computeNewApproverSignaturesAndSigners( approvalsFromPeers ValidatorSetApprovals, oldApprovingNodes bitmask, nodeID2ValidatorIndex map[nodeID]int, - sigAggr simplex.SignatureAggregator, - logger simplex.Logger, + sigAggr common.SignatureAggregator, + logger common.Logger, ) ([]byte, bitmask, error) { if nextEpochApprovals == nil { return nil, bitmask{}, errEmptyNextEpochApprovals @@ -1352,14 +1352,14 @@ func computeNewApproverSignaturesAndSigners( // sanitizeApprovals filters out approvals that are not valid by checking if they agree with our candidate auxiliary info digest and P-Chain height, // and if they are from the validator set and haven't already been approved. -func sanitizeApprovals(approvals ValidatorSetApprovals, pChainHeight uint64, nodeID2ValidatorIndex map[nodeID]int, oldApprovingNodes bitmask, logger simplex.Logger) ValidatorSetApprovals { +func sanitizeApprovals(approvals ValidatorSetApprovals, pChainHeight uint64, nodeID2ValidatorIndex map[nodeID]int, oldApprovingNodes bitmask, logger common.Logger) ValidatorSetApprovals { filter1 := approvalsThatAgreeWithPChainHeight(pChainHeight) filter2 := approvalsThatAreInValidatorSetAndHaveNotAlreadyApproved(oldApprovingNodes.Clone(), nodeID2ValidatorIndex) return approvals.Filter(filter1, logger).Filter(filter2, logger).UniqueByNodeID() } -func approvalsThatAgreeWithPChainHeight(pChainHeight uint64) func(approval ValidatorSetApproval, logger simplex.Logger) bool { - return func(approval ValidatorSetApproval, logger simplex.Logger) bool { +func approvalsThatAgreeWithPChainHeight(pChainHeight uint64) func(approval ValidatorSetApproval, logger common.Logger) bool { + return func(approval ValidatorSetApproval, logger common.Logger) bool { // Pick only approvals that agree with our P-Chain height ok := approval.PChainHeight == pChainHeight if !ok { @@ -1372,8 +1372,8 @@ func approvalsThatAgreeWithPChainHeight(pChainHeight uint64) func(approval Valid } } -func approvalsThatAreInValidatorSetAndHaveNotAlreadyApproved(oldApprovingNodes bitmask, nodeID2ValidatorIndex map[nodeID]int) func(approval ValidatorSetApproval, logger simplex.Logger) bool { - return func(approval ValidatorSetApproval, logger simplex.Logger) bool { +func approvalsThatAreInValidatorSetAndHaveNotAlreadyApproved(oldApprovingNodes bitmask, nodeID2ValidatorIndex map[nodeID]int) func(approval ValidatorSetApproval, logger common.Logger) bool { + return func(approval ValidatorSetApproval, logger common.Logger) bool { approvingNodeIndexOfNewApprover, exists := nodeID2ValidatorIndex[approval.NodeID] if !exists { logger.Debug("Filtering out approval from node that is not in the validator set", diff --git a/msm/msm_test.go b/msm/msm_test.go index 90ef0146..1d569af7 100644 --- a/msm/msm_test.go +++ b/msm/msm_test.go @@ -11,13 +11,13 @@ import ( "testing" "time" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" "github.com/ava-labs/simplex/testutil" "github.com/stretchr/testify/require" ) func TestMSMBuildAndVerifyBlocksAfterGenesis(t *testing.T) { - validMD := simplex.ProtocolMetadata{ + validMD := common.ProtocolMetadata{ Round: 1, Seq: 1, Epoch: 1, @@ -26,7 +26,7 @@ func TestMSMBuildAndVerifyBlocksAfterGenesis(t *testing.T) { for _, testCase := range []struct { name string - md simplex.ProtocolMetadata + md common.ProtocolMetadata err error configure func(*StateMachine, *testConfig) mutateBlock func(*StateMachineBlock) @@ -39,7 +39,7 @@ func TestMSMBuildAndVerifyBlocksAfterGenesis(t *testing.T) { name: "verifying a genesis block", md: validMD, mutateBlock: func(block *StateMachineBlock) { - md, err := simplex.ProtocolMetadataFromBytes(block.Metadata.SimplexProtocolMetadata) + md, err := common.ProtocolMetadataFromBytes(block.Metadata.SimplexProtocolMetadata) require.NoError(t, err) md.Seq = 0 block.Metadata.SimplexProtocolMetadata = md.Bytes() @@ -52,7 +52,7 @@ func TestMSMBuildAndVerifyBlocksAfterGenesis(t *testing.T) { configure: func(_ *StateMachine, tc *testConfig) { delete(tc.blockStore, 0) }, - err: simplex.ErrBlockNotFound, + err: common.ErrBlockNotFound, }, { name: "parent has no inner block", @@ -159,7 +159,7 @@ func TestMSMFirstSimplexBlockAfterPreSimplexBlocks(t *testing.T) { }, } - md := simplex.ProtocolMetadata{ + md := common.ProtocolMetadata{ Round: 0, Seq: 43, Epoch: 43, @@ -218,7 +218,7 @@ func TestMSMBuildBlockRejectsZeroSeq(t *testing.T) { // Seq 0 is reserved for the genesis block, which should never be built. sm, _ := newStateMachine(t) - block, err := sm.BuildBlock(context.Background(), simplex.ProtocolMetadata{Seq: 0}, nil) + block, err := sm.BuildBlock(context.Background(), common.ProtocolMetadata{Seq: 0}, nil) require.ErrorIs(t, err, errInvalidProtocolMetadataSeq) require.Nil(t, block) } @@ -246,7 +246,7 @@ func TestMSMNormalOp(t *testing.T) { { name: "trying to build a genesis block", mutateBlock: func(block *StateMachineBlock) { - md, err := simplex.ProtocolMetadataFromBytes(block.Metadata.SimplexProtocolMetadata) + md, err := common.ProtocolMetadataFromBytes(block.Metadata.SimplexProtocolMetadata) require.NoError(t, err) md.Seq = 0 block.Metadata.SimplexProtocolMetadata = md.Bytes() @@ -256,12 +256,12 @@ func TestMSMNormalOp(t *testing.T) { { name: "previous block not found", mutateBlock: func(block *StateMachineBlock) { - md, err := simplex.ProtocolMetadataFromBytes(block.Metadata.SimplexProtocolMetadata) + md, err := common.ProtocolMetadataFromBytes(block.Metadata.SimplexProtocolMetadata) require.NoError(t, err) md.Seq = 999 block.Metadata.SimplexProtocolMetadata = md.Bytes() }, - err: simplex.ErrBlockNotFound, + err: common.ErrBlockNotFound, }, { name: "P-chain height too big", @@ -338,19 +338,19 @@ func TestMSMNormalOp(t *testing.T) { sm2, testConfig2 := newStateMachine(t) for i, block := range chain { - testConfig1.blockStore[uint64(i)] = &outerBlock{block: block, finalization: &simplex.Finalization{}} - testConfig2.blockStore[uint64(i)] = &outerBlock{block: block, finalization: &simplex.Finalization{}} + testConfig1.blockStore[uint64(i)] = &outerBlock{block: block, finalization: &common.Finalization{}} + testConfig2.blockStore[uint64(i)] = &outerBlock{block: block, finalization: &common.Finalization{}} } lastBlock := chain[len(chain)-1] - md, err := simplex.ProtocolMetadataFromBytes(lastBlock.Metadata.SimplexProtocolMetadata) + md, err := common.ProtocolMetadataFromBytes(lastBlock.Metadata.SimplexProtocolMetadata) require.NoError(t, err) md.Seq++ md.Round++ md.Prev = lastBlock.Digest() - var blacklist simplex.Blacklist + var blacklist common.Blacklist blacklist.NodeCount = 4 blockTime := lastBlock.InnerBlock.Timestamp().Add(time.Second) @@ -560,7 +560,7 @@ func TestMSMFullEpochLifecycle(t *testing.T) { smVerify.LastNonSimplexBlockPChainHeight = pChainHeight1 // addBlock adds a block to both block stores so builder and verifier stay in sync. - addBlock := func(seq uint64, block StateMachineBlock, fin *simplex.Finalization) { + addBlock := func(seq uint64, block StateMachineBlock, fin *common.Finalization) { tc.blockStore[seq] = &outerBlock{block: block, finalization: fin} tcVerify.blockStore[seq] = &outerBlock{block: block, finalization: fin} } @@ -572,7 +572,7 @@ func TestMSMFullEpochLifecycle(t *testing.T) { // ----- Step 1: Build zero epoch block (first simplex block) ----- tc.blockBuilder.block = nextBlock(1) - md := simplex.ProtocolMetadata{ + md := common.ProtocolMetadata{ Seq: baseSeq + 1, Round: 0, Epoch: testCase.epochNum, @@ -601,7 +601,7 @@ func TestMSMFullEpochLifecycle(t *testing.T) { ICMEpochInfo: testCase.firstBlockICMEpochInfo, }, }, block1) - addBlock(md.Seq, *block1, &simplex.Finalization{}) + addBlock(md.Seq, *block1, &common.Finalization{}) require.NoError(t, smVerify.VerifyBlock(context.Background(), block1)) @@ -612,7 +612,7 @@ func TestMSMFullEpochLifecycle(t *testing.T) { // ----- Step 2: Build a normal block (no validator set change) ----- currentTime = startTime.Add(2 * time.Millisecond) tc.blockBuilder.block = nextBlock(2) - md = simplex.ProtocolMetadata{Seq: baseSeq + 2, Round: 1, Epoch: testCase.epochNum, Prev: block1.Digest()} + md = common.ProtocolMetadata{Seq: baseSeq + 2, Round: 1, Epoch: testCase.epochNum, Prev: block1.Digest()} block2, err := sm.BuildBlock(context.Background(), md, nil) require.NoError(t, err) require.Equal(t, &StateMachineBlock{ @@ -642,7 +642,7 @@ func TestMSMFullEpochLifecycle(t *testing.T) { // epochStart + 1s and transitions ICM to epoch 2. currentTime = startTime.Add(time.Second + 3*time.Millisecond) tc.blockBuilder.block = nextBlock(3) - md = simplex.ProtocolMetadata{Seq: baseSeq + 3, Round: 2, Epoch: testCase.epochNum, Prev: block2.Digest()} + md = common.ProtocolMetadata{Seq: baseSeq + 3, Round: 2, Epoch: testCase.epochNum, Prev: block2.Digest()} block3, err := sm.BuildBlock(context.Background(), md, nil) require.NoError(t, err) require.Equal(t, &StateMachineBlock{ @@ -685,7 +685,7 @@ func TestMSMFullEpochLifecycle(t *testing.T) { currentTime = startTime.Add(time.Second + 4*time.Millisecond) tc.blockBuilder.block = nextBlock(4) - md = simplex.ProtocolMetadata{Seq: baseSeq + 4, Round: 3, Epoch: testCase.epochNum, Prev: block3.Digest()} + md = common.ProtocolMetadata{Seq: baseSeq + 4, Round: 3, Epoch: testCase.epochNum, Prev: block3.Digest()} block4, err := sm.BuildBlock(context.Background(), md, nil) require.NoError(t, err) require.Equal(t, &StateMachineBlock{ @@ -727,7 +727,7 @@ func TestMSMFullEpochLifecycle(t *testing.T) { currentTime = startTime.Add(time.Second + 5*time.Millisecond) tc.blockBuilder.block = nextBlock(5) - md = simplex.ProtocolMetadata{Seq: baseSeq + 5, Round: 4, Epoch: testCase.epochNum, Prev: block4.Digest()} + md = common.ProtocolMetadata{Seq: baseSeq + 5, Round: 4, Epoch: testCase.epochNum, Prev: block4.Digest()} block5, err := sm.BuildBlock(context.Background(), md, nil) require.NoError(t, err) require.Equal(t, &StateMachineBlock{ @@ -769,7 +769,7 @@ func TestMSMFullEpochLifecycle(t *testing.T) { currentTime = startTime.Add(time.Second + 6*time.Millisecond) tc.blockBuilder.block = nextBlock(6) - md = simplex.ProtocolMetadata{Seq: baseSeq + 6, Round: 5, Epoch: testCase.epochNum, Prev: block5.Digest()} + md = common.ProtocolMetadata{Seq: baseSeq + 6, Round: 5, Epoch: testCase.epochNum, Prev: block5.Digest()} block6, err := sm.BuildBlock(context.Background(), md, nil) require.NoError(t, err) require.Equal(t, &StateMachineBlock{ @@ -820,7 +820,7 @@ func TestMSMFullEpochLifecycle(t *testing.T) { { name: "sealing block immediately finalized", setup: func() { - addBlock(sealingSeq, tc.blockStore[sealingSeq].block, &simplex.Finalization{}) + addBlock(sealingSeq, tc.blockStore[sealingSeq].block, &common.Finalization{}) }, }, } { @@ -834,7 +834,7 @@ func TestMSMFullEpochLifecycle(t *testing.T) { subTestCase.setup() tc.blockBuilder.block = nextBlock(7) - md = simplex.ProtocolMetadata{Seq: baseSeq + 7, Round: 6, Epoch: testCase.epochNum, Prev: block6.Digest()} + md = common.ProtocolMetadata{Seq: baseSeq + 7, Round: 6, Epoch: testCase.epochNum, Prev: block6.Digest()} // If the sealing block isn't finalized yet, we expect to build a Telock. // However, despite the fact that the block builder is willing to build a new block, @@ -863,7 +863,7 @@ func TestMSMFullEpochLifecycle(t *testing.T) { }, telock) // Next, finalize the sealing block after we have built a Telock. - addBlock(sealingSeq, tc.blockStore[sealingSeq].block, &simplex.Finalization{}) + addBlock(sealingSeq, tc.blockStore[sealingSeq].block, &common.Finalization{}) } // ----- Step 7: Build a new epoch block (sealing block is finalized) ----- @@ -1024,7 +1024,7 @@ func TestVerifyNextPChainRefHeightNormal(t *testing.T) { next: SimplexEpochInfo{NextPChainReferenceHeight: nextPChainRefHeight}, setup: func(tc *testConfig) { withChangedValidatorSet(tc) - tc.blockStore[sealingBlockSeq] = &outerBlock{finalization: &simplex.Finalization{}} + tc.blockStore[sealingBlockSeq] = &outerBlock{finalization: &common.Finalization{}} }, }, { @@ -1043,7 +1043,7 @@ func TestVerifyNextPChainRefHeightNormal(t *testing.T) { withChangedValidatorSet(tc) delete(tc.blockStore, sealingBlockSeq) }, - err: simplex.ErrBlockNotFound, + err: common.ErrBlockNotFound, }, } @@ -1425,7 +1425,7 @@ func TestBuildBlockCollectingApprovalsDedupsOwnApprovalAcrossRounds(t *testing.T // Use concatAggregator so that AppendSignatures(existing) with zero new // signatures returns `existing` verbatim. This makes signature equality // a direct witness that no new signature was aggregated in. - sm.SignatureAggregatorCreator = func(_ []simplex.Node) simplex.SignatureAggregator { + sm.SignatureAggregatorCreator = func(_ []common.Node) common.SignatureAggregator { return concatAggregator{} } @@ -1452,7 +1452,7 @@ func TestBuildBlockCollectingApprovalsDedupsOwnApprovalAcrossRounds(t *testing.T InnerBlock: &InnerBlock{TS: time.Now(), BlockHeight: 1, Bytes: []byte{0xAA}}, Metadata: StateMachineMetadata{ PChainHeight: 200, - SimplexProtocolMetadata: (&simplex.ProtocolMetadata{ + SimplexProtocolMetadata: (&common.ProtocolMetadata{ Seq: parentSeq, Round: 5, Epoch: 1, }).Bytes(), SimplexEpochInfo: SimplexEpochInfo{ @@ -1467,7 +1467,7 @@ func TestBuildBlockCollectingApprovalsDedupsOwnApprovalAcrossRounds(t *testing.T // ----- Round 1: first collecting-approvals block ----- tc.blockBuilder.block = &InnerBlock{TS: time.Now(), BlockHeight: 2, Bytes: []byte{0x01}} - md1 := simplex.ProtocolMetadata{Seq: parentSeq + 1, Round: 6, Epoch: 1, Prev: parent.Digest()} + md1 := common.ProtocolMetadata{Seq: parentSeq + 1, Round: 6, Epoch: 1, Prev: parent.Digest()} block1, err := sm.BuildBlock(context.Background(), md1, nil) require.NoError(t, err) require.NotNil(t, block1.Metadata.SimplexEpochInfo.NextEpochApprovals, @@ -1483,7 +1483,7 @@ func TestBuildBlockCollectingApprovalsDedupsOwnApprovalAcrossRounds(t *testing.T // ----- Round 2: another collecting-approvals block, still no peer approvals ----- tc.blockBuilder.block = &InnerBlock{TS: time.Now(), BlockHeight: 3, Bytes: []byte{0x02}} - md2 := simplex.ProtocolMetadata{Seq: md1.Seq + 1, Round: 7, Epoch: 1, Prev: block1.Digest()} + md2 := common.ProtocolMetadata{Seq: md1.Seq + 1, Round: 7, Epoch: 1, Prev: block1.Digest()} block2, err := sm.BuildBlock(context.Background(), md2, nil) require.NoError(t, err) require.NotNil(t, block2.Metadata.SimplexEpochInfo.NextEpochApprovals) diff --git a/msm/util_test.go b/msm/util_test.go index 4675b600..eeb306de 100644 --- a/msm/util_test.go +++ b/msm/util_test.go @@ -15,7 +15,7 @@ import ( "testing" "time" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" "github.com/ava-labs/simplex/testutil" "github.com/stretchr/testify/require" ) @@ -55,7 +55,7 @@ func (f *fakeVMBlock) Timestamp() time.Time { return time.Ti func (f *fakeVMBlock) Verify(_ context.Context, _ uint64) error { return nil } type outerBlock struct { - finalization *simplex.Finalization + finalization *common.Finalization block StateMachineBlock } @@ -67,10 +67,10 @@ func (bs blockStore) clone() blockStore { return newStore } -func (bs blockStore) getBlock(seq uint64, _ [32]byte) (StateMachineBlock, *simplex.Finalization, error) { +func (bs blockStore) getBlock(seq uint64, _ [32]byte) (StateMachineBlock, *common.Finalization, error) { blk, exits := bs[seq] if !exits { - return StateMachineBlock{}, nil, fmt.Errorf("%w: block %d not found", simplex.ErrBlockNotFound, seq) + return StateMachineBlock{}, nil, fmt.Errorf("%w: block %d not found", common.ErrBlockNotFound, seq) } return blk.block, blk.finalization, nil } @@ -100,7 +100,7 @@ type aggregatrdSignature struct { Signatures [][]byte } -func (sv *signatureAggregator) Aggregate([]simplex.Signature) (simplex.QuorumCertificate, error) { +func (sv *signatureAggregator) Aggregate([]common.Signature) (common.QuorumCertificate, error) { panic("unused in tests") } @@ -113,7 +113,7 @@ func (sv *signatureAggregator) AppendSignatures(existing []byte, sigs ...[]byte) return asn1.Marshal(aggregatrdSignature{Signatures: all}) } -func (sv *signatureAggregator) IsQuorum(signers []simplex.NodeID) bool { +func (sv *signatureAggregator) IsQuorum(signers []common.NodeID) bool { var sum uint64 for _, signer := range signers { sum += sv.weightByNodeID[string(signer)] @@ -121,8 +121,8 @@ func (sv *signatureAggregator) IsQuorum(signers []simplex.NodeID) bool { return sum*3 > sv.totalWeight*2 } -func newSignatureAggregatorCreator() simplex.SignatureAggregatorCreator { - return func(weights []simplex.Node) simplex.SignatureAggregator { +func newSignatureAggregatorCreator() common.SignatureAggregatorCreator { + return func(weights []common.Node) common.SignatureAggregator { s := &signatureAggregator{weightByNodeID: make(map[string]uint64, len(weights))} for _, nw := range weights { s.weightByNodeID[string(nw.Node)] = nw.Weight @@ -238,7 +238,7 @@ func makeNormalSimplexBlock(t *testing.T, index int, blocks []StateMachineBlock, }, Metadata: StateMachineMetadata{ PChainHeight: 100, - SimplexProtocolMetadata: (&simplex.ProtocolMetadata{ + SimplexProtocolMetadata: (&common.ProtocolMetadata{ Round: round, Seq: seq, Epoch: 1, @@ -282,7 +282,7 @@ func newStateMachine(t *testing.T) (*StateMachine, *testConfig) { return newStateMachineWithLogger(t, testutil.MakeLogger(t)) } -func newStateMachineWithLogger(tb testing.TB, logger simplex.Logger) (*StateMachine, *testConfig) { +func newStateMachineWithLogger(tb testing.TB, logger common.Logger) (*StateMachine, *testConfig) { bs := make(blockStore) bs[0] = &outerBlock{block: genesisBlock} @@ -346,7 +346,7 @@ func newStateMachineWithLogger(tb testing.TB, logger simplex.Logger) (*StateMach // concatAggregator concatenates signatures for easy verification in tests. type concatAggregator struct{} -func (concatAggregator) Aggregate([]simplex.Signature) (simplex.QuorumCertificate, error) { +func (concatAggregator) Aggregate([]common.Signature) (common.QuorumCertificate, error) { panic("unused in tests") } @@ -355,13 +355,13 @@ func (concatAggregator) AppendSignatures(existing []byte, sigs ...[]byte) ([]byt return append(result, existing...), nil } -func (concatAggregator) IsQuorum([]simplex.NodeID) bool { +func (concatAggregator) IsQuorum([]common.NodeID) bool { return false } type failingAggregator struct{} -func (failingAggregator) Aggregate([]simplex.Signature) (simplex.QuorumCertificate, error) { +func (failingAggregator) Aggregate([]common.Signature) (common.QuorumCertificate, error) { panic("unused in tests") } @@ -371,16 +371,16 @@ func (failingAggregator) AppendSignatures([]byte, ...[]byte) ([]byte, error) { return nil, errTestAggregationFailed } -func (failingAggregator) IsQuorum([]simplex.NodeID) bool { +func (failingAggregator) IsQuorum([]common.NodeID) bool { return false } type testBlockStore map[uint64]StateMachineBlock -func (bs testBlockStore) getBlock(seq uint64, _ [32]byte) (StateMachineBlock, *simplex.Finalization, error) { +func (bs testBlockStore) getBlock(seq uint64, _ [32]byte) (StateMachineBlock, *common.Finalization, error) { blk, ok := bs[seq] if !ok { - return StateMachineBlock{}, nil, fmt.Errorf("%w: block %d", simplex.ErrBlockNotFound, seq) + return StateMachineBlock{}, nil, fmt.Errorf("%w: block %d", common.ErrBlockNotFound, seq) } return blk, nil, nil } diff --git a/block_scheduler.go b/simplex/block_scheduler.go similarity index 92% rename from block_scheduler.go rename to simplex/block_scheduler.go index 6434d5bd..70c03c30 100644 --- a/block_scheduler.go +++ b/simplex/block_scheduler.go @@ -11,6 +11,7 @@ import ( "sync" "sync/atomic" + "github.com/ava-labs/simplex/common" "go.uber.org/zap" ) @@ -26,7 +27,7 @@ type Scheduler interface { // It schedules tasks when their dependencies are resolved. type BlockDependencyManager struct { lock sync.Mutex - logger Logger + logger common.Logger scheduler Scheduler dependencies []*TaskWithDependents @@ -38,7 +39,7 @@ type TaskWithDependents struct { Task Task blockSeq uint64 // the seq of the block being verified - prevBlock *Digest + prevBlock *common.Digest emptyRounds map[uint64]struct{} } @@ -50,7 +51,7 @@ func (t *TaskWithDependents) String() string { return fmt.Sprintf("BlockVerificationTask{blockSeq: %d, prevBlock: %v, emptyRounds: %v}", t.blockSeq, t.prevBlock, slices.Collect(maps.Keys(t.emptyRounds))) } -func NewBlockVerificationScheduler(logger Logger, maxDeps uint64, scheduler Scheduler) *BlockDependencyManager { +func NewBlockVerificationScheduler(logger common.Logger, maxDeps uint64, scheduler Scheduler) *BlockDependencyManager { b := &BlockDependencyManager{ logger: logger, maxDeps: maxDeps, @@ -62,7 +63,7 @@ func NewBlockVerificationScheduler(logger Logger, maxDeps uint64, scheduler Sche } // ExecuteBlockDependents removes the given digest from dependent tasks and schedules any whose dependencies are now resolved. -func (bs *BlockDependencyManager) ExecuteBlockDependents(prev Digest) { +func (bs *BlockDependencyManager) ExecuteBlockDependents(prev common.Digest) { bs.lock.Lock() defer bs.lock.Unlock() @@ -121,7 +122,7 @@ func (bs *BlockDependencyManager) ExecuteEmptyRoundDependents(emptyRound uint64) bs.dependencies = remainingDeps } -func (bs *BlockDependencyManager) ScheduleTaskWithDependencies(task Task, blockSeq uint64, prev *Digest, emptyRounds []uint64) error { +func (bs *BlockDependencyManager) ScheduleTaskWithDependencies(task Task, blockSeq uint64, prev *common.Digest, emptyRounds []uint64) error { bs.lock.Lock() defer bs.lock.Unlock() @@ -129,7 +130,7 @@ func (bs *BlockDependencyManager) ScheduleTaskWithDependencies(task Task, blockS return nil } - wrappedTask := func() Digest { + wrappedTask := func() common.Digest { id := task() bs.ExecuteBlockDependents(id) return id diff --git a/block_scheduler_test.go b/simplex/block_scheduler_test.go similarity index 93% rename from block_scheduler_test.go rename to simplex/block_scheduler_test.go index 27e55ca0..bb3f139a 100644 --- a/block_scheduler_test.go +++ b/simplex/block_scheduler_test.go @@ -8,7 +8,8 @@ import ( "testing" "time" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" + "github.com/ava-labs/simplex/simplex" "github.com/ava-labs/simplex/testutil" "github.com/stretchr/testify/require" ) @@ -27,7 +28,7 @@ func TestBlockVerificationScheduler(t *testing.T) { wg := sync.WaitGroup{} wg.Add(1) - task := func() simplex.Digest { + task := func() common.Digest { defer wg.Done() return makeDigest(t) } @@ -44,7 +45,7 @@ func TestBlockVerificationScheduler(t *testing.T) { prev := makeDigest(t) done := make(chan struct{}, 1) - task := func() simplex.Digest { + task := func() common.Digest { done <- struct{}{} return makeDigest(t) } @@ -64,7 +65,7 @@ func TestBlockVerificationScheduler(t *testing.T) { defer bvs.Close() done := make(chan struct{}, 1) - task := func() simplex.Digest { + task := func() common.Digest { done <- struct{}{} return makeDigest(t) } @@ -87,7 +88,7 @@ func TestBlockVerificationScheduler(t *testing.T) { prev := makeDigest(t) done := make(chan struct{}, 1) - task := func() simplex.Digest { + task := func() common.Digest { done <- struct{}{} return makeDigest(t) } @@ -112,7 +113,7 @@ func TestBlockVerificationScheduler(t *testing.T) { prev := makeDigest(t) done := make(chan struct{}, 1) - task := func() simplex.Digest { + task := func() common.Digest { done <- struct{}{} return makeDigest(t) } @@ -138,14 +139,14 @@ func TestBlockVerificationScheduler(t *testing.T) { // Task A produces digest 'Aout' Aout := makeDigest(t) aRan := make(chan struct{}, 1) - taskA := func() simplex.Digest { + taskA := func() common.Digest { aRan <- struct{}{} return Aout } // Task B depends on A's output digest bRan := make(chan struct{}, 1) - taskB := func() simplex.Digest { + taskB := func() common.Digest { bRan <- struct{}{} return makeDigest(t) } @@ -174,12 +175,12 @@ func TestBlockVerificationScheduler(t *testing.T) { prev := makeDigest(t) // First: add one task with a dependency (it will sit in ds.dependencies) - require.NoError(t, bvs.ScheduleTaskWithDependencies(func() simplex.Digest { + require.NoError(t, bvs.ScheduleTaskWithDependencies(func() common.Digest { return makeDigest(t) }, 0, &prev, nil)) // Second: trying to add another should exceed the limit. - err := bvs.ScheduleTaskWithDependencies(func() simplex.Digest { + err := bvs.ScheduleTaskWithDependencies(func() common.Digest { return makeDigest(t) }, 0, &prev, nil) @@ -195,13 +196,13 @@ func TestBlockVerificationScheduler(t *testing.T) { prev2 := makeDigest(t) done1 := make(chan struct{}, 1) - task1 := func() simplex.Digest { + task1 := func() common.Digest { done1 <- struct{}{} return makeDigest(t) } done2 := make(chan struct{}, 1) - task2 := func() simplex.Digest { + task2 := func() common.Digest { done2 <- struct{}{} return makeDigest(t) } @@ -237,11 +238,11 @@ func TestBlockVerificationScheduler(t *testing.T) { oldRan := make(chan struct{}, 1) newRan := make(chan struct{}, 1) - taskOld := func() simplex.Digest { + taskOld := func() common.Digest { oldRan <- struct{}{} return makeDigest(t) } - taskNew := func() simplex.Digest { + taskNew := func() common.Digest { newRan <- struct{}{} return makeDigest(t) } diff --git a/epoch.go b/simplex/epoch.go similarity index 88% rename from epoch.go rename to simplex/epoch.go index 55d4a26e..b51d9d83 100644 --- a/epoch.go +++ b/simplex/epoch.go @@ -16,6 +16,7 @@ import ( "sync/atomic" "time" + "github.com/ava-labs/simplex/common" "github.com/ava-labs/simplex/record" "go.uber.org/zap" @@ -35,26 +36,26 @@ const ( type EmptyVoteSet struct { timedOut bool - votes map[string]*EmptyVote - emptyNotarization *EmptyNotarization + votes map[string]*common.EmptyVote + emptyNotarization *common.EmptyNotarization persisted bool } type Round struct { num uint64 - block VerifiedBlock - votes map[string]*Vote // NodeID --> vote - notarization *Notarization - finalizeVotes map[string]*FinalizeVote // NodeID --> vote - finalization *Finalization + block common.VerifiedBlock + votes map[string]*common.Vote // NodeID --> vote + notarization *common.Notarization + finalizeVotes map[string]*common.FinalizeVote // NodeID --> vote + finalization *common.Finalization } -func NewRound(block VerifiedBlock) *Round { +func NewRound(block common.VerifiedBlock) *Round { return &Round{ num: block.BlockHeader().Round, block: block, - votes: make(map[string]*Vote), - finalizeVotes: make(map[string]*FinalizeVote), + votes: make(map[string]*common.Vote), + finalizeVotes: make(map[string]*common.FinalizeVote), } } @@ -63,17 +64,17 @@ type EpochConfig struct { MaxRoundWindow uint64 MaxRebroadcastWait time.Duration FinalizeRebroadcastTimeout time.Duration - QCDeserializer QCDeserializer - Logger Logger - ID NodeID - Signer Signer - Verifier SignatureVerifier - BlockDeserializer BlockDeserializer - SignatureAggregatorCreator SignatureAggregatorCreator - Comm Communication - Storage Storage - WAL WriteAheadLog - BlockBuilder BlockBuilder + QCDeserializer common.QCDeserializer + Logger common.Logger + ID common.NodeID + Signer common.Signer + Verifier common.SignatureVerifier + BlockDeserializer common.BlockDeserializer + SignatureAggregatorCreator common.SignatureAggregatorCreator + Comm common.Communication + Storage common.Storage + WAL common.WriteAheadLog + BlockBuilder common.BlockBuilder Epoch uint64 StartTime time.Time ReplicationEnabled bool @@ -83,19 +84,19 @@ type EpochConfig struct { type Epoch struct { EpochConfig // Runtime - signatureAggregator SignatureAggregator + signatureAggregator common.SignatureAggregator oneTimeVerifier *OneTimeVerifier buildBlockScheduler *BasicScheduler blockVerificationScheduler *BlockDependencyManager lock sync.Mutex - lastBlock *VerifiedFinalizedBlock // latest block & finalization committed + lastBlock *common.VerifiedFinalizedBlock // latest block & finalization committed canReceiveMessages atomic.Bool finishCtx context.Context finishFn context.CancelFunc blockBuilderCtx context.Context blockBuilderCancelFunc context.CancelFunc - nodeIDs NodeIDs - nodes Nodes + nodeIDs common.NodeIDs + nodes common.Nodes eligibleNodeIDs map[string]struct{} rounds map[uint64]*Round emptyVotes map[uint64]*EmptyVoteSet @@ -127,7 +128,7 @@ func (e *Epoch) AdvanceTime(t time.Time) { } // HandleMessage notifies the engine about a reception of a message. -func (e *Epoch) HandleMessage(msg *Message, from NodeID) error { +func (e *Epoch) HandleMessage(msg *common.Message, from common.NodeID) error { e.lock.Lock() defer e.lock.Unlock() @@ -294,7 +295,7 @@ func (e *Epoch) sequenceAlreadyIndexed(seq uint64) bool { } func (e *Epoch) restoreBlockRecord(r []byte, highestWalRound *walRound) error { - block, err := BlockFromRecord(e.finishCtx, e.BlockDeserializer, r) + block, err := common.BlockFromRecord(e.finishCtx, e.BlockDeserializer, r) if err != nil { return err } @@ -312,7 +313,7 @@ func (e *Epoch) restoreBlockRecord(r []byte, highestWalRound *walRound) error { return e.loadBlockRecord(block) } -func (e *Epoch) loadBlockRecord(block Block) error { +func (e *Epoch) loadBlockRecord(block common.Block) error { if e.sequenceAlreadyIndexed(block.BlockHeader().Seq) { e.Logger.Debug("Block already indexed, skipping restoration", zap.Uint64("Sequence", block.BlockHeader().Seq)) return nil @@ -332,7 +333,7 @@ func (e *Epoch) loadBlockRecord(block Block) error { } func (e *Epoch) restoreNotarizationRecord(r []byte, highestWalRound *walRound) error { - notarization, err := NotarizationFromRecord(r, e.QCDeserializer) + notarization, err := common.NotarizationFromRecord(r, e.QCDeserializer) if err != nil { return err } @@ -351,7 +352,7 @@ func (e *Epoch) restoreNotarizationRecord(r []byte, highestWalRound *walRound) e } func (e *Epoch) loadNotarizationRecord(r []byte) error { - notarization, err := NotarizationFromRecord(r, e.QCDeserializer) + notarization, err := common.NotarizationFromRecord(r, e.QCDeserializer) if err != nil { return err } @@ -371,7 +372,7 @@ func (e *Epoch) loadNotarizationRecord(r []byte) error { } func (e *Epoch) restoreEmptyNotarizationRecord(r []byte, highestWalRound *walRound) error { - emptyNotarization, err := EmptyNotarizationFromRecord(r, e.QCDeserializer) + emptyNotarization, err := common.EmptyNotarizationFromRecord(r, e.QCDeserializer) if err != nil { return err } @@ -390,7 +391,7 @@ func (e *Epoch) restoreEmptyNotarizationRecord(r []byte, highestWalRound *walRou } func (e *Epoch) loadEmptyNotarizationRecord(r []byte) error { - emptyNotarization, err := EmptyNotarizationFromRecord(r, e.QCDeserializer) + emptyNotarization, err := common.EmptyNotarizationFromRecord(r, e.QCDeserializer) if err != nil { return err } @@ -401,7 +402,7 @@ func (e *Epoch) loadEmptyNotarizationRecord(r []byte) error { } func (e *Epoch) restoreEmptyVoteRecord(r []byte, highestWalRound *walRound) error { - vote, err := ParseEmptyVoteRecord(r) + vote, err := common.ParseEmptyVoteRecord(r) if err != nil { return err } @@ -420,7 +421,7 @@ func (e *Epoch) restoreEmptyVoteRecord(r []byte, highestWalRound *walRound) erro } func (e *Epoch) loadEmptyVoteRecord(r []byte) error { - vote, err := ParseEmptyVoteRecord(r) + vote, err := common.ParseEmptyVoteRecord(r) if err != nil { return err } @@ -433,8 +434,8 @@ func (e *Epoch) loadEmptyVoteRecord(r []byte) error { return err } - emptyVote := &EmptyVote{ - Signature: Signature{ + emptyVote := &common.EmptyVote{ + Signature: common.Signature{ Signer: e.ID, Value: signature, }, @@ -447,7 +448,7 @@ func (e *Epoch) loadEmptyVoteRecord(r []byte) error { } func (e *Epoch) restoreFinalizationRecord(r []byte, highestWalRound *walRound) error { - finalization, err := FinalizationFromRecord(r, e.QCDeserializer) + finalization, err := common.FinalizationFromRecord(r, e.QCDeserializer) if err != nil { return err } @@ -466,7 +467,7 @@ func (e *Epoch) restoreFinalizationRecord(r []byte, highestWalRound *walRound) e } func (e *Epoch) loadFinalizationRecord(r []byte) error { - finalization, err := FinalizationFromRecord(r, e.QCDeserializer) + finalization, err := common.FinalizationFromRecord(r, e.QCDeserializer) if err != nil { return err } @@ -503,8 +504,8 @@ func (e *Epoch) broadcastReplicationSync() { latestFinalizedSeq = e.lastBlock.Finalization.Finalization.Seq } - replicationRequest := &Message{ - ReplicationRequest: &ReplicationRequest{ + replicationRequest := &common.Message{ + ReplicationRequest: &common.ReplicationRequest{ LatestRound: latestRound, LatestFinalizedSeq: latestFinalizedSeq, }, @@ -518,7 +519,7 @@ func (e *Epoch) resumeFromWal(highestRoundRecord *walRound) error { // Handle the most relevant record based on priority: finalization > notarization > emptyNotarization > emptyVote > block if highestRoundRecord.finalization != nil { - finalizationMsg := &Message{Finalization: highestRoundRecord.finalization} + finalizationMsg := &common.Message{Finalization: highestRoundRecord.finalization} e.Comm.Broadcast(finalizationMsg) e.Logger.Debug("Broadcast finalization", @@ -530,7 +531,7 @@ func (e *Epoch) resumeFromWal(highestRoundRecord *walRound) error { if highestRoundRecord.notarization != nil { notarization := highestRoundRecord.notarization - lastMessage := Message{Notarization: notarization} + lastMessage := common.Message{Notarization: notarization} e.Comm.Broadcast(&lastMessage) if e.sequenceAlreadyIndexed(notarization.Vote.Seq) { @@ -542,7 +543,7 @@ func (e *Epoch) resumeFromWal(highestRoundRecord *walRound) error { } if highestRoundRecord.emptyNotarization != nil { - lastMessage := Message{EmptyNotarization: highestRoundRecord.emptyNotarization} + lastMessage := common.Message{EmptyNotarization: highestRoundRecord.emptyNotarization} e.Comm.Broadcast(&lastMessage) return e.startRound() } @@ -557,7 +558,7 @@ func (e *Epoch) resumeFromWal(highestRoundRecord *walRound) error { if !exists { return fmt.Errorf("could not find my own vote for round %d", ev.Round) } - lastMessage := Message{EmptyVoteMessage: emptyVote} + lastMessage := common.Message{EmptyVoteMessage: emptyVote} e.Comm.Broadcast(&lastMessage) e.Logger.Info("Rebroadcasting empty vote from WAL", zap.Uint64("round", ev.Round)) e.addEmptyVoteRebroadcastTimeout() @@ -581,8 +582,8 @@ func (e *Epoch) resumeFromWal(highestRoundRecord *walRound) error { if err != nil { return err } - proposal := &Message{ - VerifiedBlockMessage: &VerifiedBlockMessage{ + proposal := &common.Message{ + VerifiedBlockMessage: &common.VerifiedBlockMessage{ VerifiedBlock: round.block, Vote: vote, }, @@ -623,7 +624,7 @@ func (e *Epoch) setMetadataFromRecords(records [][]byte) error { recordType := binary.BigEndian.Uint16(records[i]) switch recordType { case record.NotarizationRecordType: - notarization, err := NotarizationFromRecord(records[i], e.QCDeserializer) + notarization, err := common.NotarizationFromRecord(records[i], e.QCDeserializer) if err != nil { return err } @@ -633,7 +634,7 @@ func (e *Epoch) setMetadataFromRecords(records [][]byte) error { found = true } case record.EmptyNotarizationRecordType: - emptyNotarization, err := EmptyNotarizationFromRecord(records[i], e.QCDeserializer) + emptyNotarization, err := common.EmptyNotarizationFromRecord(records[i], e.QCDeserializer) if err != nil { return err } @@ -643,7 +644,7 @@ func (e *Epoch) setMetadataFromRecords(records [][]byte) error { found = true } case record.FinalizationRecordType: - finalization, err := FinalizationFromRecord(records[i], e.QCDeserializer) + finalization, err := common.FinalizationFromRecord(records[i], e.QCDeserializer) if err != nil { return err } @@ -733,7 +734,7 @@ func (e *Epoch) Stop() { e.replicationState.Close() } -func (e *Epoch) handleFinalizationMessage(message *Finalization, from NodeID) error { +func (e *Epoch) handleFinalizationMessage(message *common.Finalization, from common.NodeID) error { e.Logger.Verbo("Received finalization message", zap.Stringer("from", from), zap.Uint64("round", message.Finalization.Round), zap.Uint64("seq", message.Finalization.Seq)) @@ -766,7 +767,7 @@ func (e *Epoch) handleFinalizationMessage(message *Finalization, from NodeID) er return e.persistFinalization(*message) } -func (e *Epoch) handleFinalizationForPendingOrFutureRound(message *Finalization, round uint64, nextSeqToCommit uint64) { +func (e *Epoch) handleFinalizationForPendingOrFutureRound(message *common.Finalization, round uint64, nextSeqToCommit uint64) { if round == e.round { // delay collecting future finalization if we are verifying the proposal for that round // and the finalization is for rounds we have @@ -789,7 +790,7 @@ func (e *Epoch) handleFinalizationForPendingOrFutureRound(message *Finalization, e.replicationState.ReceivedFutureFinalization(message, nextSeqToCommit) } -func (e *Epoch) handleFinalizeVoteMessage(message *FinalizeVote, from NodeID) error { +func (e *Epoch) handleFinalizeVoteMessage(message *common.FinalizeVote, from common.NodeID) error { vote := message.Finalization e.Logger.Verbo("Received finalize vote", @@ -838,7 +839,7 @@ func (e *Epoch) handleFinalizeVoteMessage(message *FinalizeVote, from NodeID) er return nil } // send the finalization to the sender in case they missed it - e.Comm.Send(&Message{ + e.Comm.Send(&common.Message{ Finalization: round.finalization, }, from) return nil @@ -854,7 +855,7 @@ func (e *Epoch) handleFinalizeVoteMessage(message *FinalizeVote, from NodeID) er return e.maybeCollectFinalization(round) } -func (e *Epoch) storeFutureFinalizeVote(message *FinalizeVote, from NodeID, round uint64) { +func (e *Epoch) storeFutureFinalizeVote(message *common.FinalizeVote, from common.NodeID, round uint64) { msgsForRound, exists := e.futureMessages[string(from)][round] if !exists { msgsForRound = &messagesForRound{} @@ -863,7 +864,7 @@ func (e *Epoch) storeFutureFinalizeVote(message *FinalizeVote, from NodeID, roun msgsForRound.finalizeVote = message } -func (e *Epoch) storeFutureNotarization(message *Notarization, from NodeID, round uint64) { +func (e *Epoch) storeFutureNotarization(message *common.Notarization, from common.NodeID, round uint64) { msgsForRound, exists := e.futureMessages[string(from)][round] if !exists { msgsForRound = &messagesForRound{} @@ -872,7 +873,7 @@ func (e *Epoch) storeFutureNotarization(message *Notarization, from NodeID, roun msgsForRound.notarization = message } -func (e *Epoch) handleEmptyVoteMessage(message *EmptyVote, from NodeID) error { +func (e *Epoch) handleEmptyVoteMessage(message *common.EmptyVote, from common.NodeID) error { vote := message.Vote e.Logger.Verbo("Received empty vote message", @@ -928,20 +929,20 @@ func (e *Epoch) handleEmptyVoteMessage(message *EmptyVote, from NodeID) error { return e.maybeAssembleEmptyNotarization() } -func (e *Epoch) sendLatestFinalization(to NodeID) { +func (e *Epoch) sendLatestFinalization(to common.NodeID) { if e.lastBlock == nil { e.Logger.Debug("No blocks committed yet, cannot send latest block", zap.Stringer("to", to)) return } - msg := &Message{ + msg := &common.Message{ Finalization: &e.lastBlock.Finalization, } e.Logger.Debug("Node appears behind, sending it the latest finalization", zap.Stringer("to", to), zap.Uint64("round", e.lastBlock.Finalization.Finalization.Round), zap.Uint64("sequence", e.lastBlock.Finalization.Finalization.Seq)) e.Comm.Send(msg, to) } -func (e *Epoch) sendHighestRound(to NodeID) { +func (e *Epoch) sendHighestRound(to common.NodeID) { latestQR := e.getLatestVerifiedQuorumRound() if latestQR == nil { @@ -950,7 +951,7 @@ func (e *Epoch) sendHighestRound(to NodeID) { } if latestQR.Notarization != nil { - msg := &Message{ + msg := &common.Message{ Notarization: latestQR.Notarization, } e.Logger.Debug("Node appears behind, sending it the highest round", zap.Stringer("to", to), zap.Uint64("round", latestQR.Notarization.Vote.Round)) @@ -959,7 +960,7 @@ func (e *Epoch) sendHighestRound(to NodeID) { } if latestQR.EmptyNotarization != nil { - msg := &Message{ + msg := &common.Message{ EmptyNotarization: latestQR.EmptyNotarization, } e.Logger.Debug("Node appears behind, sending it the highest empty notarized round", zap.Stringer("to", to), zap.Uint64("round", latestQR.EmptyNotarization.Vote.Round)) @@ -968,14 +969,14 @@ func (e *Epoch) sendHighestRound(to NodeID) { } } -func (e *Epoch) maybeSendNotarizationOrFinalization(to NodeID, round uint64) { +func (e *Epoch) maybeSendNotarizationOrFinalization(to common.NodeID, round uint64) { r, ok := e.rounds[round] if !ok { // round could be an empty notarized round evs, ok := e.emptyVotes[round] if ok && evs.emptyNotarization != nil { - msg := &Message{ + msg := &common.Message{ EmptyNotarization: evs.emptyNotarization, } e.Logger.Debug("Node appears behind, sending it an empty notarization", zap.Stringer("to", to), zap.Uint64("round", round)) @@ -986,7 +987,7 @@ func (e *Epoch) maybeSendNotarizationOrFinalization(to NodeID, round uint64) { } if r.finalization != nil { - msg := &Message{ + msg := &common.Message{ Finalization: r.finalization, } e.Comm.Send(msg, to) @@ -995,7 +996,7 @@ func (e *Epoch) maybeSendNotarizationOrFinalization(to NodeID, round uint64) { if r.notarization != nil { e.Logger.Debug("Node appears behind, sending it a notarization", zap.Stringer("to", to), zap.Uint64("round", round)) - msg := &Message{ + msg := &common.Message{ Notarization: r.notarization, } e.Comm.Send(msg, to) @@ -1006,13 +1007,13 @@ func (e *Epoch) maybeSendNotarizationOrFinalization(to NodeID, round uint64) { func (e *Epoch) getOrCreateEmptyVoteSetForRound(round uint64) *EmptyVoteSet { emptyVotes, exists := e.emptyVotes[round] if !exists { - emptyVotes = &EmptyVoteSet{votes: make(map[string]*EmptyVote)} + emptyVotes = &EmptyVoteSet{votes: make(map[string]*common.EmptyVote)} e.emptyVotes[round] = emptyVotes } return emptyVotes } -func (e *Epoch) handleVoteMessage(message *Vote, from NodeID) error { +func (e *Epoch) handleVoteMessage(message *common.Vote, from common.NodeID) error { vote := message.Vote e.Logger.Verbo("Received vote message", @@ -1084,7 +1085,7 @@ func (e *Epoch) haveWeAlreadyTimedOutOnThisRound(round uint64) bool { return exists && emptyVotes.timedOut } -func (e *Epoch) storeFutureVote(message *Vote, from NodeID, round uint64) { +func (e *Epoch) storeFutureVote(message *common.Vote, from common.NodeID, round uint64) { msgsForRound, exists := e.futureMessages[string(from)][round] if !exists { msgsForRound = &messagesForRound{} @@ -1093,7 +1094,7 @@ func (e *Epoch) storeFutureVote(message *Vote, from NodeID, round uint64) { msgsForRound.vote = message } -func (e *Epoch) deleteFutureVote(from NodeID, round uint64) { +func (e *Epoch) deleteFutureVote(from common.NodeID, round uint64) { msgsForRound, exists := e.futureMessages[string(from)][round] if !exists { return @@ -1101,7 +1102,7 @@ func (e *Epoch) deleteFutureVote(from NodeID, round uint64) { msgsForRound.vote = nil } -func (e *Epoch) deleteFutureProposal(from NodeID, round uint64) { +func (e *Epoch) deleteFutureProposal(from common.NodeID, round uint64) { msgsForRound, exists := e.futureMessages[string(from)][round] if !exists { return @@ -1110,7 +1111,7 @@ func (e *Epoch) deleteFutureProposal(from NodeID, round uint64) { msgsForRound.proposalBeingProcessed = false } -func (e *Epoch) deleteFutureFinalizeVote(from NodeID, round uint64) { +func (e *Epoch) deleteFutureFinalizeVote(from common.NodeID, round uint64) { msgsForRound, exists := e.futureMessages[string(from)][round] if !exists { return @@ -1118,7 +1119,7 @@ func (e *Epoch) deleteFutureFinalizeVote(from NodeID, round uint64) { msgsForRound.finalizeVote = nil } -func (e *Epoch) deleteFutureNotarization(from NodeID, round uint64) { +func (e *Epoch) deleteFutureNotarization(from common.NodeID, round uint64) { msgsForRound, exists := e.futureMessages[string(from)][round] if !exists { return @@ -1126,7 +1127,7 @@ func (e *Epoch) deleteFutureNotarization(from NodeID, round uint64) { msgsForRound.notarization = nil } -func (e *Epoch) isFinalizationValid(signature []byte, finalization ToBeSignedFinalization, from NodeID) bool { +func (e *Epoch) isFinalizationValid(signature []byte, finalization common.ToBeSignedFinalization, from common.NodeID) bool { if err := finalization.Verify(signature, e.Verifier, from); err != nil { e.Logger.Debug("Received a finalization with an invalid signature", zap.Uint64("round", finalization.Round), zap.Error(err)) return false @@ -1153,14 +1154,14 @@ func (e *Epoch) isVoteRoundValid(round uint64) bool { func (e *Epoch) maybeCollectFinalization(round *Round) error { // Divide finalizations into sets that agree on the same metadata - finalizationsByMD := make(map[string][]*FinalizeVote) + finalizationsByMD := make(map[string][]*common.FinalizeVote) for _, vote := range round.finalizeVotes { key := string(vote.Finalization.Bytes()) finalizationsByMD[key] = append(finalizationsByMD[key], vote) } - var finalizations []*FinalizeVote + var finalizations []*common.FinalizeVote for _, finalizationsWithTheSameDigest := range finalizationsByMD { if e.signatureAggregator.IsQuorum(NodeIDsFromVotes(finalizationsWithTheSameDigest)) { @@ -1177,12 +1178,12 @@ func (e *Epoch) maybeCollectFinalization(round *Round) error { return e.assembleFinalization(round, finalizations) } -func (e *Epoch) assembleFinalization(round *Round, finalizationVotes []*FinalizeVote) error { +func (e *Epoch) assembleFinalization(round *Round, finalizationVotes []*common.FinalizeVote) error { for _, vote := range finalizationVotes { e.Logger.Debug("Collected a finalize vote from node", zap.Stringer("NodeID", vote.Signature.Signer), zap.Uint64("round", vote.Finalization.Round), zap.Uint64("seq", vote.Finalization.Seq)) } - finalization, err := NewFinalization(e.signatureAggregator, finalizationVotes) + finalization, err := common.NewFinalization(e.signatureAggregator, finalizationVotes) if err != nil { return err } @@ -1198,7 +1199,7 @@ func (e *Epoch) progressRoundsDueToCommit(round uint64) { } } -func (e *Epoch) persistFinalization(finalization Finalization) error { +func (e *Epoch) persistFinalization(finalization common.Finalization) error { e.Logger.Debug("Received enough finalize votes to finalize a block", zap.Uint64("round", finalization.Finalization.Round)) // Check to see if we should commit this finalization to the storage as part of a block commit, // or otherwise write it to the WAL in order to commit it later. @@ -1216,7 +1217,7 @@ func (e *Epoch) persistFinalization(finalization Finalization) error { return err } } else { - finalizationRecord := NewQuorumRecord(finalization.QC.Bytes(), finalization.Finalization.Bytes(), record.FinalizationRecordType) + finalizationRecord := common.NewQuorumRecord(finalization.QC.Bytes(), finalization.Finalization.Bytes(), record.FinalizationRecordType) if err := e.WAL.Append(finalizationRecord); err != nil { e.Logger.Error("Failed to append finalization record to WAL", zap.Error(err)) return err @@ -1247,7 +1248,7 @@ func (e *Epoch) persistFinalization(finalization Finalization) error { } } - finalizationMsg := &Message{Finalization: &finalization} + finalizationMsg := &common.Message{Finalization: &finalization} e.Comm.Broadcast(finalizationMsg) e.Logger.Debug("Broadcast finalization", @@ -1285,10 +1286,10 @@ func (e *Epoch) rebroadcastPastFinalizeVotes() error { continue } - var finalizeVoteMessage *Message + var finalizeVoteMessage *common.Message // Try to re-use finalization we created if possible, else create it. if vote, exists := round.finalizeVotes[string(e.ID)]; exists { - finalizeVoteMessage = &Message{FinalizeVote: vote} + finalizeVoteMessage = &common.Message{FinalizeVote: vote} } else { _, msg, err := e.constructFinalizeVoteMessage(round.notarization.Vote.BlockHeader) if err != nil { @@ -1366,7 +1367,7 @@ func (e *Epoch) indexFinalizations(startRound uint64) error { return nil } -func (e *Epoch) indexFinalization(block VerifiedBlock, finalization Finalization) error { +func (e *Epoch) indexFinalization(block common.VerifiedBlock, finalization common.Finalization) error { if err := e.Storage.Index(e.finishCtx, block, finalization); err != nil { return err } @@ -1374,7 +1375,7 @@ func (e *Epoch) indexFinalization(block VerifiedBlock, finalization Finalization zap.Uint64("round", finalization.Finalization.Round), zap.Uint64("sequence", finalization.Finalization.Seq), zap.Stringer("digest", finalization.Finalization.BlockHeader.Digest)) - e.lastBlock = &VerifiedFinalizedBlock{ + e.lastBlock = &common.VerifiedFinalizedBlock{ VerifiedBlock: block, Finalization: finalization, } @@ -1407,7 +1408,7 @@ func (e *Epoch) maybeAssembleEmptyNotarization() error { return nil } - emptyNotarization := &EmptyNotarization{QC: qc, Vote: popularEmptyVote} + emptyNotarization := &common.EmptyNotarization{QC: qc, Vote: popularEmptyVote} // write to the empty vote set emptyVotes.emptyNotarization = emptyNotarization @@ -1415,8 +1416,8 @@ func (e *Epoch) maybeAssembleEmptyNotarization() error { return e.persistEmptyNotarization(emptyVotes, true) } -func findEmptyVoteThatIsQuorum(votes map[string]*EmptyVote, isQuorum func([]NodeID) bool) (ToBeSignedEmptyVote, []Signature, bool) { - votesByBytes := make(map[string][]*EmptyVote) +func findEmptyVoteThatIsQuorum(votes map[string]*common.EmptyVote, isQuorum func([]common.NodeID) bool) (common.ToBeSignedEmptyVote, []common.Signature, bool) { + votesByBytes := make(map[string][]*common.EmptyVote) for _, vote := range votes { key := string(vote.Vote.Bytes()) votesByBytes[key] = append(votesByBytes[key], vote) @@ -1428,7 +1429,7 @@ func findEmptyVoteThatIsQuorum(votes map[string]*EmptyVote, isQuorum func([]Node } } - return ToBeSignedEmptyVote{}, nil, false + return common.ToBeSignedEmptyVote{}, nil, false } func (e *Epoch) persistEmptyNotarization(emptyVotes *EmptyVoteSet, shouldBroadcast bool) error { @@ -1439,7 +1440,7 @@ func (e *Epoch) persistEmptyNotarization(emptyVotes *EmptyVoteSet, shouldBroadca } emptyNotarization := emptyVotes.emptyNotarization - emptyNotarizationRecord := NewEmptyNotarizationRecord(emptyNotarization) + emptyNotarizationRecord := common.NewEmptyNotarizationRecord(emptyNotarization) if err := e.WAL.Append(emptyNotarizationRecord); err != nil { e.Logger.Error("Failed to append empty notarization record to WAL", zap.Error(err)) return err @@ -1451,7 +1452,7 @@ func (e *Epoch) persistEmptyNotarization(emptyVotes *EmptyVoteSet, shouldBroadca emptyVotes.persisted = true if shouldBroadcast { - notarizationMessage := &Message{EmptyNotarization: emptyNotarization} + notarizationMessage := &common.Message{EmptyNotarization: emptyNotarization} e.Comm.Broadcast(notarizationMessage) e.Logger.Debug("Broadcast empty notarization", zap.Uint64("round", emptyNotarization.Vote.Round)) @@ -1474,9 +1475,9 @@ func (e *Epoch) persistEmptyNotarization(emptyVotes *EmptyVoteSet, shouldBroadca return e.startRound() } -func (e *Epoch) maybeMarkLeaderAsTimedOutForFutureBlacklisting(emptyNotarization *EmptyNotarization) error { +func (e *Epoch) maybeMarkLeaderAsTimedOutForFutureBlacklisting(emptyNotarization *common.EmptyNotarization) error { e.Logger.Debug("Marking the leader as timed out", zap.Uint64("round", emptyNotarization.Vote.Round), zap.Stringer("leader", LeaderForRound(e.nodeIDs, emptyNotarization.Vote.Round))) - var blacklist Blacklist + var blacklist common.Blacklist if e.lastBlock != nil { if e.lastBlock.VerifiedBlock == nil { e.Logger.Error("No verified block found in last block") @@ -1499,7 +1500,7 @@ func (e *Epoch) maybeCollectNotarization() error { block := e.rounds[e.round].block md := block.BlockHeader() - votesForOurBlock := make([]*Vote, 0, voteCount) + votesForOurBlock := make([]*common.Vote, 0, voteCount) // Ensure we have enough votes for the same block header. for _, vote := range votesForCurrentRound { @@ -1516,7 +1517,7 @@ func (e *Epoch) maybeCollectNotarization() error { return nil } - notarization, err := NewNotarization(e.Logger, e.signatureAggregator, votesForCurrentRound, block.BlockHeader()) + notarization, err := common.NewNotarization(e.Logger, e.signatureAggregator, votesForCurrentRound, block.BlockHeader()) if err != nil { return err } @@ -1524,8 +1525,8 @@ func (e *Epoch) maybeCollectNotarization() error { return e.persistAndBroadcastNotarization(notarization) } -func (e *Epoch) writeNotarizationToWal(notarization Notarization) error { - notarizationRecord := NewQuorumRecord(notarization.QC.Bytes(), notarization.Vote.Bytes(), record.NotarizationRecordType) +func (e *Epoch) writeNotarizationToWal(notarization common.Notarization) error { + notarizationRecord := common.NewQuorumRecord(notarization.QC.Bytes(), notarization.Vote.Bytes(), record.NotarizationRecordType) if err := e.WAL.Append(notarizationRecord); err != nil { e.Logger.Error("Failed to append notarization record to WAL", zap.Error(err)) @@ -1540,7 +1541,7 @@ func (e *Epoch) writeNotarizationToWal(notarization Notarization) error { return nil } -func (e *Epoch) persistNotarization(notarization Notarization) error { +func (e *Epoch) persistNotarization(notarization common.Notarization) error { r, exists := e.rounds[notarization.Vote.Round] if !exists { return fmt.Errorf("attempted to store notarization of a non existent round %d", notarization.Vote.Round) @@ -1572,13 +1573,13 @@ func (e *Epoch) persistNotarization(notarization Notarization) error { return nil } -func (e *Epoch) persistAndBroadcastNotarization(notarization Notarization) error { +func (e *Epoch) persistAndBroadcastNotarization(notarization common.Notarization) error { err := e.persistNotarization(notarization) if err != nil { return err } - notarizationMessage := &Message{Notarization: ¬arization} + notarizationMessage := &common.Message{Notarization: ¬arization} e.Comm.Broadcast(notarizationMessage) e.Logger.Debug("Broadcast notarization", @@ -1589,7 +1590,7 @@ func (e *Epoch) persistAndBroadcastNotarization(notarization Notarization) error return e.doNotarized(notarization.Vote.Round) } -func (e *Epoch) handleEmptyNotarizationMessage(emptyNotarization *EmptyNotarization, from NodeID) error { +func (e *Epoch) handleEmptyNotarizationMessage(emptyNotarization *common.EmptyNotarization, from common.NodeID) error { vote := emptyNotarization.Vote e.Logger.Verbo("Received empty notarization message", zap.Uint64("round", vote.Round)) @@ -1648,7 +1649,7 @@ func (e *Epoch) isVoteForFinalizedRound(round uint64) bool { return round < max } -func (e *Epoch) handleNotarizationMessage(message *Notarization, from NodeID) error { +func (e *Epoch) handleNotarizationMessage(message *common.Notarization, from common.NodeID) error { vote := message.Vote e.Logger.Verbo("Received notarization message", @@ -1688,8 +1689,8 @@ func (e *Epoch) handleNotarizationMessage(message *Notarization, from NodeID) er e.storeFutureNotarization(message, from, vote.Round) // we need to request the block - blockDigestRequest := &Message{ - BlockDigestRequest: &BlockDigestRequest{ + blockDigestRequest := &common.Message{ + BlockDigestRequest: &common.BlockDigestRequest{ Digest: vote.Digest, Seq: vote.Seq, }, @@ -1707,7 +1708,7 @@ func (e *Epoch) handleNotarizationMessage(message *Notarization, from NodeID) er return e.persistAndBroadcastNotarization(*message) } -func (e *Epoch) handleBlockMessage(message *BlockMessage, from NodeID) error { +func (e *Epoch) handleBlockMessage(message *common.BlockMessage, from common.NodeID) error { block := message.Block if block == nil { e.Logger.Debug("Got empty block in a BlockMessage") @@ -1814,13 +1815,13 @@ func (e *Epoch) handleBlockMessage(message *BlockMessage, from NodeID) error { return nil } -func (e *Epoch) sendMissingRoundsRequest(to NodeID, missingRounds []uint64) { +func (e *Epoch) sendMissingRoundsRequest(to common.NodeID, missingRounds []uint64) { e.Logger.Debug("Requesting missing empty notarizations for rounds", zap.Stringer("to", to), zap.Uint64s("missing rounds", missingRounds)) - request := &Message{ - ReplicationRequest: &ReplicationRequest{ + request := &common.Message{ + ReplicationRequest: &common.ReplicationRequest{ Rounds: missingRounds, }, } @@ -1832,7 +1833,7 @@ func (e *Epoch) sendMissingRoundsRequest(to NodeID, missingRounds []uint64) { // It returns the digest of the previous block it depends on (or emptyDigest if none), // as well as a list of rounds for which it needs to verify empty notarizations. // TODO: we should request empty notarizations if we don't have them -func (e *Epoch) blockDependencies(bh BlockHeader) (*Digest, []uint64) { +func (e *Epoch) blockDependencies(bh common.BlockHeader) (*common.Digest, []uint64) { if bh.Seq == 0 { // genesis block has no dependencies return nil, nil @@ -1871,7 +1872,7 @@ func (e *Epoch) blockDependencies(bh BlockHeader) (*Digest, []uint64) { // processFinalizedBlocks processes a block that has a finalization. // if the block has already been verified, it will index the finalization, // otherwise it will verify the block first. -func (e *Epoch) processFinalizedBlock(block Block, finalization *Finalization) error { +func (e *Epoch) processFinalizedBlock(block common.Block, finalization *common.Finalization) error { e.Logger.Debug("Processing finalized block during replication", zap.Uint64("round", finalization.Finalization.Round), zap.Uint64("sequence", finalization.Finalization.Seq)) round, exists := e.rounds[finalization.Finalization.Round] @@ -1929,7 +1930,7 @@ func (e *Epoch) processFinalizedBlock(block Block, finalization *Finalization) e // processNotarizedBlock processes a block that has a notarization. // if the block has already been verified, it will persist the notarization, // otherwise it will verify the block first. -func (e *Epoch) processNotarizedBlock(block Block, notarization *Notarization) error { +func (e *Epoch) processNotarizedBlock(block common.Block, notarization *common.Notarization) error { e.Logger.Debug("Processing notarized block during replication", zap.Uint64("round", notarization.Vote.Round), zap.Uint64("sequence", notarization.Vote.Seq)) md := block.BlockHeader() round, exists := e.rounds[md.Round] @@ -1980,8 +1981,8 @@ func (e *Epoch) processNotarizedBlock(block Block, notarization *Notarization) e return e.blockVerificationScheduler.ScheduleTaskWithDependencies(task, md.Seq, blockDependency, missingRounds) } -func (e *Epoch) createBlockVerificationTask(block Block, from NodeID, vote Vote) func() Digest { - return func() Digest { +func (e *Epoch) createBlockVerificationTask(block common.Block, from common.NodeID, vote common.Vote) func() common.Digest { + return func() common.Digest { md := block.BlockHeader() e.Logger.Debug("Block verification started", zap.Uint64("round", md.Round)) @@ -2021,7 +2022,7 @@ func (e *Epoch) createBlockVerificationTask(block Block, from NodeID, vote Vote) return md.Digest } - blockRecord := BlockRecord(md, blockBytes) + blockRecord := common.BlockRecord(md, blockBytes) if err := e.WAL.Append(blockRecord); err != nil { e.haltedError = err e.Logger.Error("Failed to append block record to WAL", zap.Error(err)) @@ -2069,8 +2070,8 @@ func (e *Epoch) createBlockVerificationTask(block Block, from NodeID, vote Vote) } } -func (e *Epoch) createFinalizedBlockVerificationTask(block Block, finalization *Finalization) func() Digest { - return func() Digest { +func (e *Epoch) createFinalizedBlockVerificationTask(block common.Block, finalization *common.Finalization) func() common.Digest { + return func() common.Digest { md := block.BlockHeader() e.Logger.Debug("Block verification started", zap.Uint64("round", md.Round)) start := time.Now() @@ -2136,8 +2137,8 @@ func (e *Epoch) createFinalizedBlockVerificationTask(block Block, finalization * } } -func (e *Epoch) createNotarizedBlockVerificationTask(block Block, notarization Notarization) func() Digest { - return func() Digest { +func (e *Epoch) createNotarizedBlockVerificationTask(block common.Block, notarization common.Notarization) func() common.Digest { + return func() common.Digest { md := block.BlockHeader() e.Logger.Debug("Block verification started", zap.Uint64("round", md.Round)) @@ -2192,7 +2193,7 @@ func (e *Epoch) createNotarizedBlockVerificationTask(block Block, notarization N // VerifyBlockMessageVote checks if we have the block in the future messages map. // If so, it means we have already verified the vote associated with this proposal. // If not, it verifies that the vote corresponds to the block proposed, and that the vote is properly signed. -func (e *Epoch) VerifyBlockMessageVote(from NodeID, md BlockHeader, vote Vote) error { +func (e *Epoch) VerifyBlockMessageVote(from common.NodeID, md common.BlockHeader, vote common.Vote) error { msgsForRound, exists := e.futureMessages[string(from)][md.Round] if exists && msgsForRound.proposal != nil { bh := msgsForRound.proposal.Block.BlockHeader() @@ -2218,16 +2219,16 @@ func (e *Epoch) VerifyBlockMessageVote(from NodeID, md BlockHeader, vote Vote) e return nil } -func (e *Epoch) verifyProposalMetadataAndBlacklist(block Block) bool { +func (e *Epoch) verifyProposalMetadataAndBlacklist(block common.Block) bool { bh := block.BlockHeader() var expectedSeq uint64 - var expectedPrevDigest Digest + var expectedPrevDigest common.Digest // Else, either it's not the first block, or we haven't committed the first block, and it is the first block. // If it's the latter we have nothing else to do. // If it's the former, we need to find the parent of the block and ensure it is correct. - prevBlacklist := NewBlacklist(uint16(len(e.nodeIDs))) + prevBlacklist := common.NewBlacklist(uint16(len(e.nodeIDs))) if bh.Seq > 0 { prevBlock, _, found := e.locateBlock(bh.Seq-1, bh.Prev[:]) if !found { @@ -2244,7 +2245,7 @@ func (e *Epoch) verifyProposalMetadataAndBlacklist(block Block) bool { prevBlacklist = prevBlock.Blacklist() if prevBlacklist.IsEmpty() { - prevBlacklist = NewBlacklist(uint16(len(e.nodeIDs))) + prevBlacklist = common.NewBlacklist(uint16(len(e.nodeIDs))) } } @@ -2255,9 +2256,9 @@ func (e *Epoch) verifyProposalMetadataAndBlacklist(block Block) bool { digest := block.BlockHeader().Digest - expectedBH := BlockHeader{ + expectedBH := common.BlockHeader{ Digest: digest, - ProtocolMetadata: ProtocolMetadata{ + ProtocolMetadata: common.ProtocolMetadata{ Round: e.round, Seq: expectedSeq, Epoch: e.Epoch, @@ -2282,7 +2283,7 @@ func (e *Epoch) verifyProposalMetadataAndBlacklist(block Block) bool { // 2) Else, on storage. // Compares to the given digest, and if it's the same, returns it. // Otherwise, returns false. -func (e *Epoch) locateBlock(seq uint64, digest []byte) (VerifiedBlock, *notarizationOrFinalization, bool) { +func (e *Epoch) locateBlock(seq uint64, digest []byte) (common.VerifiedBlock, *notarizationOrFinalization, bool) { // TODO index rounds by digest too to make it quicker // TODO: optimize this by building an index from digest to round for _, round := range e.rounds { @@ -2364,14 +2365,14 @@ func (e *Epoch) buildBlock() { e.Logger.Debug("Blacklist updated", zap.Uint64("round", metadata.Round), - zap.String("Update", blacklistUpdatesAsString(updates)), + zap.String("Update", common.BlacklistUpdatesAsString(updates)), zap.Stringer("prev", &prevBlacklist), zap.Stringer("next", &nextBlacklist)) buildTheBlock := e.createBlockBuildingTask(metadata, nextBlacklist) round := e.round - task := func() Digest { + task := func() common.Digest { digest := buildTheBlock() e.lock.Lock() defer e.lock.Unlock() @@ -2383,8 +2384,8 @@ func (e *Epoch) buildBlock() { e.buildBlockScheduler.ScheduleOrReplace(task) } -func (e *Epoch) retrieveBlacklistOfParentBlock(metadata ProtocolMetadata) (Blacklist, bool) { - var blacklist Blacklist +func (e *Epoch) retrieveBlacklistOfParentBlock(metadata common.ProtocolMetadata) (common.Blacklist, bool) { + var blacklist common.Blacklist if metadata.Seq > 0 { prevBlock, _, ok := e.locateBlock(metadata.Seq-1, metadata.Prev[:]) if !ok { @@ -2393,26 +2394,26 @@ func (e *Epoch) retrieveBlacklistOfParentBlock(metadata ProtocolMetadata) (Black zap.Uint64("seq", metadata.Seq), zap.Stringer("digest", metadata.Prev)) e.haltedError = fmt.Errorf("failed locating previous block (%d)", metadata.Seq) - return Blacklist{}, false + return common.Blacklist{}, false } blacklist = prevBlock.Blacklist() } if blacklist.IsEmpty() { - blacklist = NewBlacklist(uint16(len(e.nodeIDs))) + blacklist = common.NewBlacklist(uint16(len(e.nodeIDs))) } return blacklist, true } -func (e *Epoch) createBlockBuildingTask(metadata ProtocolMetadata, blacklist Blacklist) func() Digest { +func (e *Epoch) createBlockBuildingTask(metadata common.ProtocolMetadata, blacklist common.Blacklist) func() common.Digest { e.blockBuilderCancelFunc() e.blockBuilderCtx, e.blockBuilderCancelFunc = context.WithCancel(e.finishCtx) context := e.blockBuilderCtx cancel := e.blockBuilderCancelFunc - return func() Digest { + return func() common.Digest { block, ok := e.BlockBuilder.BuildBlock(context, metadata, blacklist) e.lock.Lock() @@ -2425,7 +2426,7 @@ func (e *Epoch) createBlockBuildingTask(metadata ProtocolMetadata, blacklist Bla default: e.Logger.Warn("Failed building block") } - return Digest{} + return common.Digest{} } e.proposeBlock(block) @@ -2434,7 +2435,7 @@ func (e *Epoch) createBlockBuildingTask(metadata ProtocolMetadata, blacklist Bla } } -func (e *Epoch) proposeBlock(block VerifiedBlock) error { +func (e *Epoch) proposeBlock(block common.VerifiedBlock) error { md := block.BlockHeader() // Write record to WAL before broadcasting it, so that @@ -2454,7 +2455,7 @@ func (e *Epoch) proposeBlock(block VerifiedBlock) error { return errors.New("failed to store block proposed by me") } - blockRecord := BlockRecord(block.BlockHeader(), rawBlock) + blockRecord := common.BlockRecord(block.BlockHeader(), rawBlock) if err := e.WAL.Append(blockRecord); err != nil { e.Logger.Error("Failed appending block to WAL", zap.Error(err)) return err @@ -2464,8 +2465,8 @@ func (e *Epoch) proposeBlock(block VerifiedBlock) error { zap.Int("size", len(rawBlock)), zap.Stringer("digest", md.Digest)) - proposal := &Message{ - VerifiedBlockMessage: &VerifiedBlockMessage{ + proposal := &common.Message{ + VerifiedBlockMessage: &common.VerifiedBlockMessage{ VerifiedBlock: block, Vote: vote, }, @@ -2483,15 +2484,15 @@ func (e *Epoch) proposeBlock(block VerifiedBlock) error { } // Metadata returns the metadata of the next expected block of the epoch. -func (e *Epoch) Metadata() ProtocolMetadata { +func (e *Epoch) Metadata() common.ProtocolMetadata { e.lock.Lock() defer e.lock.Unlock() return e.metadata() } -func (e *Epoch) metadata() ProtocolMetadata { - var prev Digest +func (e *Epoch) metadata() common.ProtocolMetadata { + var prev common.Digest seq := e.nextSeqToCommit() highestRound := e.getHighestRound() @@ -2510,7 +2511,7 @@ func (e *Epoch) metadata() ProtocolMetadata { } } - md := ProtocolMetadata{ + md := common.ProtocolMetadata{ Round: e.round, Seq: seq, Epoch: e.Epoch, @@ -2527,7 +2528,7 @@ func (e *Epoch) triggerEmptyBlockNotarization(round uint64) { return } - emptyVote := ToBeSignedEmptyVote{EmptyVoteMetadata: EmptyVoteMetadata{ + emptyVote := common.ToBeSignedEmptyVote{EmptyVoteMetadata: common.EmptyVoteMetadata{ Round: round, Epoch: e.Epoch, }} @@ -2537,7 +2538,7 @@ func (e *Epoch) triggerEmptyBlockNotarization(round uint64) { return } - emptyVoteRecord := NewEmptyVoteRecord(emptyVote) + emptyVoteRecord := common.NewEmptyVoteRecord(emptyVote) if err := e.WAL.Append(emptyVoteRecord); err != nil { e.Logger.Error("Failed appending empty vote", zap.Error(err)) return @@ -2549,12 +2550,12 @@ func (e *Epoch) triggerEmptyBlockNotarization(round uint64) { emptyVotes := e.getOrCreateEmptyVoteSetForRound(round) emptyVotes.timedOut = true - signedEV := EmptyVote{Vote: emptyVote, Signature: Signature{Signer: e.ID, Value: rawSig}} + signedEV := common.EmptyVote{Vote: emptyVote, Signature: common.Signature{Signer: e.ID, Value: rawSig}} // Add our own empty vote to the set emptyVotes.votes[string(e.ID)] = &signedEV - e.Comm.Broadcast(&Message{EmptyVoteMessage: &signedEV}) + e.Comm.Broadcast(&common.Message{EmptyVoteMessage: &signedEV}) e.addEmptyVoteRebroadcastTimeout() @@ -2582,7 +2583,7 @@ func (e *Epoch) emptyVoteTimeoutTaskRunner(_ []string) { } e.Logger.Debug("Rebroadcasting empty vote because round has not advanced", zap.Uint64("round", ourVote.Vote.Round)) - e.Comm.Broadcast(&Message{EmptyVoteMessage: ourVote}) + e.Comm.Broadcast(&common.Message{EmptyVoteMessage: ourVote}) } func (e *Epoch) addEmptyVoteRebroadcastTimeout() { @@ -2698,18 +2699,18 @@ func (e *Epoch) monitorProgress(round uint64) { } } -func (e *Epoch) retrieveLastPersistedBlacklist() (Blacklist, bool) { +func (e *Epoch) retrieveLastPersistedBlacklist() (common.Blacklist, bool) { e.lock.Lock() defer e.lock.Unlock() - var blacklist Blacklist + var blacklist common.Blacklist // This can be the first block, in which case we don't have a blacklist. if e.lastBlock != nil { // If we have a last block that is non-nil, it should have a verified block inside. if e.lastBlock.VerifiedBlock == nil { e.Logger.Error("Last block is nil") e.haltedError = fmt.Errorf("last block is nil") - return Blacklist{}, false + return common.Blacklist{}, false } blacklist = e.lastBlock.VerifiedBlock.Blacklist() @@ -2736,7 +2737,7 @@ func (e *Epoch) startRound() error { return nil } -func (e *Epoch) doProposed(block VerifiedBlock) error { +func (e *Epoch) doProposed(block common.VerifiedBlock) error { vote, err := e.voteOnBlock(block) if err != nil { return err @@ -2746,7 +2747,7 @@ func (e *Epoch) doProposed(block VerifiedBlock) error { // We do not write the vote to the WAL as we have written the block itself to the WAL // and we can always restore the block and sign it again if needed. - voteMsg := &Message{ + voteMsg := &common.Message{ VoteMessage: &vote, } @@ -2759,15 +2760,15 @@ func (e *Epoch) doProposed(block VerifiedBlock) error { return e.handleVoteMessage(&vote, e.ID) } -func (e *Epoch) voteOnBlock(block VerifiedBlock) (Vote, error) { - vote := ToBeSignedVote{BlockHeader: block.BlockHeader()} +func (e *Epoch) voteOnBlock(block common.VerifiedBlock) (common.Vote, error) { + vote := common.ToBeSignedVote{BlockHeader: block.BlockHeader()} sig, err := vote.Sign(e.Signer) if err != nil { - return Vote{}, fmt.Errorf("failed signing vote %w", err) + return common.Vote{}, fmt.Errorf("failed signing vote %w", err) } - sv := Vote{ - Signature: Signature{ + sv := common.Vote{ + Signature: common.Signature{ Signer: e.ID, Value: sig, }, @@ -2842,24 +2843,24 @@ func (e *Epoch) doNotarized(r uint64) error { return errors.Join(err1, err2) } -func (e *Epoch) constructFinalizeVoteMessage(md BlockHeader) (FinalizeVote, *Message, error) { - f := ToBeSignedFinalization{BlockHeader: md} +func (e *Epoch) constructFinalizeVoteMessage(md common.BlockHeader) (common.FinalizeVote, *common.Message, error) { + f := common.ToBeSignedFinalization{BlockHeader: md} signature, err := f.Sign(e.Signer) if err != nil { - return FinalizeVote{}, nil, fmt.Errorf("failed signing vote %w", err) + return common.FinalizeVote{}, nil, fmt.Errorf("failed signing vote %w", err) } - vote := FinalizeVote{ - Signature: Signature{ + vote := common.FinalizeVote{ + Signature: common.Signature{ Signer: e.ID, Value: signature, }, - Finalization: ToBeSignedFinalization{ + Finalization: common.ToBeSignedFinalization{ BlockHeader: md, }, } - finalizationMsg := &Message{ + finalizationMsg := &common.Message{ FinalizeVote: &vote, } return vote, finalizationMsg, nil @@ -2873,38 +2874,38 @@ func (e *Epoch) maybeLoadFutureMessages() error { for from, messagesFromNode := range e.futureMessages { if msgs, exists := messagesFromNode[round]; exists { if msgs.proposal != nil { - if err := e.handleBlockMessage(msgs.proposal, NodeID(from)); err != nil { + if err := e.handleBlockMessage(msgs.proposal, common.NodeID(from)); err != nil { return err } } if msgs.finalization != nil { - if err := e.handleFinalizationMessage(msgs.finalization, NodeID(from)); err != nil { + if err := e.handleFinalizationMessage(msgs.finalization, common.NodeID(from)); err != nil { return err } } if msgs.vote != nil { - if err := e.handleVoteMessage(msgs.vote, NodeID(from)); err != nil { + if err := e.handleVoteMessage(msgs.vote, common.NodeID(from)); err != nil { return err } } if msgs.notarization != nil { - if err := e.handleNotarizationMessage(msgs.notarization, NodeID(from)); err != nil { + if err := e.handleNotarizationMessage(msgs.notarization, common.NodeID(from)); err != nil { return err } } if msgs.finalizeVote != nil { - if err := e.handleFinalizeVoteMessage(msgs.finalizeVote, NodeID(from)); err != nil { + if err := e.handleFinalizeVoteMessage(msgs.finalizeVote, common.NodeID(from)); err != nil { return err } } if e.futureMessagesForRoundEmpty(msgs) { e.Logger.Debug("Deleting future messages", - zap.Stringer("from", NodeID(from)), zap.Uint64("round", round)) + zap.Stringer("from", common.NodeID(from)), zap.Uint64("round", round)) delete(messagesFromNode, round) } } else { e.Logger.Debug("No future messages received for this round", - zap.Stringer("from", NodeID(from)), zap.Uint64("round", round)) + zap.Stringer("from", common.NodeID(from)), zap.Uint64("round", round)) } } @@ -2916,7 +2917,7 @@ func (e *Epoch) maybeLoadFutureMessages() error { } } else { for from, vote := range emptyVotes.votes { - if err := e.handleEmptyVoteMessage(vote, NodeID(from)); err != nil { + if err := e.handleEmptyVoteMessage(vote, common.NodeID(from)); err != nil { return err } } @@ -2937,7 +2938,7 @@ func (e *Epoch) futureMessagesForRoundEmpty(msgs *messagesForRound) bool { // storeProposal stores a block in the epochs memory(NOT storage). // it creates a new round with the block and stores it in the rounds map. -func (e *Epoch) storeProposal(block VerifiedBlock) bool { +func (e *Epoch) storeProposal(block common.VerifiedBlock) bool { md := block.BlockHeader() // Have we already received a block from that node? @@ -2962,12 +2963,12 @@ func (e *Epoch) storeProposal(block VerifiedBlock) bool { } // HandleRequest processes a request and returns a response. It also sends a response to the sender. -func (e *Epoch) handleReplicationRequest(req *ReplicationRequest, from NodeID) error { +func (e *Epoch) handleReplicationRequest(req *common.ReplicationRequest, from common.NodeID) error { e.Logger.Debug("Received replication request", zap.Stringer("from", from), zap.Int("num seqs", len(req.Seqs)), zap.Int("num rounds", len(req.Rounds)), zap.Uint64("latest round", req.LatestRound)) if !e.ReplicationEnabled { return nil } - response := &VerifiedReplicationResponse{} + response := &common.VerifiedReplicationResponse{} if len(req.Seqs) > int(e.MaxRoundWindow) || len(req.Rounds) > int(e.MaxRoundWindow) { e.Logger.Info("Replication request exceeds maximum allowed seqs and rounds", @@ -2986,7 +2987,7 @@ func (e *Epoch) handleReplicationRequest(req *ReplicationRequest, from NodeID) e } if req.LatestFinalizedSeq > 0 { if e.lastBlock != nil && e.lastBlock.Finalization.Finalization.Seq > req.LatestFinalizedSeq { - response.LatestFinalizedSeq = &VerifiedQuorumRound{ + response.LatestFinalizedSeq = &common.VerifiedQuorumRound{ VerifiedBlock: e.lastBlock.VerifiedBlock, Finalization: &e.lastBlock.Finalization, } @@ -2995,7 +2996,7 @@ func (e *Epoch) handleReplicationRequest(req *ReplicationRequest, from NodeID) e seqs := req.Seqs slices.Sort(seqs) - seqData := make([]VerifiedQuorumRound, len(seqs)) + seqData := make([]common.VerifiedQuorumRound, len(seqs)) for i, seq := range seqs { quorumRound := e.locateQuorumRecord(seq) if quorumRound == nil { @@ -3008,7 +3009,7 @@ func (e *Epoch) handleReplicationRequest(req *ReplicationRequest, from NodeID) e } rounds := req.Rounds - roundData := make([]VerifiedQuorumRound, 0, len(rounds)) + roundData := make([]common.VerifiedQuorumRound, 0, len(rounds)) slices.Sort(rounds) for _, roundNum := range rounds { quorumRound := e.locateQuorumRecordByRound(roundNum) @@ -3019,7 +3020,7 @@ func (e *Epoch) handleReplicationRequest(req *ReplicationRequest, from NodeID) e roundData = append(roundData, *quorumRound) } - data := make([]VerifiedQuorumRound, 0, len(seqData)+len(roundData)) + data := make([]common.VerifiedQuorumRound, 0, len(seqData)+len(roundData)) data = append(data, seqData...) data = append(data, roundData...) response.Data = data @@ -3030,19 +3031,19 @@ func (e *Epoch) handleReplicationRequest(req *ReplicationRequest, from NodeID) e } e.Logger.Debug("Sending response back to node", zap.Stringer("to", from), zap.Int("num rounds", len(data))) - msg := &Message{VerifiedReplicationResponse: response} + msg := &common.Message{VerifiedReplicationResponse: response} e.Comm.Send(msg, from) return nil } // locateQuorumRecord locates a block with a notarization or finalization in the epochs memory or storage. -func (e *Epoch) locateQuorumRecord(seq uint64) *VerifiedQuorumRound { +func (e *Epoch) locateQuorumRecord(seq uint64) *common.VerifiedQuorumRound { var notarizedRound *Round for _, round := range e.rounds { blockSeq := round.block.BlockHeader().Seq if blockSeq == seq { if round.finalization != nil { - return &VerifiedQuorumRound{ + return &common.VerifiedQuorumRound{ VerifiedBlock: round.block, Finalization: round.finalization, } @@ -3059,7 +3060,7 @@ func (e *Epoch) locateQuorumRecord(seq uint64) *VerifiedQuorumRound { if notarizedRound != nil { // we have a notarization, but no finalization, so we return the notarization - return &VerifiedQuorumRound{ + return &common.VerifiedQuorumRound{ VerifiedBlock: notarizedRound.block, Notarization: notarizedRound.notarization, } @@ -3076,20 +3077,20 @@ func (e *Epoch) locateQuorumRecord(seq uint64) *VerifiedQuorumRound { return nil } - return &VerifiedQuorumRound{ + return &common.VerifiedQuorumRound{ VerifiedBlock: block, Finalization: &finalization, } } -func (e *Epoch) locateQuorumRecordByRound(targetRound uint64) *VerifiedQuorumRound { - var qr *VerifiedQuorumRound +func (e *Epoch) locateQuorumRecordByRound(targetRound uint64) *common.VerifiedQuorumRound { + var qr *common.VerifiedQuorumRound for _, round := range e.rounds { blockRound := round.block.BlockHeader().Round if blockRound == targetRound { if round.finalization != nil || round.notarization != nil { - qr = &VerifiedQuorumRound{ + qr = &common.VerifiedQuorumRound{ VerifiedBlock: round.block, Finalization: round.finalization, Notarization: round.notarization, @@ -3106,7 +3107,7 @@ func (e *Epoch) locateQuorumRecordByRound(targetRound uint64) *VerifiedQuorumRou qr.EmptyNotarization = emptyVoteForRound.emptyNotarization return qr } - qr = &VerifiedQuorumRound{ + qr = &common.VerifiedQuorumRound{ EmptyNotarization: emptyVoteForRound.emptyNotarization, } } @@ -3136,7 +3137,7 @@ func (e *Epoch) haveNotFinalizedNotarizedRound() (uint64, bool) { return minRoundNum, found } -func (e *Epoch) handleBlockDigestRequest(req *BlockDigestRequest, from NodeID) error { +func (e *Epoch) handleBlockDigestRequest(req *common.BlockDigestRequest, from common.NodeID) error { e.Logger.Debug("Received block digest request", zap.Stringer("from", from), zap.Uint64("seq", req.Seq)) block, notarizationOrFinalization, ok := e.locateBlock(req.Seq, req.Digest[:]) @@ -3150,22 +3151,22 @@ func (e *Epoch) handleBlockDigestRequest(req *BlockDigestRequest, from NodeID) e return nil } - qr := VerifiedQuorumRound{ + qr := common.VerifiedQuorumRound{ VerifiedBlock: block, Notarization: notarizationOrFinalization.Notarization, Finalization: notarizationOrFinalization.Finalization, } - response := &VerifiedReplicationResponse{ - Data: []VerifiedQuorumRound{qr}, + response := &common.VerifiedReplicationResponse{ + Data: []common.VerifiedQuorumRound{qr}, } - msg := &Message{VerifiedReplicationResponse: response} + msg := &common.Message{VerifiedReplicationResponse: response} e.Comm.Send(msg, from) return nil } -func (e *Epoch) handleReplicationResponse(resp *ReplicationResponse, from NodeID) error { +func (e *Epoch) handleReplicationResponse(resp *common.ReplicationResponse, from common.NodeID) error { if !e.ReplicationEnabled { return nil } @@ -3203,7 +3204,7 @@ func (e *Epoch) handleReplicationResponse(resp *ReplicationResponse, from NodeID return e.processReplicationState() } -func (e *Epoch) verifyQuorumRound(q QuorumRound, from NodeID) error { +func (e *Epoch) verifyQuorumRound(q common.QuorumRound, from common.NodeID) error { if err := q.VerifyQCConsistentWithBlock(); err != nil { return err } @@ -3232,7 +3233,7 @@ func (e *Epoch) verifyQuorumRound(q QuorumRound, from NodeID) error { return nil } -func (e *Epoch) processEmptyNotarization(emptyNotarization *EmptyNotarization) error { +func (e *Epoch) processEmptyNotarization(emptyNotarization *common.EmptyNotarization) error { e.Logger.Debug("Processing empty notarization due to replication", zap.Uint64("round", emptyNotarization.Vote.Round), zap.Uint64("our round", e.round)) emptyVotes := e.getOrCreateEmptyVoteSetForRound(emptyNotarization.Vote.Round) emptyVotes.emptyNotarization = emptyNotarization @@ -3247,7 +3248,7 @@ func (e *Epoch) processEmptyNotarization(emptyNotarization *EmptyNotarization) e // processQuorumRound processes a quorum round received from another node. // It verifies the quorum round and stores it in the replication state if valid. -func (e *Epoch) processQuorumRound(round *QuorumRound, from NodeID) error { +func (e *Epoch) processQuorumRound(round *common.QuorumRound, from common.NodeID) error { if round == nil { return nil } @@ -3374,8 +3375,8 @@ func (e *Epoch) getHighestRound() *Round { return nil } -func (e *Epoch) getHighestEmptyNotarization() *EmptyNotarization { - var emptyNotarization *EmptyNotarization +func (e *Epoch) getHighestEmptyNotarization() *common.EmptyNotarization { + var emptyNotarization *common.EmptyNotarization var max uint64 for round, emptyVote := range e.emptyVotes { if round > max && emptyVote.emptyNotarization != nil { @@ -3387,7 +3388,7 @@ func (e *Epoch) getHighestEmptyNotarization() *EmptyNotarization { return emptyNotarization } -func (e *Epoch) getLatestVerifiedQuorumRound() *VerifiedQuorumRound { +func (e *Epoch) getLatestVerifiedQuorumRound() *common.VerifiedQuorumRound { return GetLatestVerifiedQuorumRound( e.getHighestRound(), e.getHighestEmptyNotarization(), @@ -3404,16 +3405,16 @@ func (e *Epoch) isWithinMaxRoundWindow(round uint64) bool { return e.round < round && round-e.round < e.MaxRoundWindow } -func (e *Epoch) retrieveBlockOrHalt(seq uint64) (VerifiedBlock, Finalization, bool) { +func (e *Epoch) retrieveBlockOrHalt(seq uint64) (common.VerifiedBlock, common.Finalization, bool) { block, finalization, err := e.Storage.Retrieve(seq) - if err == ErrBlockNotFound { - return nil, Finalization{}, false + if err == common.ErrBlockNotFound { + return nil, common.Finalization{}, false } if err != nil { e.Logger.Error("Failed retrieving block from storage", zap.Uint64("seq", seq), zap.Error(err)) e.haltedError = err - return nil, Finalization{}, false + return nil, common.Finalization{}, false } return block, finalization, true @@ -3425,13 +3426,13 @@ func (e *Epoch) nextSeqToCommit() uint64 { } // SortNodes sorts the nodes in place by their byte representations. -func SortNodes(nodes Nodes) { - slices.SortFunc(nodes, func(a, b Node) int { +func SortNodes(nodes common.Nodes) { + slices.SortFunc(nodes, func(a, b common.Node) int { return bytes.Compare(a.Node[:], b.Node[:]) }) } -func LeaderForRound(nodes []NodeID, r uint64) NodeID { +func LeaderForRound(nodes []common.NodeID, r uint64) common.NodeID { n := len(nodes) return nodes[r%uint64(n)] } @@ -3448,14 +3449,14 @@ type messagesFromNode map[string]map[uint64]*messagesForRound type messagesForRound struct { proposalBeingProcessed bool - proposal *BlockMessage - vote *Vote - finalizeVote *FinalizeVote - finalization *Finalization - notarization *Notarization + proposal *common.BlockMessage + vote *common.Vote + finalizeVote *common.FinalizeVote + finalization *common.Finalization + notarization *common.Notarization } type notarizationOrFinalization struct { - *Notarization - *Finalization + *common.Notarization + *common.Finalization } diff --git a/epoch_failover_test.go b/simplex/epoch_failover_test.go similarity index 99% rename from epoch_failover_test.go rename to simplex/epoch_failover_test.go index 9db6a9b1..f8489ed2 100644 --- a/epoch_failover_test.go +++ b/simplex/epoch_failover_test.go @@ -13,9 +13,9 @@ import ( "testing" "time" - "github.com/ava-labs/simplex" - . "github.com/ava-labs/simplex" + . "github.com/ava-labs/simplex/common" "github.com/ava-labs/simplex/record" + . "github.com/ava-labs/simplex/simplex" "github.com/ava-labs/simplex/testutil" "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" @@ -1170,7 +1170,7 @@ func TestEpochRebroadcastsEmptyVote(t *testing.T) { } emptyNotarization := testutil.NewEmptyNotarization(nodes, 0) - e.HandleMessage(&simplex.Message{ + e.HandleMessage(&Message{ EmptyNotarization: emptyNotarization, }, nodes[2]) diff --git a/epoch_multinode_test.go b/simplex/epoch_multinode_test.go similarity index 87% rename from epoch_multinode_test.go rename to simplex/epoch_multinode_test.go index 87b04ca3..74a88ea8 100644 --- a/epoch_multinode_test.go +++ b/simplex/epoch_multinode_test.go @@ -10,22 +10,23 @@ import ( "testing" "time" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" + "github.com/ava-labs/simplex/simplex" "github.com/ava-labs/simplex/testutil" "github.com/stretchr/testify/require" ) func TestSimplexRebroadcastFinalizationVotes(t *testing.T) { - nodes := []simplex.NodeID{{1}, {2}, {3}, {4}} + nodes := []common.NodeID{{1}, {2}, {3}, {4}} net := testutil.NewControlledNetwork(t, nodes) var allowFinalizeVotes atomic.Bool var numFinalizeVotesSent atomic.Uint32 - config := func(from simplex.NodeID) *testutil.TestNodeConfig { + config := func(from common.NodeID) *testutil.TestNodeConfig { return &testutil.TestNodeConfig{ - Comm: testutil.NewTestComm(from, net.BasicInMemoryNetwork, func(msg *simplex.Message, from simplex.NodeID, to simplex.NodeID) bool { + Comm: testutil.NewTestComm(from, net.BasicInMemoryNetwork, func(msg *common.Message, from common.NodeID, to common.NodeID) bool { if msg.Finalization != nil && !allowFinalizeVotes.Load() { return false } @@ -121,7 +122,7 @@ func TestSimplexRebroadcastFinalizationVotes(t *testing.T) { } func TestSimplexMultiNodeSimple(t *testing.T) { - nodes := []simplex.NodeID{{1}, {2}, {3}, {4}} + nodes := []common.NodeID{{1}, {2}, {3}, {4}} net := testutil.NewControlledNetwork(t, nodes) testutil.NewControlledSimplexNode(t, nodes[0], net, nil) testutil.NewControlledSimplexNode(t, nodes[1], net, nil) @@ -139,7 +140,7 @@ func TestSimplexMultiNodeSimple(t *testing.T) { } } -func dontVoteFilter(msg *simplex.Message, _, _ simplex.NodeID) bool { +func dontVoteFilter(msg *common.Message, _, _ common.NodeID) bool { if msg.VoteMessage != nil || msg.EmptyVoteMessage != nil || msg.Notarization != nil || msg.FinalizeVote != nil { return false } @@ -147,7 +148,7 @@ func dontVoteFilter(msg *simplex.Message, _, _ simplex.NodeID) bool { } func TestSimplexMultiNodeBlacklist(t *testing.T) { - nodes := []simplex.NodeID{{1}, {2}, {3}, {4}} + nodes := []common.NodeID{{1}, {2}, {3}, {4}} net := testutil.NewControlledNetwork(t, nodes) testEpochConfig := &testutil.TestNodeConfig{ ReplicationEnabled: true, @@ -187,10 +188,10 @@ func TestSimplexMultiNodeBlacklist(t *testing.T) { for _, n := range net.Instances[:3] { block := n.Storage.WaitForBlockCommit(uint64(3)) blacklist := block.Blacklist() - require.Equal(t, simplex.Blacklist{ + require.Equal(t, common.Blacklist{ NodeCount: 4, - SuspectedNodes: simplex.SuspectedNodes{{NodeIndex: 3, SuspectingCount: 1, OrbitSuspected: 1}}, - Updates: []simplex.BlacklistUpdate{{NodeIndex: 3, Type: simplex.BlacklistOpType_NodeSuspected}}, + SuspectedNodes: common.SuspectedNodes{{NodeIndex: 3, SuspectingCount: 1, OrbitSuspected: 1}}, + Updates: []common.BlacklistUpdate{{NodeIndex: 3, Type: common.BlacklistOpType_NodeSuspected}}, }, blacklist) } @@ -203,20 +204,20 @@ func TestSimplexMultiNodeBlacklist(t *testing.T) { for _, n := range net.Instances[:3] { block := n.Storage.WaitForBlockCommit(uint64(4)) blacklist := block.Blacklist() - require.Equal(t, simplex.Blacklist{ + require.Equal(t, common.Blacklist{ NodeCount: 4, - SuspectedNodes: simplex.SuspectedNodes{{NodeIndex: 3, SuspectingCount: 2, OrbitSuspected: 1}}, - Updates: []simplex.BlacklistUpdate{{NodeIndex: 3, Type: simplex.BlacklistOpType_NodeSuspected}}, + SuspectedNodes: common.SuspectedNodes{{NodeIndex: 3, SuspectingCount: 2, OrbitSuspected: 1}}, + Updates: []common.BlacklistUpdate{{NodeIndex: 3, Type: common.BlacklistOpType_NodeSuspected}}, }, blacklist) } // Wait for the node to replicate the missing blocks. net.Instances[3].TriggerNewBlock() block := net.Instances[3].Storage.WaitForBlockCommit(4) - require.Equal(t, simplex.Blacklist{ + require.Equal(t, common.Blacklist{ NodeCount: 4, - SuspectedNodes: simplex.SuspectedNodes{{NodeIndex: 3, SuspectingCount: 2, OrbitSuspected: 1}}, - Updates: []simplex.BlacklistUpdate{{NodeIndex: 3, Type: simplex.BlacklistOpType_NodeSuspected}}, + SuspectedNodes: common.SuspectedNodes{{NodeIndex: 3, SuspectingCount: 2, OrbitSuspected: 1}}, + Updates: []common.BlacklistUpdate{{NodeIndex: 3, Type: common.BlacklistOpType_NodeSuspected}}, }, block.Blacklist()) // Make another block. @@ -259,7 +260,7 @@ func TestSimplexMultiNodeBlacklist(t *testing.T) { testutil.WaitForBlockProposerTimeout(t, n.E, &n.E.StartTime, 11) } - var lastBlacklist simplex.Blacklist + var lastBlacklist common.Blacklist // Create two blocks for i := 0; i < 2; i++ { @@ -292,8 +293,8 @@ func TestSimplexMultiNodeBlacklist(t *testing.T) { } } -func onlySendBlockProposalsAndVotes(splitNodes []simplex.NodeID) testutil.MessageFilter { - return func(m *simplex.Message, from simplex.NodeID, to simplex.NodeID) bool { +func onlySendBlockProposalsAndVotes(splitNodes []common.NodeID) testutil.MessageFilter { + return func(m *common.Message, from common.NodeID, to common.NodeID) bool { if m.BlockMessage != nil { return true } @@ -309,10 +310,10 @@ func onlySendBlockProposalsAndVotes(splitNodes []simplex.NodeID) testutil.Messag // TestSplitVotes ensures that nodes who have timeout out, while the rest of the network has // progressed due to notarizations, are able to collect the notarizations and continue func TestSplitVotes(t *testing.T) { - nodes := []simplex.NodeID{{1}, {2}, {3}, {4}} + nodes := []common.NodeID{{1}, {2}, {3}, {4}} net := testutil.NewControlledNetwork(t, nodes) - config := func(from simplex.NodeID) *testutil.TestNodeConfig { + config := func(from common.NodeID) *testutil.TestNodeConfig { return &testutil.TestNodeConfig{ Comm: testutil.NewTestComm(from, net.BasicInMemoryNetwork, onlySendBlockProposalsAndVotes(nodes[2:])), } @@ -385,7 +386,7 @@ func TestSplitVotes(t *testing.T) { // denyFinalizationMessages blocks any messages that would cause nodes in // a network to index a block in storage. -func denyFinalizationMessages(msg *simplex.Message, _, _ simplex.NodeID) bool { +func denyFinalizationMessages(msg *common.Message, _, _ common.NodeID) bool { if msg.FinalizeVote != nil { return false } @@ -396,7 +397,7 @@ func denyFinalizationMessages(msg *simplex.Message, _, _ simplex.NodeID) bool { return true } -func onlyAllowEmptyRoundMessages(msg *simplex.Message, _, _ simplex.NodeID) bool { +func onlyAllowEmptyRoundMessages(msg *common.Message, _, _ common.NodeID) bool { if msg.EmptyNotarization != nil { return true } diff --git a/epoch_test.go b/simplex/epoch_test.go similarity index 98% rename from epoch_test.go rename to simplex/epoch_test.go index f8680485..974022c6 100644 --- a/epoch_test.go +++ b/simplex/epoch_test.go @@ -16,9 +16,9 @@ import ( "testing" "time" - "github.com/ava-labs/simplex" - . "github.com/ava-labs/simplex" + . "github.com/ava-labs/simplex/common" "github.com/ava-labs/simplex/record" + . "github.com/ava-labs/simplex/simplex" "github.com/ava-labs/simplex/testutil" "github.com/stretchr/testify/require" @@ -83,7 +83,7 @@ func TestFinalizeSameSequence(t *testing.T) { Seq: 1, // set next seq to 1 not 2 Prev: initialBlock.VerifiedBlock.BlockHeader().Digest, } - vb, ok := bb.BuildBlock(context.Background(), md, simplex.Blacklist{ + vb, ok := bb.BuildBlock(context.Background(), md, Blacklist{ NodeCount: uint16(len(e.EpochConfig.Comm.Nodes())), }) require.True(t, ok) @@ -97,8 +97,8 @@ func TestFinalizeSameSequence(t *testing.T) { // send block from leader vote, err := testutil.NewTestVote(block, nodes[2]) require.NoError(t, err) - err = e.HandleMessage(&simplex.Message{ - BlockMessage: &simplex.BlockMessage{ + err = e.HandleMessage(&Message{ + BlockMessage: &BlockMessage{ Vote: *vote, Block: block, }, @@ -112,7 +112,7 @@ func TestFinalizeSameSequence(t *testing.T) { // now lets send empty notarization emptyNotarization := testutil.NewEmptyNotarization(nodes, 1) - err = e.HandleMessage(&simplex.Message{ + err = e.HandleMessage(&Message{ EmptyNotarization: emptyNotarization, }, nodes[3]) require.NoError(t, err) @@ -226,7 +226,7 @@ func testFinalizeSameSequenceGap(t *testing.T, nodes []NodeID, numEmptyNotarizat Seq: seqToDoubleFinalize, Prev: finalizeVoteSeqs[seqToDoubleFinalize-1].Finalization.Digest, } - vb, ok := bb.BuildBlock(context.Background(), md, simplex.Blacklist{ + vb, ok := bb.BuildBlock(context.Background(), md, Blacklist{ NodeCount: uint16(len(e.EpochConfig.Comm.Nodes())), }) require.True(t, ok) @@ -245,8 +245,8 @@ func testFinalizeSameSequenceGap(t *testing.T, nodes []NodeID, numEmptyNotarizat // send block from leader vote, err := testutil.NewTestVote(block, leader) require.NoError(t, err) - err = e.HandleMessage(&simplex.Message{ - BlockMessage: &simplex.BlockMessage{ + err = e.HandleMessage(&Message{ + BlockMessage: &BlockMessage{ Vote: *vote, Block: block, }, @@ -262,7 +262,7 @@ func testFinalizeSameSequenceGap(t *testing.T, nodes []NodeID, numEmptyNotarizat startMissingNotarizationRound := finalizeVoteSeqs[seqToDoubleFinalize-1].Finalization.Round + 1 for i := startMissingNotarizationRound; i < md.Round; i++ { emptyNotarization := testutil.NewEmptyNotarization(nodes, i) - err = e.HandleMessage(&simplex.Message{ + err = e.HandleMessage(&Message{ EmptyNotarization: emptyNotarization, }, nodes[3]) require.NoError(t, err) @@ -1636,13 +1636,13 @@ func TestBlockDeserializer(t *testing.T) { // advanceRound progresses [e] to a new round. If [notarize] is set, the round will progress due to a notarization. // If [finalize] is set, the round will advance and the block will be indexed to storage. // If [injectedMD] is non-nil, it will be used as the metadata for the new block instead of generating one from the epoch. -func advanceRound(t *testing.T, e *simplex.Epoch, bb *testutil.TestBlockBuilder, notarize bool, finalize bool, injectedMD *ProtocolMetadata) (simplex.VerifiedBlock, *simplex.Notarization) { +func advanceRound(t *testing.T, e *Epoch, bb *testutil.TestBlockBuilder, notarize bool, finalize bool, injectedMD *ProtocolMetadata) (VerifiedBlock, *Notarization) { require.True(t, notarize || finalize, "must either notarize or finalize a round to advance") nextSeqToCommit := e.Storage.NumBlocks() nodes := e.Comm.Nodes() - quorum := simplex.Quorum(len(nodes)) + quorum := Quorum(len(nodes)) // leader is the proposer of the new block for the given round - leader := simplex.LeaderForRound(nodes.NodeIDs(), e.Metadata().Round) + leader := LeaderForRound(nodes.NodeIDs(), e.Metadata().Round) md := e.Metadata() if injectedMD != nil { md = *injectedMD @@ -1651,7 +1651,7 @@ func advanceRound(t *testing.T, e *simplex.Epoch, bb *testutil.TestBlockBuilder, // only create blocks if we are not the node running the epoch isEpochNode := leader.Equals(e.ID) if !isEpochNode { - _, ok := bb.BuildBlock(context.Background(), md, simplex.Blacklist{ + _, ok := bb.BuildBlock(context.Background(), md, Blacklist{ NodeCount: uint16(len(e.EpochConfig.Comm.Nodes())), }) require.True(t, ok) @@ -1663,8 +1663,8 @@ func advanceRound(t *testing.T, e *simplex.Epoch, bb *testutil.TestBlockBuilder, // send node a message from the leader vote, err := testutil.NewTestVote(block, leader) require.NoError(t, err) - err = e.HandleMessage(&simplex.Message{ - BlockMessage: &simplex.BlockMessage{ + err = e.HandleMessage(&Message{ + BlockMessage: &BlockMessage{ Vote: *vote, Block: block, }, @@ -1672,7 +1672,7 @@ func advanceRound(t *testing.T, e *simplex.Epoch, bb *testutil.TestBlockBuilder, require.NoError(t, err) } - var notarization *simplex.Notarization + var notarization *Notarization if notarize { // start at one since our node has already voted sigAggr := e.SignatureAggregatorCreator(nodes) diff --git a/fuzz_network_test.go b/simplex/fuzz_network_test.go similarity index 100% rename from fuzz_network_test.go rename to simplex/fuzz_network_test.go diff --git a/leak_test.go b/simplex/leak_test.go similarity index 100% rename from leak_test.go rename to simplex/leak_test.go diff --git a/long_running_test.go b/simplex/long_running_test.go similarity index 100% rename from long_running_test.go rename to simplex/long_running_test.go diff --git a/monitor.go b/simplex/monitor.go similarity index 95% rename from monitor.go rename to simplex/monitor.go index 1ab44ed2..21d25601 100644 --- a/monitor.go +++ b/simplex/monitor.go @@ -8,11 +8,12 @@ import ( "sync/atomic" "time" + "github.com/ava-labs/simplex/common" "go.uber.org/zap" ) type Monitor struct { - logger Logger + logger common.Logger close chan struct{} time atomic.Value ticks chan time.Time @@ -27,7 +28,7 @@ type futureTask struct { f func() } -func NewMonitor(startTime time.Time, logger Logger) *Monitor { +func NewMonitor(startTime time.Time, logger common.Logger) *Monitor { m := &Monitor{ cancelTask: func() {}, logger: logger, diff --git a/monitor_test.go b/simplex/monitor_test.go similarity index 100% rename from monitor_test.go rename to simplex/monitor_test.go diff --git a/pos_test.go b/simplex/pos_test.go similarity index 93% rename from pos_test.go rename to simplex/pos_test.go index 1d1d7f08..5111128c 100644 --- a/pos_test.go +++ b/simplex/pos_test.go @@ -8,7 +8,8 @@ import ( "testing" "time" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" + "github.com/ava-labs/simplex/simplex" "github.com/ava-labs/simplex/testutil" "github.com/stretchr/testify/require" ) @@ -21,11 +22,11 @@ func TestPoS(t *testing.T) { 4: 1, } - nodes := []simplex.NodeID{{1}, {2}, {3}, {4}} + nodes := []common.NodeID{{1}, {2}, {3}, {4}} - posSigAggregatorCreator := func(_ []simplex.Node) simplex.SignatureAggregator { + posSigAggregatorCreator := func(_ []common.Node) common.SignatureAggregator { return &testutil.TestSignatureAggregator{ - IsQuorumFunc: func(signatures []simplex.NodeID) bool { + IsQuorumFunc: func(signatures []common.NodeID) bool { var totalWeight uint64 for _, signer := range signatures { totalWeight += weights[int(signer[0])] diff --git a/recovery_test.go b/simplex/recovery_test.go similarity index 99% rename from recovery_test.go rename to simplex/recovery_test.go index 5320fc8f..e32f7da7 100644 --- a/recovery_test.go +++ b/simplex/recovery_test.go @@ -9,9 +9,9 @@ import ( "testing" "time" - "github.com/ava-labs/simplex" - . "github.com/ava-labs/simplex" + . "github.com/ava-labs/simplex/common" "github.com/ava-labs/simplex/record" + . "github.com/ava-labs/simplex/simplex" "github.com/ava-labs/simplex/testutil" "github.com/stretchr/testify/require" ) @@ -964,7 +964,7 @@ func TestWalRecoverySetsRoundCorrectly(t *testing.T) { } func TestRecoveryAndBroadcast(t *testing.T) { - nodes := []simplex.NodeID{{1}, {2}, {3}, []byte("recovering")} + nodes := []NodeID{{1}, {2}, {3}, []byte("recovering")} net := testutil.NewControlledNetwork(t, nodes) diff --git a/replication_request_test.go b/simplex/replication_request_test.go similarity index 84% rename from replication_request_test.go rename to simplex/replication_request_test.go index 3ce3435a..54ac1765 100644 --- a/replication_request_test.go +++ b/simplex/replication_request_test.go @@ -6,7 +6,8 @@ import ( "testing" "time" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" + "github.com/ava-labs/simplex/simplex" "github.com/ava-labs/simplex/testutil" "github.com/stretchr/testify/require" ) @@ -14,7 +15,7 @@ import ( // TestReplicationRequestIndexedBlocks tests replication requests for indexed blocks. func TestReplicationRequestIndexedBlocks(t *testing.T) { bb := testutil.NewTestBlockBuilder() - nodes := []simplex.NodeID{{1}, {2}, {3}, {4}} + nodes := []common.NodeID{{1}, {2}, {3}, {4}} comm := NewListenerComm(nodes) ctx := context.Background() conf, _, _ := testutil.DefaultTestNodeEpochConfig(t, nodes[0], comm, bb) @@ -31,8 +32,8 @@ func TestReplicationRequestIndexedBlocks(t *testing.T) { t.Cleanup(e.Stop) require.NoError(t, e.Start()) sequences := []uint64{0, 1, 2, 3} - req := &simplex.Message{ - ReplicationRequest: &simplex.ReplicationRequest{ + req := &common.Message{ + ReplicationRequest: &common.ReplicationRequest{ Seqs: sequences, LatestRound: numBlocks, }, @@ -53,8 +54,8 @@ func TestReplicationRequestIndexedBlocks(t *testing.T) { } // request out of scope - req = &simplex.Message{ - ReplicationRequest: &simplex.ReplicationRequest{ + req = &common.Message{ + ReplicationRequest: &common.ReplicationRequest{ Seqs: []uint64{11, 12, 13}, }, } @@ -69,7 +70,7 @@ func TestReplicationRequestIndexedBlocks(t *testing.T) { func TestReplicationRequestNotarizations(t *testing.T) { // generate 5 blocks & notarizations bb := testutil.NewTestBlockBuilder() - nodes := []simplex.NodeID{{1}, {2}, {3}, {4}} + nodes := []common.NodeID{{1}, {2}, {3}, {4}} comm := NewListenerComm(nodes) noop := testutil.NewNoopComm(nodes) conf, _, _ := testutil.DefaultTestNodeEpochConfig(t, nodes[0], noop, bb) @@ -81,11 +82,11 @@ func TestReplicationRequestNotarizations(t *testing.T) { require.NoError(t, e.Start()) numBlocks := uint64(5) - rounds := make(map[uint64]simplex.VerifiedQuorumRound) + rounds := make(map[uint64]common.VerifiedQuorumRound) for i := uint64(0); i < numBlocks; i++ { block, notarization := advanceRoundFromNotarization(t, e, bb) - rounds[i] = simplex.VerifiedQuorumRound{ + rounds[i] = common.VerifiedQuorumRound{ VerifiedBlock: block, Notarization: notarization, } @@ -97,8 +98,8 @@ func TestReplicationRequestNotarizations(t *testing.T) { for k := range rounds { seqs = append(seqs, k) } - req := &simplex.Message{ - ReplicationRequest: &simplex.ReplicationRequest{ + req := &common.Message{ + ReplicationRequest: &common.ReplicationRequest{ Seqs: seqs, LatestRound: 1, LatestFinalizedSeq: 0, @@ -126,8 +127,8 @@ func TestReplicationRequestNotarizations(t *testing.T) { } // now ask for the notarizations as rounds - req = &simplex.Message{ - ReplicationRequest: &simplex.ReplicationRequest{ + req = &common.Message{ + ReplicationRequest: &common.ReplicationRequest{ Rounds: seqs, }, } @@ -150,7 +151,7 @@ func TestReplicationRequestNotarizations(t *testing.T) { func TestReplicationRequestMixed(t *testing.T) { // generate 5 blocks & notarizations bb := testutil.NewTestBlockBuilder() - nodes := []simplex.NodeID{{1}, {2}, {3}, {4}} + nodes := []common.NodeID{{1}, {2}, {3}, {4}} comm := NewListenerComm(nodes) conf, wal, _ := testutil.DefaultTestNodeEpochConfig(t, nodes[0], comm, bb) conf.ReplicationEnabled = true @@ -161,7 +162,7 @@ func TestReplicationRequestMixed(t *testing.T) { require.NoError(t, e.Start()) numBlocks := uint64(8) - rounds := make(map[uint64]simplex.VerifiedQuorumRound) + rounds := make(map[uint64]common.VerifiedQuorumRound) numExpectedRounds := 0 // only produce a notarization for blocks we are the leader, otherwise produce an empty notarization @@ -171,18 +172,18 @@ func TestReplicationRequestMixed(t *testing.T) { emptyBlock := !leaderForRound if emptyBlock { emptyNotarization := testutil.NewEmptyNotarization(nodes, uint64(i)) - e.HandleMessage(&simplex.Message{ + e.HandleMessage(&common.Message{ EmptyNotarization: emptyNotarization, }, nodes[1]) wal.AssertNotarization(uint64(i)) - rounds[i] = simplex.VerifiedQuorumRound{ + rounds[i] = common.VerifiedQuorumRound{ EmptyNotarization: emptyNotarization, } continue } block, notarization := advanceRoundFromNotarization(t, e, bb) - rounds[i] = simplex.VerifiedQuorumRound{ + rounds[i] = common.VerifiedQuorumRound{ VerifiedBlock: block, Notarization: notarization, } @@ -195,8 +196,8 @@ func TestReplicationRequestMixed(t *testing.T) { roundsRequested = append(roundsRequested, k) } - req := &simplex.Message{ - ReplicationRequest: &simplex.ReplicationRequest{ + req := &common.Message{ + ReplicationRequest: &common.ReplicationRequest{ Rounds: roundsRequested, LatestRound: 1, }, @@ -221,7 +222,7 @@ func TestReplicationRequestMixed(t *testing.T) { func TestReplicationRequestTailingEmptyNotarizations(t *testing.T) { bb := testutil.NewTestBlockBuilder() - nodes := []simplex.NodeID{{1}, {2}, {3}, {4}} + nodes := []common.NodeID{{1}, {2}, {3}, {4}} comm := NewListenerComm(nodes) conf, wal, _ := testutil.DefaultTestNodeEpochConfig(t, nodes[0], comm, bb) conf.ReplicationEnabled = true @@ -232,15 +233,15 @@ func TestReplicationRequestTailingEmptyNotarizations(t *testing.T) { require.NoError(t, e.Start()) numBlocks := uint64(8) - rounds := make(map[uint64]simplex.VerifiedQuorumRound) + rounds := make(map[uint64]common.VerifiedQuorumRound) // only produce a notarization for blocks we are the leader, otherwise produce an empty notarization for i := range numBlocks { emptyNotarization := testutil.NewEmptyNotarization(nodes, uint64(i)) - e.HandleMessage(&simplex.Message{ + e.HandleMessage(&common.Message{ EmptyNotarization: emptyNotarization, }, nodes[1]) wal.AssertNotarization(uint64(i)) - rounds[i] = simplex.VerifiedQuorumRound{ + rounds[i] = common.VerifiedQuorumRound{ EmptyNotarization: emptyNotarization, } } @@ -251,8 +252,8 @@ func TestReplicationRequestTailingEmptyNotarizations(t *testing.T) { roundsRequested = append(roundsRequested, k) } - req := &simplex.Message{ - ReplicationRequest: &simplex.ReplicationRequest{ + req := &common.Message{ + ReplicationRequest: &common.ReplicationRequest{ Rounds: roundsRequested, LatestRound: 1, }, @@ -277,7 +278,7 @@ func TestReplicationRequestTailingEmptyNotarizations(t *testing.T) { func TestReplicationRequestUnknownSeqsAndRounds(t *testing.T) { bb := testutil.NewTestBlockBuilder() - nodes := []simplex.NodeID{{1}, {2}, {3}, {4}} + nodes := []common.NodeID{{1}, {2}, {3}, {4}} comm := NewListenerComm(nodes) conf, _, _ := testutil.DefaultTestNodeEpochConfig(t, nodes[0], comm, bb) conf.ReplicationEnabled = true @@ -287,8 +288,8 @@ func TestReplicationRequestUnknownSeqsAndRounds(t *testing.T) { t.Cleanup(e.Stop) require.NoError(t, e.Start()) - req := &simplex.Message{ - ReplicationRequest: &simplex.ReplicationRequest{ + req := &common.Message{ + ReplicationRequest: &common.ReplicationRequest{ Rounds: []uint64{100, 101, 102}, Seqs: []uint64{200, 201, 202}, LatestRound: 1, @@ -302,16 +303,16 @@ func TestReplicationRequestUnknownSeqsAndRounds(t *testing.T) { } func TestNilReplicationResponse(t *testing.T) { - nodes := []simplex.NodeID{{1}, {2}, {3}, {4}} + nodes := []common.NodeID{{1}, {2}, {3}, {4}} net := testutil.NewControlledNetwork(t, nodes) normalNode0 := testutil.NewControlledSimplexNode(t, nodes[0], net, nil) normalNode0.Start() defer net.StopInstances() - err := normalNode0.HandleMessage(&simplex.Message{ - ReplicationResponse: &simplex.ReplicationResponse{ - Data: []simplex.QuorumRound{{}}, + err := normalNode0.HandleMessage(&common.Message{ + ReplicationResponse: &common.ReplicationResponse{ + Data: []common.QuorumRound{{}}, }, }, nodes[1]) require.NoError(t, err) @@ -321,16 +322,16 @@ func TestNilReplicationResponse(t *testing.T) { // This replication response is malformed since it must also include a notarization or // finalization. func TestMalformedReplicationResponse(t *testing.T) { - nodes := []simplex.NodeID{{1}, {2}, {3}, {4}} + nodes := []common.NodeID{{1}, {2}, {3}, {4}} net := testutil.NewControlledNetwork(t, nodes) normalNode0 := testutil.NewControlledSimplexNode(t, nodes[0], net, nil) normalNode0.Start() defer net.StopInstances() - err := normalNode0.HandleMessage(&simplex.Message{ - ReplicationResponse: &simplex.ReplicationResponse{ - Data: []simplex.QuorumRound{{ + err := normalNode0.HandleMessage(&common.Message{ + ReplicationResponse: &common.ReplicationResponse{ + Data: []common.QuorumRound{{ Block: &testutil.TestBlock{}, }}, }, diff --git a/replication_state.go b/simplex/replication_state.go similarity index 88% rename from replication_state.go rename to simplex/replication_state.go index 7d77cc93..b74c30bf 100644 --- a/replication_state.go +++ b/simplex/replication_state.go @@ -8,15 +8,16 @@ import ( "sync" "time" + "github.com/ava-labs/simplex/common" "go.uber.org/zap" ) type seqAndDigest struct { - digest Digest + digest common.Digest seq uint64 } -func seqAndDigestFromBlock(block Block) seqAndDigest { +func seqAndDigestFromBlock(block common.Block) seqAndDigest { return seqAndDigest{ digest: block.BlockHeader().Digest, seq: block.BlockHeader().Seq, @@ -24,21 +25,21 @@ func seqAndDigestFromBlock(block Block) seqAndDigest { } type finalizedQuorumRound struct { - block Block - finalization *Finalization + block common.Block + finalization *common.Finalization } type ReplicationState struct { enabled bool - logger Logger - myNodeID NodeID + logger common.Logger + myNodeID common.NodeID rand *rand.Rand // Random number generator // seqs maps sequences to a block and its associated finalization seqs map[uint64]*finalizedQuorumRound // rounds maps round numbers to QuorumRounds - rounds map[uint64]*QuorumRound + rounds map[uint64]*common.QuorumRound // digestTimeouts handles timeouts for fetching missing block digests. // When a notarization depends on a block we haven't received yet, @@ -59,7 +60,7 @@ type ReplicationState struct { epochLock *sync.Mutex } -func NewReplicationState(logger Logger, comm Sender, myNodeID NodeID, maxRoundWindow uint64, enabled bool, start time.Time, lock *sync.Mutex, rng *rand.Rand) *ReplicationState { +func NewReplicationState(logger common.Logger, comm Sender, myNodeID common.NodeID, maxRoundWindow uint64, enabled bool, start time.Time, lock *sync.Mutex, rng *rand.Rand) *ReplicationState { if !enabled { return &ReplicationState{ enabled: enabled, @@ -79,7 +80,7 @@ func NewReplicationState(logger Logger, comm Sender, myNodeID NodeID, maxRoundWi finalizationRequestor: newRequestor(logger, start, lock, maxRoundWindow, comm, true), // round replication - rounds: make(map[uint64]*QuorumRound), + rounds: make(map[uint64]*common.QuorumRound), roundRequestor: newRequestor(logger, start, lock, maxRoundWindow, comm, false), sender: comm, @@ -119,7 +120,7 @@ func (r *ReplicationState) deleteOldRounds(finalizedRound uint64) { } // storeSequence stores a block and finalization into the replication state -func (r *ReplicationState) storeSequence(block Block, finalization *Finalization) bool { +func (r *ReplicationState) storeSequence(block common.Block, finalization *common.Finalization) bool { if _, exists := r.seqs[finalization.Finalization.Seq]; exists { return false } @@ -137,7 +138,7 @@ func (r *ReplicationState) storeSequence(block Block, finalization *Finalization // storeRound adds or updates a quorum round in the replication state. // If the round already exists, it merges any missing notarizations or empty notarizations // from the provided quorum round. Otherwise, it stores the new round as is. -func (r *ReplicationState) storeRound(qr *QuorumRound) { +func (r *ReplicationState) storeRound(qr *common.QuorumRound) { if qr.Block != nil { r.digestTimeouts.RemoveTask(seqAndDigestFromBlock(qr.Block)) } @@ -159,7 +160,7 @@ func (r *ReplicationState) storeRound(qr *QuorumRound) { } // StoreQuorumRound stores the quorum round into the replication state. -func (r *ReplicationState) StoreQuorumRound(round *QuorumRound) { +func (r *ReplicationState) StoreQuorumRound(round *common.QuorumRound) { if !r.enabled { return } @@ -191,7 +192,7 @@ func (r *ReplicationState) StoreQuorumRound(round *QuorumRound) { } // receivedFutureFinalization notifies the replication state a finalization was created in a future round. -func (r *ReplicationState) ReceivedFutureFinalization(finalization *Finalization, nextSeqToCommit uint64) { +func (r *ReplicationState) ReceivedFutureFinalization(finalization *common.Finalization, nextSeqToCommit uint64) { if !r.enabled { return } @@ -207,7 +208,7 @@ func (r *ReplicationState) ReceivedFutureFinalization(finalization *Finalization } // receivedFutureRound notifies the replication state of a future round. -func (r *ReplicationState) ReceivedFutureRound(round, seq, currentRound uint64, signers []NodeID) { +func (r *ReplicationState) ReceivedFutureRound(round, seq, currentRound uint64, signers []common.NodeID) { if !r.enabled { return } @@ -222,12 +223,12 @@ func (r *ReplicationState) ReceivedFutureRound(round, seq, currentRound uint64, } // ResendFinalizationRequest notifies the replication state that `seq` should be re-requested. -func (r *ReplicationState) ResendFinalizationRequest(seq uint64, signers []NodeID) { +func (r *ReplicationState) ResendFinalizationRequest(seq uint64, signers []common.NodeID) { if !r.enabled { return } - signers = NodeIDs(signers).Remove(r.myNodeID) + signers = common.NodeIDs(signers).Remove(r.myNodeID) numSigners := int64(len(signers)) index := r.rand.Int64N(numSigners) @@ -239,7 +240,7 @@ func (r *ReplicationState) ResendFinalizationRequest(seq uint64, signers []NodeI // CreateDependencyTasks creates tasks to refetch the given parent digest and empty rounds. If there are no // dependencies, no tasks are created. -func (r *ReplicationState) CreateDependencyTasks(parent *Digest, parentSeq uint64, emptyRounds []uint64) { +func (r *ReplicationState) CreateDependencyTasks(parent *common.Digest, parentSeq uint64, emptyRounds []uint64) { if parent != nil { r.digestTimeouts.AddTask(seqAndDigest{digest: *parent, seq: parentSeq}) } @@ -251,7 +252,7 @@ func (r *ReplicationState) CreateDependencyTasks(parent *Digest, parentSeq uint6 } } -func (r *ReplicationState) clearBlockDependencyTasks(digest Digest, seq uint64, finalizationPersisted bool) { +func (r *ReplicationState) clearBlockDependencyTasks(digest common.Digest, seq uint64, finalizationPersisted bool) { if !r.enabled { return } @@ -291,7 +292,7 @@ func (r *ReplicationState) MaybeAdvanceState(nextSequenceToCommit uint64, curren r.roundRequestor.updateState(currentRound) } -func (r *ReplicationState) GetFinalizedBlockForSequence(seq uint64) (Block, *Finalization, bool) { +func (r *ReplicationState) GetFinalizedBlockForSequence(seq uint64) (common.Block, *common.Finalization, bool) { blockWithFinalization, exists := r.seqs[seq] if !exists { return nil, nil, false @@ -300,8 +301,8 @@ func (r *ReplicationState) GetFinalizedBlockForSequence(seq uint64) (Block, *Fin return blockWithFinalization.block, blockWithFinalization.finalization, true } -func (r *ReplicationState) GetLowestRound() *QuorumRound { - var lowestRound *QuorumRound +func (r *ReplicationState) GetLowestRound() *common.QuorumRound { + var lowestRound *common.QuorumRound for round, qr := range r.rounds { if lowestRound == nil { @@ -336,7 +337,7 @@ func (r *ReplicationState) GetHighestRound() uint64 { return highestRound } -func (r *ReplicationState) GetBlockWithSeq(seq uint64) Block { +func (r *ReplicationState) GetBlockWithSeq(seq uint64) common.Block { block, _, _ := r.GetFinalizedBlockForSequence(seq) if block != nil { return block @@ -381,11 +382,11 @@ func (r *ReplicationState) requestDigests(missingBlocks []seqAndDigest) { node := signedQuorum.signers[index] r.logger.Debug("Replication State requesting missing block digest", zap.Uint64("seq", mb.seq), zap.Stringer("digest", &mb.digest)) - blockRequest := &BlockDigestRequest{ + blockRequest := &common.BlockDigestRequest{ Seq: mb.seq, Digest: mb.digest, } - r.sender.Send(&Message{ + r.sender.Send(&common.Message{ BlockDigestRequest: blockRequest, }, node) } diff --git a/replication_test.go b/simplex/replication_test.go similarity index 89% rename from replication_test.go rename to simplex/replication_test.go index 501c6ceb..e4e810dd 100644 --- a/replication_test.go +++ b/simplex/replication_test.go @@ -12,7 +12,8 @@ import ( "testing" "time" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" + "github.com/ava-labs/simplex/simplex" "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" @@ -24,7 +25,7 @@ import ( // TestReplication tests the replication process of a node that // is behind the rest of the network by less than maxRoundWindow. func TestBasicReplication(t *testing.T) { - nodes := []simplex.NodeID{{1}, {2}, {3}, []byte("lagging")} + nodes := []common.NodeID{{1}, {2}, {3}, []byte("lagging")} for i := range 3 * simplex.DefaultMaxRoundWindow { testName := fmt.Sprintf("Basic replication_of_%d_blocks", i) @@ -42,7 +43,7 @@ func TestBasicReplication(t *testing.T) { } } -func testReplication(t *testing.T, startSeq uint64, nodes []simplex.NodeID) { +func testReplication(t *testing.T, startSeq uint64, nodes []common.NodeID) { net := NewControlledNetwork(t, nodes) // initiate a network with 4 nodes. one node is behind by startSeq blocks @@ -79,7 +80,7 @@ func testReplication(t *testing.T, startSeq uint64, nodes []simplex.NodeID) { // has been sent a different block by one node, however the rest of the network // notarizes a different block for the same round func TestReplicationAdversarialNode(t *testing.T) { - nodes := []simplex.NodeID{{1}, {2}, {3}, []byte("lagging")} + nodes := []common.NodeID{{1}, {2}, {3}, []byte("lagging")} quorum := simplex.Quorum(len(nodes)) net := NewControlledNetwork(t, nodes) @@ -105,8 +106,8 @@ func TestReplicationAdversarialNode(t *testing.T) { doubleBlock := NewTestBlock(doubleBlockProposalNode.E.Metadata(), emptyBlacklist) doubleBlockVote, err := NewTestVote(doubleBlock, doubleBlockProposalNode.E.ID) require.NoError(t, err) - msg := &simplex.Message{ - BlockMessage: &simplex.BlockMessage{ + msg := &common.Message{ + BlockMessage: &common.BlockMessage{ Block: doubleBlock, Vote: *doubleBlockVote, }, @@ -115,7 +116,7 @@ func TestReplicationAdversarialNode(t *testing.T) { laggingNode.E.HandleMessage(msg, doubleBlockProposalNode.E.ID) net.Disconnect(laggingNode.E.ID) - blocks := []simplex.VerifiedBlock{} + blocks := []common.VerifiedBlock{} for i := uint64(0); i < 2; i++ { net.TriggerLeaderBlockBuilder(i) @@ -134,7 +135,7 @@ func TestReplicationAdversarialNode(t *testing.T) { sigAggr := laggingNode.E.SignatureAggregatorCreator(laggingNode.E.Comm.Nodes()) finalization, _ := NewFinalizationRecord(t, sigAggr, blocks[1], nodes[:quorum]) - finalizationMsg := &simplex.Message{ + finalizationMsg := &common.Message{ Finalization: &finalization, } laggingNode.E.HandleMessage(finalizationMsg, doubleBlockProposalNode.E.ID) @@ -149,10 +150,10 @@ func TestReplicationAdversarialNode(t *testing.T) { // a lagging node and the rest of the network correctly propagate missing // finalizations and index all blocks. func TestRebroadcastingWithReplication(t *testing.T) { - nodes := []simplex.NodeID{{1}, {2}, {3}, {4}} + nodes := []common.NodeID{{1}, {2}, {3}, {4}} net := NewControlledNetwork(t, nodes) - newNodeConfig := func(from simplex.NodeID) *TestNodeConfig { + newNodeConfig := func(from common.NodeID) *TestNodeConfig { comm := NewTestComm(from, net.BasicInMemoryNetwork, AllowAllMessages) return &TestNodeConfig{ Comm: comm, @@ -257,7 +258,7 @@ func TestRebroadcastingWithReplication(t *testing.T) { // many empty notarizations in a row. // This test sometimes takes > 30 sec func TestReplicationEmptyNotarizations(t *testing.T) { - nodes := []simplex.NodeID{{1}, {2}, {3}, {4}, {5}, {6}} + nodes := []common.NodeID{{1}, {2}, {3}, {4}, {5}, {6}} for endRound := uint64(2); endRound <= 2*simplex.DefaultMaxRoundWindow; endRound++ { isLaggingNodeLeader := bytes.Equal(simplex.LeaderForRound(nodes, endRound), nodes[5]) @@ -273,9 +274,9 @@ func TestReplicationEmptyNotarizations(t *testing.T) { } } -func testReplicationEmptyNotarizations(t *testing.T, nodes []simplex.NodeID, endRound uint64) { +func testReplicationEmptyNotarizations(t *testing.T, nodes []common.NodeID, endRound uint64) { net := NewControlledNetwork(t, nodes) - newNodeConfig := func(from simplex.NodeID) *TestNodeConfig { + newNodeConfig := func(from common.NodeID) *TestNodeConfig { comm := NewTestComm(from, net.BasicInMemoryNetwork, AllowAllMessages) return &TestNodeConfig{ Comm: comm, @@ -354,7 +355,7 @@ func testReplicationEmptyNotarizations(t *testing.T, nodes []simplex.NodeID, end // TestReplicationStartsBeforeCurrentRound tests the replication process of a node that // starts replicating in the middle of the current round. func TestReplicationStartsBeforeCurrentRound(t *testing.T) { - nodes := []simplex.NodeID{{1}, {2}, {3}, []byte("lagging")} + nodes := []common.NodeID{{1}, {2}, {3}, []byte("lagging")} quorum := simplex.Quorum(len(nodes)) net := NewControlledNetwork(t, nodes) startSeq := uint64(simplex.DefaultMaxRoundWindow + 3) @@ -373,7 +374,7 @@ func TestReplicationStartsBeforeCurrentRound(t *testing.T) { firstBlock := storageData[0].VerifiedBlock fBytes, err := firstBlock.Bytes() require.NoError(t, err) - record := simplex.BlockRecord(firstBlock.BlockHeader(), fBytes) + record := common.BlockRecord(firstBlock.BlockHeader(), fBytes) laggingNode.WAL.Append(record) sigAggr := laggingNode.E.SignatureAggregatorCreator(laggingNode.E.Comm.Nodes()) @@ -384,7 +385,7 @@ func TestReplicationStartsBeforeCurrentRound(t *testing.T) { secondBlock := storageData[1].VerifiedBlock sBytes, err := secondBlock.Bytes() require.NoError(t, err) - record = simplex.BlockRecord(secondBlock.BlockHeader(), sBytes) + record = common.BlockRecord(secondBlock.BlockHeader(), sBytes) laggingNode.WAL.Append(record) secondNotarizationRecord, err := NewNotarizationRecord(laggingNode.E.Logger, sigAggr, secondBlock, nodes[0:quorum]) @@ -413,7 +414,7 @@ func TestReplicationStartsBeforeCurrentRound(t *testing.T) { func TestReplicationFutureFinalization(t *testing.T) { // send a block, then simultaneously send a finalization for the block bb := testutil.NewTestBlockBuilder() - nodes := []simplex.NodeID{{1}, {2}, {3}, {4}} + nodes := []common.NodeID{{1}, {2}, {3}, {4}} quorum := simplex.Quorum(len(nodes)) conf, _, storage := DefaultTestNodeEpochConfig(t, nodes[1], NewNoopComm(nodes), bb) @@ -435,8 +436,8 @@ func TestReplicationFutureFinalization(t *testing.T) { vote, err := NewTestVote(block, nodes[0]) require.NoError(t, err) - err = e.HandleMessage(&simplex.Message{ - BlockMessage: &simplex.BlockMessage{ + err = e.HandleMessage(&common.Message{ + BlockMessage: &common.BlockMessage{ Vote: *vote, Block: block, }, @@ -446,7 +447,7 @@ func TestReplicationFutureFinalization(t *testing.T) { sigAggr := e.SignatureAggregatorCreator(conf.Comm.Nodes()) finalization, _ := NewFinalizationRecord(t, sigAggr, block, nodes[0:quorum]) // send finalization - err = e.HandleMessage(&simplex.Message{ + err = e.HandleMessage(&common.Message{ Finalization: &finalization, }, nodes[0]) require.NoError(t, err) @@ -465,7 +466,7 @@ func TestReplicationFutureFinalization(t *testing.T) { // and the rest of the nodes continue to make progress for another `endDisconnect - startDisconnect` blocks. // The lagging node reconnects and the after the next `finalization` is sent, the lagging node catches up to the latest height. func TestReplicationAfterNodeDisconnects(t *testing.T) { - nodes := []simplex.NodeID{{1}, {2}, {3}, []byte("lagging")} + nodes := []common.NodeID{{1}, {2}, {3}, []byte("lagging")} for startDisconnect := uint64(0); startDisconnect <= 5; startDisconnect++ { for endDisconnect := uint64(10); endDisconnect <= 20; endDisconnect++ { @@ -485,7 +486,7 @@ func TestReplicationAfterNodeDisconnects(t *testing.T) { } } -func testReplicationAfterNodeDisconnects(t *testing.T, nodes []simplex.NodeID, startDisconnect, endDisconnect uint64) { +func testReplicationAfterNodeDisconnects(t *testing.T, nodes []common.NodeID, startDisconnect, endDisconnect uint64) { net := NewControlledNetwork(t, nodes) testConfig := &TestNodeConfig{ ReplicationEnabled: true, @@ -547,7 +548,7 @@ func testReplicationAfterNodeDisconnects(t *testing.T, nodes []simplex.NodeID, s net.Connect(laggingNode.E.ID) net.TriggerLeaderBlockBuilder(endDisconnect) - var blacklist simplex.Blacklist + var blacklist common.Blacklist for _, n := range net.Instances { block := n.Storage.WaitForBlockCommit(endDisconnect - missedSeqs) blacklist = block.Blacklist() @@ -572,8 +573,8 @@ func testReplicationAfterNodeDisconnects(t *testing.T, nodes []simplex.NodeID, s // sendVotesToOneNode allows block messages to be sent to all nodes, and only // passes vote messages to one node. This will allows that node to notarize the block, // while the other blocks will timeout -func sendVotesToOneNode(filteredInNode simplex.NodeID) MessageFilter { - return func(msg *simplex.Message, _, to simplex.NodeID) bool { +func sendVotesToOneNode(filteredInNode common.NodeID) MessageFilter { + return func(msg *common.Message, _, to common.NodeID) bool { if msg.VerifiedBlockMessage != nil || msg.BlockMessage != nil { return true } @@ -596,11 +597,11 @@ func TestReplicationStuckInProposingBlock(t *testing.T) { tbb := testutil.NewTestBlockBuilder() bb := NewTestControlledBlockBuilder(t) bb.TestBlockBuilder = *tbb - nodes := []simplex.NodeID{{1}, {2}, {3}, {4}} + nodes := []common.NodeID{{1}, {2}, {3}, {4}} blocks := createBlocks(t, nodes, 5) quorum := simplex.Quorum(len(nodes)) - sentMessages := make(chan *simplex.Message, 100) + sentMessages := make(chan *common.Message, 100) conf, _, storage := DefaultTestNodeEpochConfig(t, nodes[0], &recordingComm{ Communication: NewNoopComm(nodes), @@ -634,7 +635,7 @@ func TestReplicationStuckInProposingBlock(t *testing.T) { highFinalization, _ := NewFinalizationRecord(t, sigAggr, highBlock, nodes[0:quorum]) // Trigger the replication process to start by sending a finalization for a block we do not have - e.HandleMessage(&simplex.Message{ + e.HandleMessage(&common.Message{ Finalization: &highFinalization, }, nodes[1]) @@ -655,23 +656,23 @@ func TestReplicationStuckInProposingBlock(t *testing.T) { } // Prepare the quorum round answer to be sent as a response to the replication request - quorumRounds := make([]simplex.QuorumRound, 0, 4) + quorumRounds := make([]common.QuorumRound, 0, 4) for i := uint64(1); i <= 4; i++ { tb := blocks[i].VerifiedBlock.(*TestBlock) finalization := blocks[i].Finalization - quorumRounds = append(quorumRounds, simplex.QuorumRound{ + quorumRounds = append(quorumRounds, common.QuorumRound{ Block: tb, Finalization: &finalization, }) } // Respond to the replication request with a block that has a notarization - replicationResponse := &simplex.ReplicationResponse{ + replicationResponse := &common.ReplicationResponse{ LatestRound: &quorumRounds[2], Data: quorumRounds[:3], } - e.HandleMessage(&simplex.Message{ + e.HandleMessage(&common.Message{ ReplicationResponse: replicationResponse, }, nodes[1]) @@ -679,7 +680,7 @@ func TestReplicationStuckInProposingBlock(t *testing.T) { aboutToBuildBlock.Wait() // Trigger the replication process to start by sending a finalization for a block we do not have - e.HandleMessage(&simplex.Message{ + e.HandleMessage(&common.Message{ Finalization: &blocks[4].Finalization, }, nodes[1]) @@ -691,12 +692,12 @@ func TestReplicationStuckInProposingBlock(t *testing.T) { } } - replicationResponse = &simplex.ReplicationResponse{ + replicationResponse = &common.ReplicationResponse{ LatestRound: &quorumRounds[3], Data: quorumRounds[3:], } - e.HandleMessage(&simplex.Message{ + e.HandleMessage(&common.Message{ ReplicationResponse: replicationResponse, }, nodes[1]) @@ -709,12 +710,12 @@ func TestReplicationStuckInProposingBlock(t *testing.T) { func TestReplicationNodeDiverges(t *testing.T) { t.Setenv("LOG_LEVEL", "debug") - nodes := []simplex.NodeID{{1}, {2}, {3}, {4}, {5}, {6}} + nodes := []common.NodeID{{1}, {2}, {3}, {4}, {5}, {6}} numBlocks := uint64(5) net := NewControlledNetwork(t, nodes) - nodeConfig := func(from simplex.NodeID) *TestNodeConfig { + nodeConfig := func(from common.NodeID) *TestNodeConfig { comm := NewTestComm(from, net.BasicInMemoryNetwork, sendVotesToOneNode(nodes[3])) return &TestNodeConfig{ Comm: comm, @@ -748,7 +749,7 @@ func TestReplicationNodeDiverges(t *testing.T) { net.Disconnect(laggingNode.E.ID) net.SetAllNodesMessageFilter( // block sending votes from round 0 to ensure all nodes will timeout - func(msg *simplex.Message, _, to simplex.NodeID) bool { + func(msg *common.Message, _, to common.NodeID) bool { return !(msg.VoteMessage != nil && msg.VoteMessage.Vote.Round == 0) }, ) @@ -833,7 +834,7 @@ func assertEqualLedgers(t *testing.T, net *ControlledInMemoryNetwork) { } func TestReplicationNotarizationWithoutFinalizations(t *testing.T) { - nodes := []simplex.NodeID{{1}, {2}, {3}, {4}} + nodes := []common.NodeID{{1}, {2}, {3}, {4}} for numBlocks := uint64(1); numBlocks <= 3*simplex.DefaultMaxRoundWindow; numBlocks++ { // lagging node cannot be the leader after node disconnects @@ -853,10 +854,10 @@ func TestReplicationNotarizationWithoutFinalizations(t *testing.T) { // TestReplicationNotarizationWithoutFinalizations tests that a lagging node will replicate // blocks that have notarizations but no finalizations. -func testReplicationNotarizationWithoutFinalizations(t *testing.T, numBlocks uint64, nodes []simplex.NodeID) { +func testReplicationNotarizationWithoutFinalizations(t *testing.T, numBlocks uint64, nodes []common.NodeID) { net := NewControlledNetwork(t, nodes) - onlyAllowBlockProposalsAndNotarizations := func(msg *simplex.Message, _, to simplex.NodeID) bool { + onlyAllowBlockProposalsAndNotarizations := func(msg *common.Message, _, to common.NodeID) bool { if to.Equals(nodes[3]) { return (msg.BlockMessage != nil || msg.VerifiedBlockMessage != nil || msg.Notarization != nil) } @@ -864,7 +865,7 @@ func testReplicationNotarizationWithoutFinalizations(t *testing.T, numBlocks uin return true } - nodeConfig := func(from simplex.NodeID) *TestNodeConfig { + nodeConfig := func(from common.NodeID) *TestNodeConfig { comm := NewTestComm(from, net.BasicInMemoryNetwork, onlyAllowBlockProposalsAndNotarizations) return &TestNodeConfig{ Comm: comm, @@ -904,13 +905,13 @@ func testReplicationNotarizationWithoutFinalizations(t *testing.T, numBlocks uin } } -func createBlocks(t *testing.T, nodes []simplex.NodeID, seqCount uint64) []simplex.VerifiedFinalizedBlock { +func createBlocks(t *testing.T, nodes []common.NodeID, seqCount uint64) []common.VerifiedFinalizedBlock { bb := NewTestBlockBuilder() ctx := context.Background() - data := make([]simplex.VerifiedFinalizedBlock, 0, seqCount) - var prev simplex.Digest + data := make([]common.VerifiedFinalizedBlock, 0, seqCount) + var prev common.Digest for i := uint64(0); i < seqCount; i++ { - protocolMetadata := simplex.ProtocolMetadata{ + protocolMetadata := common.ProtocolMetadata{ Seq: i, Round: i, Prev: prev, @@ -920,7 +921,7 @@ func createBlocks(t *testing.T, nodes []simplex.NodeID, seqCount uint64) []simpl require.True(t, ok) prev = block.BlockHeader().Digest finalization, _ := NewFinalizationRecord(t, &TestSignatureAggregator{N: len(nodes)}, block, nodes) - data = append(data, simplex.VerifiedFinalizedBlock{ + data = append(data, common.VerifiedFinalizedBlock{ VerifiedBlock: block, Finalization: finalization, }) @@ -930,11 +931,11 @@ func createBlocks(t *testing.T, nodes []simplex.NodeID, seqCount uint64) []simpl func TestReplicationVerifyNotarization(t *testing.T) { bb := testutil.NewTestBlockBuilder() - nodes := []simplex.NodeID{{1}, {2}, {3}, {4}} + nodes := []common.NodeID{{1}, {2}, {3}, {4}} // This function takes a QC and makes it that it is signed by only 2 out of 4 nodes, // while still having a quorum of signatures. - corruptQC := func(qc simplex.QuorumCertificate) simplex.QuorumCertificate { + corruptQC := func(qc common.QuorumCertificate) common.QuorumCertificate { badQC := qc.(TestQC) // Duplicate the last signature badQC = append(badQC, badQC[len(badQC)-1]) @@ -956,7 +957,7 @@ func TestReplicationVerifyNotarization(t *testing.T) { } quorum := simplex.Quorum(len(nodes)) - sentMessages := make(chan *simplex.Message, 100) + sentMessages := make(chan *common.Message, 100) conf, wal, _ := DefaultTestNodeEpochConfig(t, nodes[1], &recordingComm{ Communication: NewNoopComm(nodes), @@ -980,7 +981,7 @@ func TestReplicationVerifyNotarization(t *testing.T) { finalization, _ := NewFinalizationRecord(t, sigAggr, block, nodes[0:quorum]) // Trigger the replication process to start by sending a finalization for a block we do not have - e.HandleMessage(&simplex.Message{ + e.HandleMessage(&common.Message{ Finalization: &finalization, }, nodes[0]) @@ -999,15 +1000,15 @@ func TestReplicationVerifyNotarization(t *testing.T) { notarization.QC = corruptQC(notarization.QC) // Respond to the replication request with a block that has a notarization - replicationResponse := &simplex.ReplicationResponse{ - Data: []simplex.QuorumRound{ + replicationResponse := &common.ReplicationResponse{ + Data: []common.QuorumRound{ { Block: block, Notarization: ¬arization, }, }, } - e.HandleMessage(&simplex.Message{ + e.HandleMessage(&common.Message{ ReplicationResponse: replicationResponse, }, nodes[0]) @@ -1019,11 +1020,11 @@ func TestReplicationVerifyNotarization(t *testing.T) { func TestReplicationVerifyEmptyNotarization(t *testing.T) { bb := testutil.NewTestBlockBuilder() - nodes := []simplex.NodeID{{1}, {2}, {3}, {4}} + nodes := []common.NodeID{{1}, {2}, {3}, {4}} // This function takes a QC and makes it that it is signed by only 2 out of 4 nodes, // while still having a quorum of signatures. - corruptQC := func(qc simplex.QuorumCertificate) simplex.QuorumCertificate { + corruptQC := func(qc common.QuorumCertificate) common.QuorumCertificate { badQC := qc.(TestQC) // Duplicate the last signature badQC = append(badQC, badQC[len(badQC)-1]) @@ -1045,7 +1046,7 @@ func TestReplicationVerifyEmptyNotarization(t *testing.T) { } quorum := simplex.Quorum(len(nodes)) - sentMessages := make(chan *simplex.Message, 100) + sentMessages := make(chan *common.Message, 100) conf, wal, _ := DefaultTestNodeEpochConfig(t, nodes[1], &recordingComm{ Communication: NewNoopComm(nodes), SentMessages: sentMessages, @@ -1068,7 +1069,7 @@ func TestReplicationVerifyEmptyNotarization(t *testing.T) { finalization, _ := NewFinalizationRecord(t, sigAggr, block, nodes[0:quorum]) // Trigger the replication process to start by sending a finalization for a block we do not have - e.HandleMessage(&simplex.Message{ + e.HandleMessage(&common.Message{ Finalization: &finalization, }, nodes[0]) @@ -1086,14 +1087,14 @@ func TestReplicationVerifyEmptyNotarization(t *testing.T) { emptyNotarization.QC = corruptQC(emptyNotarization.QC) // Respond to the replication request with a block that has a notarization - replicationResponse := &simplex.ReplicationResponse{ - Data: []simplex.QuorumRound{ + replicationResponse := &common.ReplicationResponse{ + Data: []common.QuorumRound{ { EmptyNotarization: emptyNotarization, }, }, } - e.HandleMessage(&simplex.Message{ + e.HandleMessage(&common.Message{ ReplicationResponse: replicationResponse, }, nodes[0]) @@ -1106,7 +1107,7 @@ func TestReplicationVerifyEmptyNotarization(t *testing.T) { // finalizations and notarizations. It ensures the node sends finalized votes for rounds // without finalizations. func TestReplicationVotesForNotarizations(t *testing.T) { - nodes := []simplex.NodeID{{1}, {2}, {3}, {4}} + nodes := []common.NodeID{{1}, {2}, {3}, {4}} numFinalizedBlocks := uint64(5) // number of notarized blocks after the finalized blocks @@ -1118,15 +1119,15 @@ func TestReplicationVotesForNotarizations(t *testing.T) { // almostFinalizeBlocks is a message filter that allows all messages except for finalized votes // and finalizations, unless the message is from node 1. This way each node will have 2 finalized votes, // which is one short from quorum. - almostFinalizeBlocks := func(msg *simplex.Message, from, _ simplex.NodeID) bool { + almostFinalizeBlocks := func(msg *common.Message, from, _ common.NodeID) bool { // block finalized votes and finalizations if msg.Finalization != nil || msg.FinalizeVote != nil { - return from.Equals(simplex.NodeID{1}) + return from.Equals(common.NodeID{1}) } return true } - nodeConfig := func(from simplex.NodeID) *TestNodeConfig { + nodeConfig := func(from common.NodeID) *TestNodeConfig { comm := NewTestComm(from, net.BasicInMemoryNetwork, almostFinalizeBlocks) return &TestNodeConfig{ InitialStorage: storageData, @@ -1242,7 +1243,7 @@ func TestReplicationVotesForNotarizations(t *testing.T) { // TestReplicationEmptyNotarizations ensures a lagging node will properly replicate // a tail of empty notarizations. func TestReplicationEmptyNotarizationsTail(t *testing.T) { - nodes := []simplex.NodeID{{1}, {2}, {3}, {4}, {5}, {6}} + nodes := []common.NodeID{{1}, {2}, {3}, {4}, {5}, {6}} for endRound := uint64(2); endRound <= 2*simplex.DefaultMaxRoundWindow; endRound++ { isLaggingNodeLeader := bytes.Equal(simplex.LeaderForRound(nodes, endRound), nodes[5]) @@ -1258,9 +1259,9 @@ func TestReplicationEmptyNotarizationsTail(t *testing.T) { } } -func testReplicationEmptyNotarizationsTail(t *testing.T, nodes []simplex.NodeID, endRound uint64) { +func testReplicationEmptyNotarizationsTail(t *testing.T, nodes []common.NodeID, endRound uint64) { net := NewControlledNetwork(t, nodes) - newNodeConfig := func(from simplex.NodeID) *TestNodeConfig { + newNodeConfig := func(from common.NodeID) *TestNodeConfig { comm := NewTestComm(from, net.BasicInMemoryNetwork, AllowAllMessages) return &TestNodeConfig{ Comm: comm, @@ -1316,12 +1317,12 @@ func testReplicationEmptyNotarizationsTail(t *testing.T, nodes []simplex.NodeID, } } -func sendEmptyNotarizationQuorumRounds(emptyNotarizations map[uint64]*simplex.EmptyNotarization) MessageFilter { - return func(msg *simplex.Message, from, to simplex.NodeID) bool { +func sendEmptyNotarizationQuorumRounds(emptyNotarizations map[uint64]*common.EmptyNotarization) MessageFilter { + return func(msg *common.Message, from, to common.NodeID) bool { if msg.VerifiedReplicationResponse != nil { - newData := make([]simplex.VerifiedQuorumRound, 0, len(msg.VerifiedReplicationResponse.Data)) + newData := make([]common.VerifiedQuorumRound, 0, len(msg.VerifiedReplicationResponse.Data)) for _, qr := range msg.VerifiedReplicationResponse.Data { - newQR := simplex.VerifiedQuorumRound{ + newQR := common.VerifiedQuorumRound{ EmptyNotarization: qr.EmptyNotarization, } if qr.EmptyNotarization == nil { @@ -1336,9 +1337,9 @@ func sendEmptyNotarizationQuorumRounds(emptyNotarizations map[uint64]*simplex.Em } } -func allowFinalizeVotes(msg *simplex.Message, from, to simplex.NodeID) bool { +func allowFinalizeVotes(msg *common.Message, from, to common.NodeID) bool { if msg.Finalization != nil || msg.FinalizeVote != nil { - if to.Equals(simplex.NodeID{3}) || from.Equals(simplex.NodeID{3}) { + if to.Equals(common.NodeID{3}) || from.Equals(common.NodeID{3}) { return false } } @@ -1349,8 +1350,8 @@ func allowFinalizeVotes(msg *simplex.Message, from, to simplex.NodeID) bool { // map when processing. func TestReplicationStoresFinalization(t *testing.T) { bb := testutil.NewTestBlockBuilder() - nodes := []simplex.NodeID{{1}, {2}, {3}, {4}} - sentMessages := make(chan *simplex.Message, 100) + nodes := []common.NodeID{{1}, {2}, {3}, {4}} + sentMessages := make(chan *common.Message, 100) conf, _, storage := DefaultTestNodeEpochConfig(t, nodes[3], &recordingComm{ Communication: NewNoopComm(nodes), @@ -1365,19 +1366,19 @@ func TestReplicationStoresFinalization(t *testing.T) { // createBlocks 2 blocks with finalizations blocks := createBlocks(t, nodes, 2) - vote, err := NewTestVote(blocks[0].VerifiedBlock.(simplex.Block), nodes[0]) + vote, err := NewTestVote(blocks[0].VerifiedBlock.(common.Block), nodes[0]) require.NoError(t, err) // send block 1 - e.HandleMessage(&simplex.Message{ - BlockMessage: &simplex.BlockMessage{ - Block: blocks[0].VerifiedBlock.(simplex.Block), + e.HandleMessage(&common.Message{ + BlockMessage: &common.BlockMessage{ + Block: blocks[0].VerifiedBlock.(common.Block), Vote: *vote, }, }, nodes[0]) // Send a finalization for block 2 to trigger replication finalization := blocks[1].Finalization - e.HandleMessage(&simplex.Message{ + e.HandleMessage(&common.Message{ Finalization: &finalization, }, nodes[1]) @@ -1390,22 +1391,22 @@ func TestReplicationStoresFinalization(t *testing.T) { } // pass in replication response to epoch with both blocks and their finalizations - quorumRounds := []simplex.QuorumRound{ + quorumRounds := []common.QuorumRound{ { - Block: blocks[0].VerifiedBlock.(simplex.Block), + Block: blocks[0].VerifiedBlock.(common.Block), Finalization: &blocks[0].Finalization, }, { - Block: blocks[1].VerifiedBlock.(simplex.Block), + Block: blocks[1].VerifiedBlock.(common.Block), Finalization: &blocks[1].Finalization, }, } - replicationResponse := &simplex.ReplicationResponse{ + replicationResponse := &common.ReplicationResponse{ Data: quorumRounds, } - e.HandleMessage(&simplex.Message{ + e.HandleMessage(&common.Message{ ReplicationResponse: replicationResponse, }, nodes[1]) @@ -1421,10 +1422,10 @@ func TestReplicationStoresFinalization(t *testing.T) { // TestReplicationChain tests that a node can both empty notarizations and notarizations for the same round. func TestReplicationChain(t *testing.T) { // Digest message requests are needed for this test - nodes := []simplex.NodeID{{1}, {2}, {3}, {4}} + nodes := []common.NodeID{{1}, {2}, {3}, {4}} net := NewControlledNetwork(t, nodes) - newNodeConfig := func(from simplex.NodeID) *TestNodeConfig { + newNodeConfig := func(from common.NodeID) *TestNodeConfig { comm := NewTestComm(from, net.BasicInMemoryNetwork, allowFinalizeVotes) return &TestNodeConfig{ Comm: comm, @@ -1447,7 +1448,7 @@ func TestReplicationChain(t *testing.T) { defer net.StopInstances() net.Disconnect(laggingNode.E.ID) - emptyNotarizations := make(map[uint64]*simplex.EmptyNotarization) + emptyNotarizations := make(map[uint64]*common.EmptyNotarization) numNotarizations := uint64(8) missedNotarizations := uint64(0) for i := range numNotarizations { @@ -1533,10 +1534,10 @@ func TestReplicationChain(t *testing.T) { // empty notarization after replicating. func TestReplicationStartsRoundFromFinalization(t *testing.T) { bb := testutil.NewTestBlockBuilder() - nodes := []simplex.NodeID{{1}, {2}, {3}, {4}} + nodes := []common.NodeID{{1}, {2}, {3}, {4}} - sentMessages := make(chan *simplex.Message, 100) - broadcastMessages := make(chan *simplex.Message, 100) + sentMessages := make(chan *common.Message, 100) + broadcastMessages := make(chan *common.Message, 100) conf, wal, storage := DefaultTestNodeEpochConfig(t, nodes[0], &recordingComm{ Communication: NewNoopComm(nodes), SentMessages: sentMessages, @@ -1554,7 +1555,7 @@ func TestReplicationStartsRoundFromFinalization(t *testing.T) { // Send a finalization for a block we don't have to trigger replication lastFinalization := blocks[len(blocks)-1].Finalization - e.HandleMessage(&simplex.Message{ + e.HandleMessage(&common.Message{ Finalization: &lastFinalization, }, nodes[1]) @@ -1567,22 +1568,22 @@ func TestReplicationStartsRoundFromFinalization(t *testing.T) { } // Prepare replication response with all the blocks - quorumRounds := make([]simplex.QuorumRound, 0, len(blocks)) + quorumRounds := make([]common.QuorumRound, 0, len(blocks)) for _, vfb := range blocks { tb := vfb.VerifiedBlock.(*TestBlock) - quorumRounds = append(quorumRounds, simplex.QuorumRound{ + quorumRounds = append(quorumRounds, common.QuorumRound{ Block: tb, Finalization: &vfb.Finalization, }) } // Send replication response - replicationResponse := &simplex.ReplicationResponse{ + replicationResponse := &common.ReplicationResponse{ LatestRound: &quorumRounds[len(quorumRounds)-1], Data: quorumRounds, } - e.HandleMessage(&simplex.Message{ + e.HandleMessage(&common.Message{ ReplicationResponse: replicationResponse, }, nodes[1]) @@ -1595,16 +1596,16 @@ func TestReplicationStartsRoundFromFinalization(t *testing.T) { require.Equal(t, uint64(len(blocks)), storage.NumBlocks()) require.Equal(t, uint64(len(blocks)), e.Metadata().Round) - emptyBlockMd := simplex.EmptyVoteMetadata{ + emptyBlockMd := common.EmptyVoteMetadata{ Round: uint64(len(blocks)), } // the other two nodes send empty votes - e.HandleMessage(&simplex.Message{ + e.HandleMessage(&common.Message{ EmptyVoteMessage: createEmptyVote(emptyBlockMd, nodes[1]), }, nodes[1]) - e.HandleMessage(&simplex.Message{ + e.HandleMessage(&common.Message{ EmptyVoteMessage: createEmptyVote(emptyBlockMd, nodes[2]), }, nodes[2]) @@ -1643,10 +1644,10 @@ messages: // except it checks the replication path when a block already exists in our rounds map for the finalized block. func TestReplicationStartsRoundFromFinalizationWithBlock(t *testing.T) { bb := testutil.NewTestBlockBuilder() - nodes := []simplex.NodeID{{1}, {2}, {3}, {4}} + nodes := []common.NodeID{{1}, {2}, {3}, {4}} - sentMessages := make(chan *simplex.Message, 100) - broadcastMessages := make(chan *simplex.Message, 100) + sentMessages := make(chan *common.Message, 100) + broadcastMessages := make(chan *common.Message, 100) conf, wal, storage := DefaultTestNodeEpochConfig(t, nodes[0], &recordingComm{ Communication: NewNoopComm(nodes), SentMessages: sentMessages, @@ -1667,30 +1668,30 @@ func TestReplicationStartsRoundFromFinalizationWithBlock(t *testing.T) { // send the block for the round before vote, err := NewTestVote(lastBlock, simplex.LeaderForRound(nodes, lastBlock.BlockHeader().Round)) require.NoError(t, err) - err = e.HandleMessage(&simplex.Message{ - BlockMessage: &simplex.BlockMessage{ + err = e.HandleMessage(&common.Message{ + BlockMessage: &common.BlockMessage{ Vote: *vote, - Block: lastBlock.(simplex.Block), + Block: lastBlock.(common.Block), }, }, simplex.LeaderForRound(nodes, lastBlock.BlockHeader().Round)) require.NoError(t, err) // Prepare replication response with all the blocks - quorumRounds := make([]simplex.QuorumRound, 0, len(blocks)) + quorumRounds := make([]common.QuorumRound, 0, len(blocks)) for _, vfb := range blocks { tb := vfb.VerifiedBlock.(*TestBlock) - quorumRounds = append(quorumRounds, simplex.QuorumRound{ + quorumRounds = append(quorumRounds, common.QuorumRound{ Block: tb, Finalization: &vfb.Finalization, }) } // Send replication response without last qr - replicationResponse := &simplex.ReplicationResponse{ + replicationResponse := &common.ReplicationResponse{ Data: quorumRounds[0 : len(quorumRounds)-1], } - e.HandleMessage(&simplex.Message{ + e.HandleMessage(&common.Message{ ReplicationResponse: replicationResponse, }, nodes[1]) @@ -1703,11 +1704,11 @@ func TestReplicationStartsRoundFromFinalizationWithBlock(t *testing.T) { wal.AssertBlockProposal(lastBlock.BlockHeader().Round) // Send replication response - replicationResponse = &simplex.ReplicationResponse{ - Data: []simplex.QuorumRound{quorumRounds[len(quorumRounds)-1]}, + replicationResponse = &common.ReplicationResponse{ + Data: []common.QuorumRound{quorumRounds[len(quorumRounds)-1]}, } - e.HandleMessage(&simplex.Message{ + e.HandleMessage(&common.Message{ ReplicationResponse: replicationResponse, }, nodes[1]) @@ -1717,16 +1718,16 @@ func TestReplicationStartsRoundFromFinalizationWithBlock(t *testing.T) { require.Equal(t, uint64(len(blocks)), storage.NumBlocks()) require.Equal(t, uint64(len(blocks)), e.Metadata().Round) - emptyBlockMd := simplex.EmptyVoteMetadata{ + emptyBlockMd := common.EmptyVoteMetadata{ Round: uint64(len(blocks)), } // the other two nodes send empty votes - e.HandleMessage(&simplex.Message{ + e.HandleMessage(&common.Message{ EmptyVoteMessage: createEmptyVote(emptyBlockMd, nodes[1]), }, nodes[1]) - e.HandleMessage(&simplex.Message{ + e.HandleMessage(&common.Message{ EmptyVoteMessage: createEmptyVote(emptyBlockMd, nodes[2]), }, nodes[2]) diff --git a/replication_timeout_test.go b/simplex/replication_timeout_test.go similarity index 90% rename from replication_timeout_test.go rename to simplex/replication_timeout_test.go index d2c23aec..f234a7cb 100644 --- a/replication_timeout_test.go +++ b/simplex/replication_timeout_test.go @@ -12,18 +12,19 @@ import ( "testing" "time" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" + "github.com/ava-labs/simplex/simplex" "github.com/ava-labs/simplex/testutil" "github.com/stretchr/testify/require" ) -func rejectReplicationRequests(msg *simplex.Message, _, _ simplex.NodeID) bool { +func rejectReplicationRequests(msg *common.Message, _, _ common.NodeID) bool { return msg.ReplicationRequest == nil && msg.ReplicationResponse == nil && msg.VerifiedReplicationResponse == nil } // A node attempts to request blocks to replicate, but fails to receive them func TestReplicationRequestTimeout(t *testing.T) { - nodes := []simplex.NodeID{{1}, {2}, {3}, []byte("lagging")} + nodes := []common.NodeID{{1}, {2}, {3}, []byte("lagging")} numInitialSeqs := uint64(8) // node begins replication @@ -31,7 +32,7 @@ func TestReplicationRequestTimeout(t *testing.T) { storageData := createBlocks(t, nodes, numInitialSeqs) - newNodeConfig := func(from simplex.NodeID) *testutil.TestNodeConfig { + newNodeConfig := func(from common.NodeID) *testutil.TestNodeConfig { comm := testutil.NewTestComm(from, net.BasicInMemoryNetwork, rejectReplicationRequests) return &testutil.TestNodeConfig{ InitialStorage: storageData, @@ -81,14 +82,14 @@ type testTimeoutMessageFilter struct { replicationResponses chan struct{} } -func (m *testTimeoutMessageFilter) failOnReplicationRequest(msg *simplex.Message, _, _ simplex.NodeID) bool { +func (m *testTimeoutMessageFilter) failOnReplicationRequest(msg *common.Message, _, _ common.NodeID) bool { require.Nil(m.t, msg.ReplicationRequest) return true } // receiveReplicationRequest is used to filter out sending replication responses, and notify a channel // when a replication request is received. -func (m *testTimeoutMessageFilter) receivedReplicationRequest(msg *simplex.Message, _, _ simplex.NodeID) bool { +func (m *testTimeoutMessageFilter) receivedReplicationRequest(msg *common.Message, _, _ common.NodeID) bool { if msg.VerifiedReplicationResponse != nil || msg.ReplicationResponse != nil { m.replicationResponses <- struct{}{} return false @@ -98,7 +99,7 @@ func (m *testTimeoutMessageFilter) receivedReplicationRequest(msg *simplex.Messa } func TestReplicationRequestTimeoutCancels(t *testing.T) { - nodes := []simplex.NodeID{{1}, {2}, {3}, []byte("lagging")} + nodes := []common.NodeID{{1}, {2}, {3}, []byte("lagging")} startSeq := uint64(8) net := testutil.NewControlledNetwork(t, nodes) @@ -147,7 +148,7 @@ func TestReplicationRequestTimeoutCancels(t *testing.T) { // A node attempts to request blocks to replicate, but fails to // receive them multiple times func TestReplicationRequestTimeoutMultiple(t *testing.T) { - nodes := []simplex.NodeID{{1}, {2}, {3}, []byte("lagging")} + nodes := []common.NodeID{{1}, {2}, {3}, []byte("lagging")} startSeq := uint64(8) // node begins replication @@ -155,7 +156,7 @@ func TestReplicationRequestTimeoutMultiple(t *testing.T) { storageData := createBlocks(t, nodes, startSeq) - newNodeConfig := func(from simplex.NodeID) *testutil.TestNodeConfig { + newNodeConfig := func(from common.NodeID) *testutil.TestNodeConfig { comm := testutil.NewTestComm(from, net.BasicInMemoryNetwork, rejectReplicationRequests) return &testutil.TestNodeConfig{ InitialStorage: storageData, @@ -214,10 +215,10 @@ func TestReplicationRequestTimeoutMultiple(t *testing.T) { } // modifies the replication response to only send every even quorum round -func incompleteReplicationResponseFilter(msg *simplex.Message, _, _ simplex.NodeID) bool { +func incompleteReplicationResponseFilter(msg *common.Message, _, _ common.NodeID) bool { if msg.VerifiedReplicationResponse != nil || msg.ReplicationResponse != nil { newLen := len(msg.VerifiedReplicationResponse.Data) / 2 - newData := make([]simplex.VerifiedQuorumRound, 0, newLen) + newData := make([]common.VerifiedQuorumRound, 0, newLen) for _, qr := range msg.VerifiedReplicationResponse.Data { if qr.GetRound()%2 == 0 { @@ -232,7 +233,7 @@ func incompleteReplicationResponseFilter(msg *simplex.Message, _, _ simplex.Node // A node attempts to request blocks to replicate, but receives incomplete // responses from nodes. func TestReplicationRequestIncompleteResponses(t *testing.T) { - nodes := []simplex.NodeID{{1}, {2}, {3}, []byte("lagging")} + nodes := []common.NodeID{{1}, {2}, {3}, []byte("lagging")} startSeq := uint64(8) // node begins replication @@ -240,7 +241,7 @@ func TestReplicationRequestIncompleteResponses(t *testing.T) { storageData := createBlocks(t, nodes, startSeq) - newNodeConfig := func(from simplex.NodeID) *testutil.TestNodeConfig { + newNodeConfig := func(from common.NodeID) *testutil.TestNodeConfig { comm := testutil.NewTestComm(from, net.BasicInMemoryNetwork, rejectReplicationRequests) return &testutil.TestNodeConfig{ InitialStorage: storageData, @@ -259,7 +260,7 @@ func TestReplicationRequestIncompleteResponses(t *testing.T) { normalNode2.E.Comm.(*testutil.TestComm).SetFilter(mf.receivedReplicationRequest) testutil.NewControlledSimplexNode(t, nodes[2], net, newNodeConfig(nodes[2])) - recordedMessages := make(chan *simplex.Message, 1000) + recordedMessages := make(chan *common.Message, 1000) comm := testutil.NewTestComm(nodes[3], net.BasicInMemoryNetwork, testutil.AllowAllMessages) laggingNode := testutil.NewControlledSimplexNode(t, nodes[3], net, &testutil.TestNodeConfig{ @@ -323,13 +324,13 @@ func TestReplicationRequestIncompleteResponses(t *testing.T) { type collectNotarizationComm struct { lock *sync.Mutex - notarizations map[uint64]*simplex.Notarization + notarizations map[uint64]*common.Notarization testutil.TestNetworkCommunication replicationResponses chan struct{} } -func newCollectNotarizationComm(nodeID simplex.NodeID, net *testutil.ControlledInMemoryNetwork, notarizations map[uint64]*simplex.Notarization, lock *sync.Mutex) *collectNotarizationComm { +func newCollectNotarizationComm(nodeID common.NodeID, net *testutil.ControlledInMemoryNetwork, notarizations map[uint64]*common.Notarization, lock *sync.Mutex) *collectNotarizationComm { return &collectNotarizationComm{ notarizations: notarizations, TestNetworkCommunication: testutil.NewTestComm(nodeID, net.BasicInMemoryNetwork, testutil.AllowAllMessages), @@ -338,7 +339,7 @@ func newCollectNotarizationComm(nodeID simplex.NodeID, net *testutil.ControlledI } } -func (c *collectNotarizationComm) Send(msg *simplex.Message, to simplex.NodeID) { +func (c *collectNotarizationComm) Send(msg *common.Message, to common.NodeID) { if msg.Notarization != nil { c.lock.Lock() c.notarizations[msg.Notarization.Vote.Round] = msg.Notarization @@ -347,7 +348,7 @@ func (c *collectNotarizationComm) Send(msg *simplex.Message, to simplex.NodeID) c.TestNetworkCommunication.Send(msg, to) } -func (c *collectNotarizationComm) Broadcast(msg *simplex.Message) { +func (c *collectNotarizationComm) Broadcast(msg *common.Message) { if msg.Notarization != nil { c.lock.Lock() c.notarizations[msg.Notarization.Vote.Round] = msg.Notarization @@ -356,12 +357,12 @@ func (c *collectNotarizationComm) Broadcast(msg *simplex.Message) { c.TestNetworkCommunication.Broadcast(msg) } -func (c *collectNotarizationComm) removeFinalizationsFromReplicationResponses(msg *simplex.Message, from, to simplex.NodeID) bool { +func (c *collectNotarizationComm) removeFinalizationsFromReplicationResponses(msg *common.Message, from, to common.NodeID) bool { c.lock.Lock() defer c.lock.Unlock() if msg.VerifiedReplicationResponse != nil || msg.ReplicationResponse != nil { - newData := make([]simplex.VerifiedQuorumRound, 0, len(msg.VerifiedReplicationResponse.Data)) + newData := make([]common.VerifiedQuorumRound, 0, len(msg.VerifiedReplicationResponse.Data)) for i := 0; i < len(msg.VerifiedReplicationResponse.Data); i++ { qr := msg.VerifiedReplicationResponse.Data[i] @@ -393,13 +394,13 @@ func (c *collectNotarizationComm) removeFinalizationsFromReplicationResponses(ms // TestReplicationRequestWithoutFinalization tests that a replication request is not marked as completed // if we are expecting a finalization but it is not present in the response. func TestReplicationRequestWithoutFinalization(t *testing.T) { - nodes := []simplex.NodeID{{1}, {2}, {3}, []byte("lagging")} + nodes := []common.NodeID{{1}, {2}, {3}, []byte("lagging")} endDisconnect := uint64(10) net := testutil.NewControlledNetwork(t, nodes) - notarizations := make(map[uint64]*simplex.Notarization) + notarizations := make(map[uint64]*common.Notarization) mapLock := &sync.Mutex{} - testConfig := func(nodeID simplex.NodeID) *testutil.TestNodeConfig { + testConfig := func(nodeID common.NodeID) *testutil.TestNodeConfig { return &testutil.TestNodeConfig{ ReplicationEnabled: true, Comm: newCollectNotarizationComm(nodeID, net, notarizations, mapLock), @@ -495,7 +496,7 @@ func TestReplicationRequestWithoutFinalization(t *testing.T) { // TestReplicationMalformedQuorumRound tests that a node re-sends a replication request when it receives a malformed quorum round message. func TestReplicationMalformedQuorumRound(t *testing.T) { - nodes := []simplex.NodeID{{1}, {2}, {3}, []byte("lagging")} + nodes := []common.NodeID{{1}, {2}, {3}, []byte("lagging")} startSeq := uint64(8) // node begins replication @@ -503,7 +504,7 @@ func TestReplicationMalformedQuorumRound(t *testing.T) { storageData := createBlocks(t, nodes, startSeq) - newNodeConfig := func(from simplex.NodeID) *testutil.TestNodeConfig { + newNodeConfig := func(from common.NodeID) *testutil.TestNodeConfig { comm := testutil.NewTestComm(from, net.BasicInMemoryNetwork, rejectReplicationRequests) return &testutil.TestNodeConfig{ InitialStorage: storageData, @@ -522,7 +523,7 @@ func TestReplicationMalformedQuorumRound(t *testing.T) { normalNode2.E.Comm.(*testutil.TestComm).SetFilter(mf.receivedReplicationRequest) testutil.NewControlledSimplexNode(t, nodes[2], net, newNodeConfig(nodes[2])) - recordedMessages := make(chan *simplex.Message, 1000) + recordedMessages := make(chan *common.Message, 1000) comm := testutil.NewTestComm(nodes[3], net.BasicInMemoryNetwork, testutil.AllowAllMessages) laggingNode := testutil.NewControlledSimplexNode(t, nodes[3], net, &testutil.TestNodeConfig{ @@ -550,9 +551,9 @@ func TestReplicationMalformedQuorumRound(t *testing.T) { // assert the lagging node has not received any replication responses require.Equal(t, uint64(0), laggingNode.Storage.NumBlocks()) net.SetAllNodesMessageFilter( - func(msg *simplex.Message, _, _ simplex.NodeID) bool { + func(msg *common.Message, _, _ common.NodeID) bool { if msg.VerifiedReplicationResponse != nil || msg.ReplicationResponse != nil { - newData := make([]simplex.VerifiedQuorumRound, 0, len(msg.VerifiedReplicationResponse.Data)) + newData := make([]common.VerifiedQuorumRound, 0, len(msg.VerifiedReplicationResponse.Data)) for _, qr := range msg.VerifiedReplicationResponse.Data { qr.Notarization = nil // remove notarization @@ -597,9 +598,9 @@ func TestReplicationResendsFinalizedBlocksThatFailedVerification(t *testing.T) { // send a block, then simultaneously send a finalization for the block bb := testutil.NewTestBlockBuilder() - nodes := []simplex.NodeID{{1}, {2}, {3}, {4}} + nodes := []common.NodeID{{1}, {2}, {3}, {4}} quorum := simplex.Quorum(len(nodes)) - sentMessages := make(chan *simplex.Message, 100) + sentMessages := make(chan *common.Message, 100) conf, _, storage := testutil.DefaultTestNodeEpochConfig(t, nodes[1], &recordingComm{ Communication: testutil.NewNoopComm(nodes), @@ -625,7 +626,7 @@ func TestReplicationResendsFinalizedBlocksThatFailedVerification(t *testing.T) { finalization, _ := testutil.NewFinalizationRecord(t, sigAggr, block, nodes[0:quorum]) // send the finalization to start the replication process - e.HandleMessage(&simplex.Message{ + e.HandleMessage(&common.Message{ Finalization: &finalization, }, nodes[0]) // wait for the replication request to be sent @@ -635,15 +636,15 @@ func TestReplicationResendsFinalizedBlocksThatFailedVerification(t *testing.T) { break } } - replicationResponse := &simplex.ReplicationResponse{ - Data: []simplex.QuorumRound{ + replicationResponse := &common.ReplicationResponse{ + Data: []common.QuorumRound{ { Block: block, Finalization: &finalization, }, }, } - e.HandleMessage(&simplex.Message{ + e.HandleMessage(&common.Message{ ReplicationResponse: replicationResponse, }, nodes[0]) // wait for the replication request to be sent again @@ -659,8 +660,8 @@ func TestReplicationResendsFinalizedBlocksThatFailedVerification(t *testing.T) { block.ComputeDigest() finalization, _ = testutil.NewFinalizationRecord(t, sigAggr, block, nodes[0:quorum]) - replicationResponse = &simplex.ReplicationResponse{ - Data: []simplex.QuorumRound{ + replicationResponse = &common.ReplicationResponse{ + Data: []common.QuorumRound{ { Block: block, Finalization: &finalization, @@ -668,7 +669,7 @@ func TestReplicationResendsFinalizedBlocksThatFailedVerification(t *testing.T) { }, } - e.HandleMessage(&simplex.Message{ + e.HandleMessage(&common.Message{ ReplicationResponse: replicationResponse, }, nodes[0]) diff --git a/requestor.go b/simplex/requestor.go similarity index 88% rename from requestor.go rename to simplex/requestor.go index d66785f2..2fafb2e0 100644 --- a/requestor.go +++ b/simplex/requestor.go @@ -8,6 +8,7 @@ import ( "sync" "time" + "github.com/ava-labs/simplex/common" "go.uber.org/zap" ) @@ -16,10 +17,10 @@ import ( type signedQuorum struct { round uint64 seq uint64 - signers NodeIDs + signers common.NodeIDs } -func newSignedQuorum(qr *QuorumRound, myNodeID NodeID) *signedQuorum { +func newSignedQuorum(qr *common.QuorumRound, myNodeID common.NodeID) *signedQuorum { // it's possible our node has signed this quorum. // For example this may happen if our node has sent a finalized vote // for this round and has not received the @@ -27,18 +28,18 @@ func newSignedQuorum(qr *QuorumRound, myNodeID NodeID) *signedQuorum { switch { case qr.EmptyNotarization != nil: return &signedQuorum{ - signers: NodeIDs(qr.EmptyNotarization.QC.Signers()).Remove(myNodeID), + signers: common.NodeIDs(qr.EmptyNotarization.QC.Signers()).Remove(myNodeID), round: qr.EmptyNotarization.Vote.Round, } case qr.Finalization != nil: return &signedQuorum{ - signers: NodeIDs(qr.Finalization.QC.Signers()).Remove(myNodeID), + signers: common.NodeIDs(qr.Finalization.QC.Signers()).Remove(myNodeID), round: qr.Finalization.Finalization.Round, seq: qr.Finalization.Finalization.Seq, } case qr.Notarization != nil: return &signedQuorum{ - signers: NodeIDs(qr.Notarization.QC.Signers()).Remove(myNodeID), + signers: common.NodeIDs(qr.Notarization.QC.Signers()).Remove(myNodeID), round: qr.Notarization.Vote.Round, seq: qr.Notarization.Vote.Seq, } @@ -47,23 +48,23 @@ func newSignedQuorum(qr *QuorumRound, myNodeID NodeID) *signedQuorum { } } -func newSignedQuorumFromFinalization(finalization *Finalization, nodeID NodeID) *signedQuorum { - return newSignedQuorum(&QuorumRound{ +func newSignedQuorumFromFinalization(finalization *common.Finalization, nodeID common.NodeID) *signedQuorum { + return newSignedQuorum(&common.QuorumRound{ Finalization: finalization, }, nodeID) } -func newSignedQuorumFromRound(round, seq uint64, signers []NodeID, myNodeID NodeID) *signedQuorum { +func newSignedQuorumFromRound(round, seq uint64, signers []common.NodeID, myNodeID common.NodeID) *signedQuorum { return &signedQuorum{ round: round, seq: seq, - signers: NodeIDs(signers).Remove(myNodeID), + signers: common.NodeIDs(signers).Remove(myNodeID), } } type Sender interface { // Send sends a message to the given destination node - Send(msg *Message, destination NodeID) + Send(msg *common.Message, destination common.NodeID) } // requestor fetches quorum rounds up to [highestObserved] from the network, @@ -87,7 +88,7 @@ type requestor struct { // Handles timeouts and retries for missing sequences/rounds. timeoutHandler *TimeoutHandler[uint64] - logger Logger + logger common.Logger // maxRoundWindow is the maximum number of requests we can request past highestRequested. maxRoundWindow uint64 @@ -101,7 +102,7 @@ type requestor struct { replicateSeqs bool } -func newRequestor(logger Logger, start time.Time, lock *sync.Mutex, maxRoundWindow uint64, sender Sender, replicateSeqs bool) *requestor { +func newRequestor(logger common.Logger, start time.Time, lock *sync.Mutex, maxRoundWindow uint64, sender Sender, replicateSeqs bool) *requestor { r := &requestor{ logger: logger, epochLock: lock, @@ -172,7 +173,7 @@ func (r *requestor) sendReplicationRequests(start uint64, end uint64) { numNodes := len(nodes) seqRequests := DistributeSequenceRequests(start, end, numNodes) - r.logger.Debug("Distributing replication requests", zap.Uint64("start", start), zap.Uint64("end", end), zap.Stringer("nodes", NodeIDs(nodes))) + r.logger.Debug("Distributing replication requests", zap.Uint64("start", start), zap.Uint64("end", end), zap.Stringer("nodes", common.NodeIDs(nodes))) r.sendSegments(seqRequests) @@ -191,7 +192,7 @@ func (r *requestor) sendSegments(segments []Segment) { // sendRequestToNode requests [start, end] from nodes[index]. // In case the nodes[index] does not respond, we create a timeout that will // re-send the request. -func (r *requestor) sendRequestToNode(start uint64, end uint64, node NodeID) { +func (r *requestor) sendRequestToNode(start uint64, end uint64, node common.NodeID) { seqsOrRound := make([]uint64, 0, (end+1)-start) for i := start; i <= end; i++ { // Skip sequences we have already committed; @@ -211,7 +212,7 @@ func (r *requestor) sendRequestToNode(start uint64, end uint64, node NodeID) { r.highestRequested = end } - request := &ReplicationRequest{} + request := &common.ReplicationRequest{} if r.replicateSeqs { request.LatestFinalizedSeq = r.highestObserved.seq request.Seqs = seqsOrRound @@ -220,7 +221,7 @@ func (r *requestor) sendRequestToNode(start uint64, end uint64, node NodeID) { request.Rounds = seqsOrRound } - msg := &Message{ReplicationRequest: request} + msg := &common.Message{ReplicationRequest: request} r.logger.Debug("Requesting missing rounds/sequences ", zap.Stringer("from", node), diff --git a/sched.go b/simplex/sched.go similarity index 92% rename from sched.go rename to simplex/sched.go index 5afe8256..cb82fe7b 100644 --- a/sched.go +++ b/simplex/sched.go @@ -6,11 +6,12 @@ package simplex import ( "sync" + "github.com/ava-labs/simplex/common" "go.uber.org/zap" ) type BasicScheduler struct { - logger Logger + logger common.Logger mu sync.Mutex closed bool @@ -18,7 +19,7 @@ type BasicScheduler struct { tasks chan Task } -func NewScheduler(logger Logger, maxTasks uint64) *BasicScheduler { +func NewScheduler(logger common.Logger, maxTasks uint64) *BasicScheduler { s := &BasicScheduler{ logger: logger, tasks: make(chan Task, maxTasks), @@ -104,4 +105,4 @@ func (as *BasicScheduler) ScheduleOrReplace(task Task) { as.tasks <- task } -type Task func() Digest +type Task func() common.Digest diff --git a/sched_test.go b/simplex/sched_test.go similarity index 81% rename from sched_test.go rename to simplex/sched_test.go index e3f71438..4dd331c1 100644 --- a/sched_test.go +++ b/simplex/sched_test.go @@ -8,7 +8,8 @@ import ( "sync" "testing" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" + "github.com/ava-labs/simplex/simplex" "github.com/ava-labs/simplex/testutil" "github.com/stretchr/testify/require" ) @@ -27,7 +28,7 @@ func TestAsyncScheduler(t *testing.T) { dig2 := makeDigest(t) - as.Schedule(func() simplex.Digest { + as.Schedule(func() common.Digest { defer wg.Done() <-ticks return dig2 @@ -44,7 +45,7 @@ func TestAsyncScheduler(t *testing.T) { as.Close() dig := makeDigest(t) - as.Schedule(func() simplex.Digest { + as.Schedule(func() common.Digest { close(ticks) return dig }) @@ -53,8 +54,8 @@ func TestAsyncScheduler(t *testing.T) { }) } -func makeDigest(t *testing.T) simplex.Digest { - var dig simplex.Digest +func makeDigest(t *testing.T) common.Digest { + var dig common.Digest _, err := rand.Read(dig[:]) require.NoError(t, err) return dig diff --git a/timeout_handler.go b/simplex/timeout_handler.go similarity index 92% rename from timeout_handler.go rename to simplex/timeout_handler.go index f7625f82..8777ef80 100644 --- a/timeout_handler.go +++ b/simplex/timeout_handler.go @@ -8,6 +8,7 @@ import ( "sync" "time" + "github.com/ava-labs/simplex/common" "go.uber.org/zap" ) @@ -27,13 +28,13 @@ type TimeoutHandler[T comparable] struct { tasks map[T]struct{} now time.Time - log Logger + log common.Logger running sync.WaitGroup } // NewTimeoutHandler returns a TimeoutHandler and starts a new goroutine that // listens for ticks and executes TimeoutTasks. -func NewTimeoutHandler[T comparable](log Logger, name string, startTime time.Time, runInterval time.Duration, taskRunner timeoutRunner[T]) *TimeoutHandler[T] { +func NewTimeoutHandler[T comparable](log common.Logger, name string, startTime time.Time, runInterval time.Duration, taskRunner timeoutRunner[T]) *TimeoutHandler[T] { t := &TimeoutHandler[T]{ name: name, now: startTime, diff --git a/timeout_handler_test.go b/simplex/timeout_handler_test.go similarity index 99% rename from timeout_handler_test.go rename to simplex/timeout_handler_test.go index e3358190..7ff700b3 100644 --- a/timeout_handler_test.go +++ b/simplex/timeout_handler_test.go @@ -8,7 +8,7 @@ import ( "testing" "time" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/simplex" "github.com/ava-labs/simplex/testutil" "github.com/stretchr/testify/require" diff --git a/util.go b/simplex/util.go similarity index 84% rename from util.go rename to simplex/util.go index 45bdf2da..36390acb 100644 --- a/util.go +++ b/simplex/util.go @@ -14,13 +14,18 @@ import ( "sync" "time" + "github.com/ava-labs/simplex/common" "go.uber.org/zap" ) +type verifiableMessage interface { + Verify() error +} + // RetrieveLastIndexFromStorage retrieves the latest block and finalization from storage. // Returns an error if it cannot be retrieved but the storage has some block. // Returns (nil, nil) if the storage is empty. -func RetrieveLastIndexFromStorage(s Storage) (*VerifiedFinalizedBlock, error) { +func RetrieveLastIndexFromStorage(s common.Storage) (*common.VerifiedFinalizedBlock, error) { numBlocks := s.NumBlocks() if numBlocks == 0 { return nil, nil @@ -29,13 +34,13 @@ func RetrieveLastIndexFromStorage(s Storage) (*VerifiedFinalizedBlock, error) { if err != nil { return nil, fmt.Errorf("failed retrieving last block from storage with seq %d: %w", numBlocks-1, err) } - return &VerifiedFinalizedBlock{ + return &common.VerifiedFinalizedBlock{ VerifiedBlock: lastBlock, Finalization: finalization, }, nil } -func hasSomeNodeSignedTwice(nodeIDs []NodeID, logger Logger) (NodeID, bool) { +func hasSomeNodeSignedTwice(nodeIDs []common.NodeID, logger common.Logger) (common.NodeID, bool) { seen := make(map[string]struct{}, len(nodeIDs)) for _, nodeID := range nodeIDs { @@ -46,10 +51,10 @@ func hasSomeNodeSignedTwice(nodeIDs []NodeID, logger Logger) (NodeID, bool) { seen[string(nodeID)] = struct{}{} } - return NodeID{}, false + return common.NodeID{}, false } -func VerifyQC(qc QuorumCertificate, logger Logger, messageType string, isQuorum func(signers []NodeID) bool, eligibleSigners map[string]struct{}, messageToVerify verifiableMessage, from NodeID) error { +func VerifyQC(qc common.QuorumCertificate, logger common.Logger, messageType string, isQuorum func(signers []common.NodeID) bool, eligibleSigners map[string]struct{}, messageToVerify verifiableMessage, from common.NodeID) error { if qc == nil { logger.Debug("Received nil QuorumCertificate") return fmt.Errorf("nil QuorumCertificate") @@ -90,14 +95,14 @@ func VerifyQC(qc QuorumCertificate, logger Logger, messageType string, isQuorum // GetLatestVerifiedQuorumRound returns the latest verified quorum round given // a round and empty notarization. If both are nil, it returns nil. -func GetLatestVerifiedQuorumRound(round *Round, emptyNotarization *EmptyNotarization) *VerifiedQuorumRound { - var verifiedQuorumRound *VerifiedQuorumRound +func GetLatestVerifiedQuorumRound(round *Round, emptyNotarization *common.EmptyNotarization) *common.VerifiedQuorumRound { + var verifiedQuorumRound *common.VerifiedQuorumRound var highestRound uint64 var exists bool if round != nil && (round.finalization != nil || round.notarization != nil) { highestRound = round.num - verifiedQuorumRound = &VerifiedQuorumRound{ + verifiedQuorumRound = &common.VerifiedQuorumRound{ VerifiedBlock: round.block, Notarization: round.notarization, Finalization: round.finalization, @@ -108,7 +113,7 @@ func GetLatestVerifiedQuorumRound(round *Round, emptyNotarization *EmptyNotariza if emptyNotarization != nil { emptyNoteRound := emptyNotarization.Vote.Round if emptyNoteRound > highestRound || !exists { - verifiedQuorumRound = &VerifiedQuorumRound{ + verifiedQuorumRound = &common.VerifiedQuorumRound{ EmptyNotarization: emptyNotarization, } } @@ -118,7 +123,7 @@ func GetLatestVerifiedQuorumRound(round *Round, emptyNotarization *EmptyNotariza } // SetRound is a helper function that is used for tests to create a round. -func SetRound(block VerifiedBlock, notarization *Notarization, finalization *Finalization) *Round { +func SetRound(block common.VerifiedBlock, notarization *common.Notarization, finalization *common.Finalization) *Round { round := &Round{ block: block, notarization: notarization, @@ -131,18 +136,18 @@ func SetRound(block VerifiedBlock, notarization *Notarization, finalization *Fin type OneTimeVerifier struct { lock sync.Mutex - digests map[Digest]verifiedResult - logger Logger + digests map[common.Digest]verifiedResult + logger common.Logger } -func NewOneTimeVerifier(logger Logger) *OneTimeVerifier { +func NewOneTimeVerifier(logger common.Logger) *OneTimeVerifier { return &OneTimeVerifier{ - digests: make(map[Digest]verifiedResult), + digests: make(map[common.Digest]verifiedResult), logger: logger, } } -func (otv *OneTimeVerifier) Wrap(block Block) Block { +func (otv *OneTimeVerifier) Wrap(block common.Block) common.Block { return &oneTimeVerifiedBlock{ otv: otv, Block: block, @@ -151,16 +156,16 @@ func (otv *OneTimeVerifier) Wrap(block Block) Block { type verifiedResult struct { seq uint64 - vb VerifiedBlock + vb common.VerifiedBlock err error } type oneTimeVerifiedBlock struct { otv *OneTimeVerifier - Block + common.Block } -func (block *oneTimeVerifiedBlock) Verify(ctx context.Context) (VerifiedBlock, error) { +func (block *oneTimeVerifiedBlock) Verify(ctx context.Context) (common.VerifiedBlock, error) { block.otv.lock.Lock() defer block.otv.lock.Unlock() @@ -339,19 +344,19 @@ func (nt *NotarizationTime) CheckForNotFinalizedNotarizedBlocks(now time.Time) { } type voteSigner interface { - Signer() NodeID + Signer() common.NodeID } -func NodeIDsFromVotes[VS voteSigner](votes []VS) []NodeID { - nodeIDs := make([]NodeID, 0, len(votes)) +func NodeIDsFromVotes[VS voteSigner](votes []VS) []common.NodeID { + nodeIDs := make([]common.NodeID, 0, len(votes)) for _, vote := range votes { nodeIDs = append(nodeIDs, vote.Signer()) } return nodeIDs } -func emptyVotesToSignatures(votes []*EmptyVote) []Signature { - sigs := make([]Signature, 0, len(votes)) +func emptyVotesToSignatures(votes []*common.EmptyVote) []common.Signature { + sigs := make([]common.Signature, 0, len(votes)) for _, vote := range votes { sigs = append(sigs, vote.Signature) } @@ -360,11 +365,11 @@ func emptyVotesToSignatures(votes []*EmptyVote) []Signature { type walRound struct { round uint64 - emptyNotarization *EmptyNotarization - emptyVote *ToBeSignedEmptyVote - notarization *Notarization - finalization *Finalization - block Block + emptyNotarization *common.EmptyNotarization + emptyVote *common.ToBeSignedEmptyVote + notarization *common.Notarization + finalization *common.Finalization + block common.Block } func (t *walRound) String() string { diff --git a/util_test.go b/simplex/util_test.go similarity index 99% rename from util_test.go rename to simplex/util_test.go index 3e4e23b2..a9447d7b 100644 --- a/util_test.go +++ b/simplex/util_test.go @@ -9,7 +9,8 @@ import ( "testing" "time" - . "github.com/ava-labs/simplex" + . "github.com/ava-labs/simplex/common" + . "github.com/ava-labs/simplex/simplex" "github.com/ava-labs/simplex/testutil" "github.com/stretchr/testify/require" diff --git a/testutil/block.go b/testutil/block.go index 176e39ee..f6ffe017 100644 --- a/testutil/block.go +++ b/testutil/block.go @@ -10,20 +10,20 @@ import ( "encoding/asn1" "fmt" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" ) type TestBlock struct { Data []byte - Metadata simplex.ProtocolMetadata - blacklist simplex.Blacklist + Metadata common.ProtocolMetadata + blacklist common.Blacklist Digest [32]byte OnVerify func() VerificationDelay chan struct{} VerificationError error } -func NewTestBlock(metadata simplex.ProtocolMetadata, blacklist simplex.Blacklist) *TestBlock { +func NewTestBlock(metadata common.ProtocolMetadata, blacklist common.Blacklist) *TestBlock { tb := TestBlock{ blacklist: blacklist, Metadata: metadata, @@ -34,11 +34,11 @@ func NewTestBlock(metadata simplex.ProtocolMetadata, blacklist simplex.Blacklist return &tb } -func (tb *TestBlock) Blacklist() simplex.Blacklist { +func (tb *TestBlock) Blacklist() common.Blacklist { return tb.blacklist } -func (tb *TestBlock) Verify(context.Context) (simplex.VerifiedBlock, error) { +func (tb *TestBlock) Verify(context.Context) (common.VerifiedBlock, error) { defer func() { if tb.OnVerify != nil { tb.OnVerify() @@ -69,15 +69,15 @@ func (tb *TestBlock) ComputeDigest() { tb.Digest = sha256.Sum256(bb.Bytes()) } -func (t *TestBlock) BlockHeader() simplex.BlockHeader { - return simplex.BlockHeader{ +func (t *TestBlock) BlockHeader() common.BlockHeader { + return common.BlockHeader{ ProtocolMetadata: t.Metadata, Digest: t.Digest, } } func (t *TestBlock) Bytes() ([]byte, error) { - bh := simplex.BlockHeader{ + bh := common.BlockHeader{ ProtocolMetadata: t.Metadata, } @@ -112,19 +112,19 @@ type BlockDeserializer struct { DelayedVerification chan struct{} } -func (b *BlockDeserializer) DeserializeBlock(ctx context.Context, buff []byte) (simplex.Block, error) { +func (b *BlockDeserializer) DeserializeBlock(ctx context.Context, buff []byte) (common.Block, error) { var encodedBlock EncodedTestBlock _, err := asn1.Unmarshal(buff, &encodedBlock) if err != nil { return nil, err } - md, err := simplex.ProtocolMetadataFromBytes(encodedBlock.Metadata) + md, err := common.ProtocolMetadataFromBytes(encodedBlock.Metadata) if err != nil { return nil, err } - var blacklist simplex.Blacklist + var blacklist common.Blacklist if err := blacklist.FromBytes(encodedBlock.Blacklist); err != nil { return nil, err } diff --git a/testutil/block_builder.go b/testutil/block_builder.go index 8cd9a24a..c6604903 100644 --- a/testutil/block_builder.go +++ b/testutil/block_builder.go @@ -7,7 +7,7 @@ import ( "context" "time" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" ) type TestBlockBuilder struct { @@ -33,7 +33,7 @@ func (t *TestBlockBuilder) WithBlockShouldBeBuiltBuffer(buffer uint64) *TestBloc return t } -func (t *TestBlockBuilder) BuildBlock(_ context.Context, metadata simplex.ProtocolMetadata, blacklist simplex.Blacklist) (simplex.VerifiedBlock, bool) { +func (t *TestBlockBuilder) BuildBlock(_ context.Context, metadata common.ProtocolMetadata, blacklist common.Blacklist) (common.VerifiedBlock, bool) { tb := NewTestBlock(metadata, blacklist) select { diff --git a/testutil/comm.go b/testutil/comm.go index 71f33191..94e3bce1 100644 --- a/testutil/comm.go +++ b/testutil/comm.go @@ -7,7 +7,7 @@ import ( "bytes" "sync" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" "github.com/stretchr/testify/require" ) @@ -20,30 +20,30 @@ import ( // // Returns: // - bool: true if the message can be transmitted, false otherwise -type MessageFilter func(msg *simplex.Message, from simplex.NodeID, to simplex.NodeID) bool +type MessageFilter func(msg *common.Message, from common.NodeID, to common.NodeID) bool -type NoopComm simplex.Nodes +type NoopComm common.Nodes -func (n NoopComm) Nodes() simplex.Nodes { - return simplex.Nodes(n) +func (n NoopComm) Nodes() common.Nodes { + return common.Nodes(n) } -func (n NoopComm) Send(*simplex.Message, simplex.NodeID) { +func (n NoopComm) Send(*common.Message, common.NodeID) { } -func (n NoopComm) Broadcast(msg *simplex.Message) { +func (n NoopComm) Broadcast(msg *common.Message) { } type TestComm struct { - from simplex.NodeID + from common.NodeID net *BasicInMemoryNetwork messageFilter MessageFilter lock sync.RWMutex } -func NewTestComm(from simplex.NodeID, net *BasicInMemoryNetwork, messageFilter MessageFilter) *TestComm { +func NewTestComm(from common.NodeID, net *BasicInMemoryNetwork, messageFilter MessageFilter) *TestComm { return &TestComm{ from: from, net: net, @@ -51,11 +51,11 @@ func NewTestComm(from simplex.NodeID, net *BasicInMemoryNetwork, messageFilter M } } -func (c *TestComm) Nodes() simplex.Nodes { +func (c *TestComm) Nodes() common.Nodes { return c.net.nodeWeights } -func (c *TestComm) Send(msg *simplex.Message, destination simplex.NodeID) { +func (c *TestComm) Send(msg *common.Message, destination common.NodeID) { if !c.isMessagePermitted(msg, destination) { return } @@ -92,19 +92,19 @@ func (c *TestComm) SetFilter(filter MessageFilter) { c.messageFilter = filter } -func (c *TestComm) maybeTranslateOutgoingToIncomingMessageTypes(msg *simplex.Message) { +func (c *TestComm) maybeTranslateOutgoingToIncomingMessageTypes(msg *common.Message) { if msg.VerifiedReplicationResponse != nil { - data := make([]simplex.QuorumRound, 0, len(msg.VerifiedReplicationResponse.Data)) + data := make([]common.QuorumRound, 0, len(msg.VerifiedReplicationResponse.Data)) for _, verifiedQuorumRound := range msg.VerifiedReplicationResponse.Data { // Outgoing block is of type verified block but incoming block is of type Block, // so we do a type cast because the test block implements both. - quorumRound := simplex.QuorumRound{} + quorumRound := common.QuorumRound{} if verifiedQuorumRound.EmptyNotarization != nil { quorumRound.EmptyNotarization = verifiedQuorumRound.EmptyNotarization } if verifiedQuorumRound.VerifiedBlock != nil { - quorumRound.Block = verifiedQuorumRound.VerifiedBlock.(simplex.Block) + quorumRound.Block = verifiedQuorumRound.VerifiedBlock.(common.Block) } if verifiedQuorumRound.Notarization != nil { quorumRound.Notarization = verifiedQuorumRound.Notarization @@ -125,7 +125,7 @@ func (c *TestComm) maybeTranslateOutgoingToIncomingMessageTypes(msg *simplex.Mes "message cannot include ReplicationResponse & VerifiedReplicationResponse", ) - msg.ReplicationResponse = &simplex.ReplicationResponse{ + msg.ReplicationResponse = &common.ReplicationResponse{ Data: data, LatestRound: latestRound, LatestSeq: latestSeq, @@ -134,39 +134,39 @@ func (c *TestComm) maybeTranslateOutgoingToIncomingMessageTypes(msg *simplex.Mes if msg.VerifiedBlockMessage != nil { require.Nil(c.net.t, msg.BlockMessage, "message cannot include BlockMessage & VerifiedBlockMessage") - msg.BlockMessage = &simplex.BlockMessage{ - Block: msg.VerifiedBlockMessage.VerifiedBlock.(simplex.Block), + msg.BlockMessage = &common.BlockMessage{ + Block: msg.VerifiedBlockMessage.VerifiedBlock.(common.Block), Vote: msg.VerifiedBlockMessage.Vote, } } } -func verifiedQRtoQR(vqr *simplex.VerifiedQuorumRound) *simplex.QuorumRound { +func verifiedQRtoQR(vqr *common.VerifiedQuorumRound) *common.QuorumRound { if vqr == nil { return nil } - qr := &simplex.QuorumRound{ + qr := &common.QuorumRound{ Notarization: vqr.Notarization, Finalization: vqr.Finalization, EmptyNotarization: vqr.EmptyNotarization, } if vqr.VerifiedBlock != nil { - qr.Block = vqr.VerifiedBlock.(simplex.Block) + qr.Block = vqr.VerifiedBlock.(common.Block) } return qr } -func (c *TestComm) isMessagePermitted(msg *simplex.Message, destination simplex.NodeID) bool { +func (c *TestComm) isMessagePermitted(msg *common.Message, destination common.NodeID) bool { c.lock.RLock() defer c.lock.RUnlock() return c.messageFilter(msg, c.from, destination) } -func (c *TestComm) Broadcast(msg *simplex.Message) { +func (c *TestComm) Broadcast(msg *common.Message) { if c.net.IsDisconnected(c.from) { return } @@ -187,10 +187,10 @@ func (c *TestComm) Broadcast(msg *simplex.Message) { } // AllowAllMessages allows every message to be sent -func AllowAllMessages(*simplex.Message, simplex.NodeID, simplex.NodeID) bool { +func AllowAllMessages(*common.Message, common.NodeID, common.NodeID) bool { return true } -func NewNoopComm(nodes simplex.NodeIDs) NoopComm { +func NewNoopComm(nodes common.NodeIDs) NoopComm { return NoopComm(nodes.EqualWeightedNodes()) } diff --git a/testutil/controlled.go b/testutil/controlled.go index e9a337d3..3ca1b4e8 100644 --- a/testutil/controlled.go +++ b/testutil/controlled.go @@ -7,8 +7,9 @@ import ( "testing" "time" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" "github.com/ava-labs/simplex/record" + "github.com/ava-labs/simplex/simplex" "github.com/stretchr/testify/require" "go.uber.org/zap" ) @@ -20,7 +21,7 @@ type ControlledInMemoryNetwork struct { // NewControlledNetwork creates an in-memory network. Node IDs must be provided before // adding instances, as nodeWeights require prior knowledge of all participants. -func NewControlledNetwork(t *testing.T, nodes simplex.NodeIDs) *ControlledInMemoryNetwork { +func NewControlledNetwork(t *testing.T, nodes common.NodeIDs) *ControlledInMemoryNetwork { simplex.SortNodes(nodes.EqualWeightedNodes()) net := &ControlledInMemoryNetwork{ BasicInMemoryNetwork: NewBasicInMemoryNetwork(t, nodes), @@ -56,7 +57,7 @@ func (n *ControlledInMemoryNetwork) addNode(node *ControlledNode) { n.Instances = append(n.Instances, node) } -func (n *ControlledInMemoryNetwork) AdvanceWithoutLeader(round uint64, laggingNodeId simplex.NodeID) { +func (n *ControlledInMemoryNetwork) AdvanceWithoutLeader(round uint64, laggingNodeId common.NodeID) { // we need to ensure all blocks are waiting for the channel before proceeding // otherwise, we may send to a channel that is not ready to receive for _, n := range n.Instances { @@ -97,7 +98,7 @@ type ControlledNode struct { } // newSimplexNode creates a new testNode and adds it to [net]. -func NewControlledSimplexNode(t *testing.T, nodeID simplex.NodeID, net *ControlledInMemoryNetwork, config *TestNodeConfig) *ControlledNode { +func NewControlledSimplexNode(t *testing.T, nodeID common.NodeID, net *ControlledInMemoryNetwork, config *TestNodeConfig) *ControlledNode { comm := NewTestComm(nodeID, net.BasicInMemoryNetwork, AllowAllMessages) bb := NewTestControlledBlockBuilder(t) if config != nil && config.BlockBuilder != nil { @@ -210,7 +211,7 @@ func (t *testControlledBlockBuilder) TriggerNewBlock() { } } -func (t *testControlledBlockBuilder) BuildBlock(ctx context.Context, metadata simplex.ProtocolMetadata, blacklist simplex.Blacklist) (simplex.VerifiedBlock, bool) { +func (t *testControlledBlockBuilder) BuildBlock(ctx context.Context, metadata common.ProtocolMetadata, blacklist common.Blacklist) (common.VerifiedBlock, bool) { select { case <-t.control: case <-ctx.Done(): diff --git a/testutil/long_running/block_builder.go b/testutil/long_running/block_builder.go index b18a4865..f892b72c 100644 --- a/testutil/long_running/block_builder.go +++ b/testutil/long_running/block_builder.go @@ -8,11 +8,11 @@ import ( "sync" "testing" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" "github.com/ava-labs/simplex/testutil" ) -var _ simplex.BlockBuilder = (*LongRunningBlockBuilder)(nil) +var _ common.BlockBuilder = (*LongRunningBlockBuilder)(nil) type LongRunningBlockBuilder struct { t *testing.T @@ -39,9 +39,9 @@ func (b *LongRunningBlockBuilder) notifyChanged() { func (b *LongRunningBlockBuilder) BuildBlock( ctx context.Context, - metadata simplex.ProtocolMetadata, - blacklist simplex.Blacklist, -) (simplex.VerifiedBlock, bool) { + metadata common.ProtocolMetadata, + blacklist common.Blacklist, +) (common.VerifiedBlock, bool) { for { b.mu.Lock() pending := b.blockPending diff --git a/testutil/long_running/network.go b/testutil/long_running/network.go index be883b7e..f055c5a1 100644 --- a/testutil/long_running/network.go +++ b/testutil/long_running/network.go @@ -9,7 +9,8 @@ import ( "testing" "time" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" + "github.com/ava-labs/simplex/simplex" "github.com/ava-labs/simplex/testutil" "github.com/stretchr/testify/require" ) @@ -27,7 +28,7 @@ type LongRunningInMemoryNetwork struct { } func NewDefaultLongRunningNetwork(t *testing.T, numNodes int) *LongRunningInMemoryNetwork { - nodes := make([]simplex.NodeID, numNodes) + nodes := make([]common.NodeID, numNodes) for i := range numNodes { nodes[i] = testutil.GenerateNodeID(t) } diff --git a/testutil/long_running/node.go b/testutil/long_running/node.go index c3893a2b..22950f74 100644 --- a/testutil/long_running/node.go +++ b/testutil/long_running/node.go @@ -6,7 +6,8 @@ package long_running import ( "testing" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" + "github.com/ava-labs/simplex/simplex" "github.com/ava-labs/simplex/testutil" "github.com/stretchr/testify/require" ) @@ -26,7 +27,7 @@ type longRunningNodeConfig struct { logger *testutil.TestLogger } -func defaultLongRunningNodeConfig(t *testing.T, nodeID simplex.NodeID, basicNetwork *testutil.BasicInMemoryNetwork, options longRunningNodeConfig) (simplex.EpochConfig, *LongRunningBlockBuilder, *testutil.TestWAL, *testutil.InMemStorage) { +func defaultLongRunningNodeConfig(t *testing.T, nodeID common.NodeID, basicNetwork *testutil.BasicInMemoryNetwork, options longRunningNodeConfig) (simplex.EpochConfig, *LongRunningBlockBuilder, *testutil.TestWAL, *testutil.InMemStorage) { comm := testutil.NewTestComm(nodeID, basicNetwork, testutil.AllowAllMessages) bb := NewNetworkBlockBuilder(t) if options.bb != nil { @@ -56,7 +57,7 @@ func defaultLongRunningNodeConfig(t *testing.T, nodeID simplex.NodeID, basicNetw return epochConfig, bb, wal, storage } -func NewLongRunningNode(t *testing.T, nodeID simplex.NodeID, basicNetwork *testutil.BasicInMemoryNetwork, options longRunningNodeConfig) *LongRunningNode { +func NewLongRunningNode(t *testing.T, nodeID common.NodeID, basicNetwork *testutil.BasicInMemoryNetwork, options longRunningNodeConfig) *LongRunningNode { epochConfig, bb, wal, storage := defaultLongRunningNodeConfig(t, nodeID, basicNetwork, options) e, err := simplex.NewEpoch(epochConfig) require.NoError(t, err) diff --git a/testutil/network.go b/testutil/network.go index 8ce6ac58..797f8963 100644 --- a/testutil/network.go +++ b/testutil/network.go @@ -9,20 +9,21 @@ import ( "testing" "time" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" + "github.com/ava-labs/simplex/simplex" "github.com/stretchr/testify/require" ) type BasicInMemoryNetwork struct { t *testing.T - nodes []simplex.NodeID - nodeWeights simplex.Nodes + nodes []common.NodeID + nodeWeights common.Nodes lock sync.RWMutex disconnected map[string]struct{} instances []*BasicNode } -func NewBasicInMemoryNetwork(t *testing.T, nodes simplex.NodeIDs) *BasicInMemoryNetwork { +func NewBasicInMemoryNetwork(t *testing.T, nodes common.NodeIDs) *BasicInMemoryNetwork { nodeWeights := nodes.EqualWeightedNodes() simplex.SortNodes(nodeWeights) return &BasicInMemoryNetwork{ @@ -35,11 +36,11 @@ func NewBasicInMemoryNetwork(t *testing.T, nodes simplex.NodeIDs) *BasicInMemory } type TestNetworkCommunication interface { - simplex.Communication + common.Communication SetFilter(filter MessageFilter) } -func (b *BasicInMemoryNetwork) SetNodeMessageFilter(node simplex.NodeID, filter MessageFilter) { +func (b *BasicInMemoryNetwork) SetNodeMessageFilter(node common.NodeID, filter MessageFilter) { b.lock.RLock() defer b.lock.RUnlock() @@ -68,7 +69,7 @@ func (b *BasicInMemoryNetwork) SetAllNodesMessageFilter(filter MessageFilter) { } } -func (b *BasicInMemoryNetwork) IsDisconnected(node simplex.NodeID) bool { +func (b *BasicInMemoryNetwork) IsDisconnected(node common.NodeID) bool { b.lock.RLock() defer b.lock.RUnlock() @@ -76,14 +77,14 @@ func (b *BasicInMemoryNetwork) IsDisconnected(node simplex.NodeID) bool { return ok } -func (b *BasicInMemoryNetwork) Connect(node simplex.NodeID) { +func (b *BasicInMemoryNetwork) Connect(node common.NodeID) { b.lock.Lock() defer b.lock.Unlock() delete(b.disconnected, string(node)) } -func (b *BasicInMemoryNetwork) Disconnect(node simplex.NodeID) { +func (b *BasicInMemoryNetwork) Disconnect(node common.NodeID) { b.lock.Lock() defer b.lock.Unlock() diff --git a/testutil/node.go b/testutil/node.go index 21784a1e..9e4a2458 100644 --- a/testutil/node.go +++ b/testutil/node.go @@ -11,7 +11,8 @@ import ( "testing" "time" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" + "github.com/ava-labs/simplex/simplex" "github.com/stretchr/testify/require" "go.uber.org/zap" ) @@ -26,14 +27,14 @@ type BasicNode struct { E *simplex.Epoch ingress chan struct { - msg *simplex.Message - from simplex.NodeID + msg *common.Message + from common.NodeID } l *TestLogger t *testing.T messageTypesSent map[string]uint64 - CustomHandler func(msg *simplex.Message, from simplex.NodeID) error + CustomHandler func(msg *common.Message, from common.NodeID) error } func NewBasicNode(t *testing.T, epoch *simplex.Epoch, logger *TestLogger) *BasicNode { @@ -44,8 +45,8 @@ func NewBasicNode(t *testing.T, epoch *simplex.Epoch, logger *TestLogger) *Basic running: sync.WaitGroup{}, E: epoch, ingress: make(chan struct { - msg *simplex.Message - from simplex.NodeID + msg *common.Message + from common.NodeID }, 100000), l: logger, t: t, @@ -76,7 +77,7 @@ func (b *BasicNode) SilenceExceptKeywords(keywords ...string) { b.l.SilenceExceptKeywords(keywords...) } -func (b *BasicNode) HandleMessage(msg *simplex.Message, from simplex.NodeID) error { +func (b *BasicNode) HandleMessage(msg *common.Message, from common.NodeID) error { err := b.E.HandleMessage(msg, from) if err != nil { b.l.Error("error handling message", zap.Stringer("from", from), zap.Stringer("to", b.E.ID), zap.Error(err), zap.Error(err), zap.Any("message", msg)) @@ -105,7 +106,7 @@ func (b *BasicNode) handleMessages() { } } -func (b *BasicNode) enqueue(msg *simplex.Message, from, to simplex.NodeID) { +func (b *BasicNode) enqueue(msg *common.Message, from, to common.NodeID) { b.lock.Lock() defer b.lock.Unlock() if b.shouldStop.Load() { @@ -122,8 +123,8 @@ func (b *BasicNode) enqueue(msg *simplex.Message, from, to simplex.NodeID) { select { case b.ingress <- struct { - msg *simplex.Message - from simplex.NodeID + msg *common.Message + from common.NodeID }{msg: msg, from: from}: default: // drop the message if the ingress channel is full @@ -141,7 +142,7 @@ func (b *BasicNode) Stop() { b.running.Wait() } -func (b *BasicNode) RecordMessageTypeSent(msg *simplex.Message) { +func (b *BasicNode) RecordMessageTypeSent(msg *common.Message) { switch { case msg.BlockMessage != nil: b.messageTypesSent["BlockMessage"]++ @@ -234,9 +235,9 @@ func UpdateEpochConfig(epochConfig *simplex.EpochConfig, testConfig *TestNodeCon // NodeConfig type TestNodeConfig struct { // optional - InitialStorage []simplex.VerifiedFinalizedBlock - Comm simplex.Communication - SigAggregatorCreator simplex.SignatureAggregatorCreator + InitialStorage []common.VerifiedFinalizedBlock + Comm common.Communication + SigAggregatorCreator common.SignatureAggregatorCreator ReplicationEnabled bool BlockBuilder *testControlledBlockBuilder diff --git a/testutil/random_network/block.go b/testutil/random_network/block.go index 59e3f3f9..c216c6ac 100644 --- a/testutil/random_network/block.go +++ b/testutil/random_network/block.go @@ -9,26 +9,26 @@ import ( "encoding/asn1" "fmt" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" ) -var _ simplex.Block = (*Block)(nil) +var _ common.Block = (*Block)(nil) type Block struct { - blacklist simplex.Blacklist + blacklist common.Blacklist // contents txs []*TX // protocol metadata - metadata simplex.ProtocolMetadata - digest simplex.Digest + metadata common.ProtocolMetadata + digest common.Digest // mempool access mempool *Mempool } -func NewBlock(metadata simplex.ProtocolMetadata, blacklist simplex.Blacklist, mempool *Mempool, txs []*TX) *Block { +func NewBlock(metadata common.ProtocolMetadata, blacklist common.Blacklist, mempool *Mempool, txs []*TX) *Block { b := &Block{ mempool: mempool, txs: txs, @@ -40,16 +40,16 @@ func NewBlock(metadata simplex.ProtocolMetadata, blacklist simplex.Blacklist, me return b } -func (b *Block) Verify(ctx context.Context) (simplex.VerifiedBlock, error) { +func (b *Block) Verify(ctx context.Context) (common.VerifiedBlock, error) { return b, b.mempool.VerifyBlock(ctx, b) } -func (b *Block) Blacklist() simplex.Blacklist { +func (b *Block) Blacklist() common.Blacklist { return b.blacklist } -func (b *Block) BlockHeader() simplex.BlockHeader { - return simplex.BlockHeader{ +func (b *Block) BlockHeader() common.BlockHeader { + return common.BlockHeader{ ProtocolMetadata: b.metadata, Digest: b.digest, } @@ -102,21 +102,21 @@ type BlockDeserializer struct { mempool *Mempool } -var _ simplex.BlockDeserializer = (*BlockDeserializer)(nil) +var _ common.BlockDeserializer = (*BlockDeserializer)(nil) -func (bd *BlockDeserializer) DeserializeBlock(ctx context.Context, buff []byte) (simplex.Block, error) { +func (bd *BlockDeserializer) DeserializeBlock(ctx context.Context, buff []byte) (common.Block, error) { var encodedBlock encodedBlock _, err := asn1.Unmarshal(buff, &encodedBlock) if err != nil { return nil, err } - md, err := simplex.ProtocolMetadataFromBytes(encodedBlock.ProtocolMetadata) + md, err := common.ProtocolMetadataFromBytes(encodedBlock.ProtocolMetadata) if err != nil { return nil, err } - var blacklist simplex.Blacklist + var blacklist common.Blacklist if err := blacklist.FromBytes(encodedBlock.Blacklist); err != nil { return nil, err } diff --git a/testutil/random_network/config.go b/testutil/random_network/config.go index d60512db..e3e353dc 100644 --- a/testutil/random_network/config.go +++ b/testutil/random_network/config.go @@ -6,7 +6,7 @@ package random_network import ( "time" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/simplex" ) type FuzzConfig struct { diff --git a/testutil/random_network/logging.go b/testutil/random_network/logging.go index 92e27592..dc3ea12b 100644 --- a/testutil/random_network/logging.go +++ b/testutil/random_network/logging.go @@ -9,7 +9,7 @@ import ( "path/filepath" "testing" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" "github.com/ava-labs/simplex/testutil" "go.uber.org/zap/zapcore" ) @@ -35,7 +35,7 @@ func CreateNetworkLogger(t *testing.T, config *FuzzConfig) *testutil.TestLogger } // CreateNodeLogger creates a logger for a node that writes to both console and {nodeID}.log -func CreateNodeLogger(t *testing.T, config *FuzzConfig, nodeID simplex.NodeID) *testutil.TestLogger { +func CreateNodeLogger(t *testing.T, config *FuzzConfig, nodeID common.NodeID) *testutil.TestLogger { if config.LogDirectory == "" { return testutil.MakeLogger(t, int(nodeID[0])) } diff --git a/testutil/random_network/mempool.go b/testutil/random_network/mempool.go index 47087efa..a395745b 100644 --- a/testutil/random_network/mempool.go +++ b/testutil/random_network/mempool.go @@ -11,11 +11,11 @@ import ( "slices" "sync" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" "go.uber.org/zap" ) -var emptyDigest = simplex.Digest{} +var emptyDigest = common.Digest{} var ( errAlreadyAccepted = errors.New("tx already accepted") @@ -29,27 +29,27 @@ type Mempool struct { lock *sync.Mutex config *FuzzConfig txsReady chan struct{} - logger simplex.Logger + logger common.Logger // txID -> TX unacceptedTxs map[txID]*TX // blocks that have been verified but not accepted - verifiedButNotAcceptedBlocks map[simplex.Digest]*Block + verifiedButNotAcceptedBlocks map[common.Digest]*Block // all the blocks that have been accepted - acceptedBlocks map[simplex.Digest]*Block + acceptedBlocks map[common.Digest]*Block // fast lookup of accepted txs acceptedTXs map[txID]struct{} } -func NewMempool(l simplex.Logger, config *FuzzConfig) *Mempool { +func NewMempool(l common.Logger, config *FuzzConfig) *Mempool { return &Mempool{ unacceptedTxs: make(map[txID]*TX), - verifiedButNotAcceptedBlocks: make(map[simplex.Digest]*Block), + verifiedButNotAcceptedBlocks: make(map[common.Digest]*Block), acceptedTXs: make(map[txID]struct{}), - acceptedBlocks: make(map[simplex.Digest]*Block), + acceptedBlocks: make(map[common.Digest]*Block), lock: &sync.Mutex{}, txsReady: make(chan struct{}, 1), logger: l, @@ -164,7 +164,7 @@ func (m *Mempool) isParentAcceptedOrVerified(block *Block) bool { } // verifyTx verifies a single transaction against the mempool state and the block's chain. -func (m *Mempool) verifyTx(ctx context.Context, tx *TX, blockParent simplex.Digest) error { +func (m *Mempool) verifyTx(ctx context.Context, tx *TX, blockParent common.Digest) error { if _, exists := m.acceptedTXs[tx.ID]; exists { return fmt.Errorf("%w: %s", errAlreadyAccepted, tx.ID) } @@ -180,7 +180,7 @@ func (m *Mempool) verifyTx(ctx context.Context, tx *TX, blockParent simplex.Dige } // recursively check if the tx has already been included in any ancestor block to prevent double spends -func (m *Mempool) isTxInChain(txID txID, parentDigest simplex.Digest) bool { +func (m *Mempool) isTxInChain(txID txID, parentDigest common.Digest) bool { block, exists := m.verifiedButNotAcceptedBlocks[parentDigest] if !exists { return false @@ -245,7 +245,7 @@ func (m *Mempool) moveTxsToUnaccepted(block *Block) { } } -func (m *Mempool) BuildBlock(ctx context.Context, md simplex.ProtocolMetadata, bl simplex.Blacklist) (simplex.VerifiedBlock, bool) { +func (m *Mempool) BuildBlock(ctx context.Context, md common.ProtocolMetadata, bl common.Blacklist) (common.VerifiedBlock, bool) { m.waitForPendingTxs(ctx) // Pack the block once we have pending txs @@ -271,7 +271,7 @@ func (m *Mempool) BuildBlock(ctx context.Context, md simplex.ProtocolMetadata, b return block, true } -func (m *Mempool) packBlock(ctx context.Context, maxTxs int, parentDigest simplex.Digest) []*TX { +func (m *Mempool) packBlock(ctx context.Context, maxTxs int, parentDigest common.Digest) []*TX { m.lock.Lock() defer m.lock.Unlock() @@ -328,5 +328,5 @@ func (m *Mempool) Clear() { } } - m.verifiedButNotAcceptedBlocks = make(map[simplex.Digest]*Block) + m.verifiedButNotAcceptedBlocks = make(map[common.Digest]*Block) } diff --git a/testutil/random_network/mempool_test.go b/testutil/random_network/mempool_test.go index 0119a434..c56f6af5 100644 --- a/testutil/random_network/mempool_test.go +++ b/testutil/random_network/mempool_test.go @@ -7,15 +7,15 @@ import ( "context" "testing" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" "github.com/ava-labs/simplex/testutil" "github.com/stretchr/testify/require" ) -var emptyBlacklist = simplex.Blacklist{ +var emptyBlacklist = common.Blacklist{ NodeCount: 4, - SuspectedNodes: simplex.SuspectedNodes{}, - Updates: []simplex.BlacklistUpdate{}, + SuspectedNodes: common.SuspectedNodes{}, + Updates: []common.BlacklistUpdate{}, } func TestMempoolVerifiesTx(t *testing.T) { @@ -24,7 +24,7 @@ func TestMempoolVerifiesTx(t *testing.T) { ctx := context.Background() require := require.New(t) - round0MD := NewProtocolMetadata(0, 0, simplex.Digest{}) + round0MD := NewProtocolMetadata(0, 0, common.Digest{}) config := DefaultFuzzConfig() tests := []struct { @@ -117,7 +117,7 @@ func TestMempoolVerifiesTx(t *testing.T) { err := mempool.VerifyBlock(ctx, blockWithSameTxButNotParent) mempool.AddPendingTXs(tx1) - block := NewBlock(NewProtocolMetadata(1, 1, simplex.Digest{}), emptyBlacklist, mempool, []*TX{tx1}) + block := NewBlock(NewProtocolMetadata(1, 1, common.Digest{}), emptyBlacklist, mempool, []*TX{tx1}) return mempool, block, err }, }, diff --git a/testutil/random_network/network.go b/testutil/random_network/network.go index a2f6d247..b3b59c9e 100644 --- a/testutil/random_network/network.go +++ b/testutil/random_network/network.go @@ -9,7 +9,7 @@ import ( "testing" "time" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" "github.com/ava-labs/simplex/testutil" "go.uber.org/zap" "go.uber.org/zap/zapcore" @@ -36,7 +36,7 @@ func NewNetwork(config *FuzzConfig, t *testing.T) *Network { r := rand.New(rand.NewSource(config.RandomSeed)) numNodes := r.Intn(config.MaxNodes-config.MinNodes+1) + config.MinNodes - nodeIds := make([]simplex.NodeID, numNodes) + nodeIds := make([]common.NodeID, numNodes) for i := range numNodes { nodeIds[i] = []byte{byte(i)} } @@ -98,7 +98,7 @@ func (n *Network) Run() { clearLogDirectory(n.config.LogDirectory) } -func (n *Network) getMinHeightNodeID() simplex.NodeID { +func (n *Network) getMinHeightNodeID() common.NodeID { minHeight := n.nodes[0].storage.NumBlocks() minHeightNodeID := n.nodes[0].E.ID @@ -216,8 +216,8 @@ func (n *Network) crashAndRecoverNodes() { return } - crashedNodes := []simplex.NodeID{} - recoveredNodes := []simplex.NodeID{} + crashedNodes := []common.NodeID{} + recoveredNodes := []common.NodeID{} maxLeftToCrash := f - int(n.numCrashedNodes()) // go through each node, randomly decide to crash based on NodeCrashPercentage for i, node := range n.nodes { diff --git a/testutil/random_network/node.go b/testutil/random_network/node.go index 44620749..a12ebb1a 100644 --- a/testutil/random_network/node.go +++ b/testutil/random_network/node.go @@ -7,7 +7,8 @@ import ( "sync/atomic" "testing" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" + "github.com/ava-labs/simplex/simplex" "github.com/ava-labs/simplex/testutil" "github.com/stretchr/testify/require" ) @@ -30,7 +31,7 @@ type Node struct { isCrashed atomic.Bool } -func NewNode(t *testing.T, nodeID simplex.NodeID, net *testutil.BasicInMemoryNetwork, config *FuzzConfig, nodeConfig randomNodeConfig) *Node { +func NewNode(t *testing.T, nodeID common.NodeID, net *testutil.BasicInMemoryNetwork, config *FuzzConfig, nodeConfig randomNodeConfig) *Node { var l *testutil.TestLogger if nodeConfig.logger != nil { l = nodeConfig.logger @@ -88,13 +89,13 @@ func NewNode(t *testing.T, nodeID simplex.NodeID, net *testutil.BasicInMemoryNet return n } -func (n *Node) HandleMessage(msg *simplex.Message, from simplex.NodeID) error { +func (n *Node) HandleMessage(msg *common.Message, from common.NodeID) error { msgCopy := n.copyMessage(msg) return n.BasicNode.HandleMessage(&msgCopy, from) } // copyBlock creates a copy of a simplex.Block with the node's mempool. -func (n *Node) copyBlock(b simplex.Block) simplex.Block { +func (n *Node) copyBlock(b common.Block) common.Block { blockCopy := *b.(*Block) blockCopy.mempool = n.mempool return &blockCopy @@ -103,7 +104,7 @@ func (n *Node) copyBlock(b simplex.Block) simplex.Block { // copyMessage creates a copy of the message and its relevant fields to avoid mutating shared state in the in-memory network // this is important because blocks are not serialized/deserialized in our current comm implementation, so sending blocks // also sends relevant state associated with the node that is sending the message which can cause unintended side effects. -func (n *Node) copyMessage(msg *simplex.Message) simplex.Message { +func (n *Node) copyMessage(msg *common.Message) common.Message { msgCopy := *msg switch { @@ -116,7 +117,7 @@ func (n *Node) copyMessage(msg *simplex.Message) simplex.Message { rrCopy := *msgCopy.ReplicationResponse // Also copy the Data slice to avoid mutating shared slice - rrCopy.Data = make([]simplex.QuorumRound, len(msgCopy.ReplicationResponse.Data)) + rrCopy.Data = make([]common.QuorumRound, len(msgCopy.ReplicationResponse.Data)) copy(rrCopy.Data, msgCopy.ReplicationResponse.Data) msgCopy.ReplicationResponse = &rrCopy diff --git a/testutil/random_network/storage.go b/testutil/random_network/storage.go index effc597c..83c49e50 100644 --- a/testutil/random_network/storage.go +++ b/testutil/random_network/storage.go @@ -6,7 +6,7 @@ package random_network import ( "context" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" "github.com/ava-labs/simplex/testutil" ) @@ -22,7 +22,7 @@ func NewStorage(mempool *Mempool) *Storage { } } -func (s *Storage) Index(ctx context.Context, block simplex.VerifiedBlock, certificate simplex.Finalization) error { +func (s *Storage) Index(ctx context.Context, block common.VerifiedBlock, certificate common.Finalization) error { s.mempool.AcceptBlock(block.(*Block)) return s.InMemStorage.Index(ctx, block, certificate) } diff --git a/testutil/random_network/utils.go b/testutil/random_network/utils.go index a9b70756..89b55c07 100644 --- a/testutil/random_network/utils.go +++ b/testutil/random_network/utils.go @@ -4,11 +4,11 @@ package random_network import ( - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" ) -func NewProtocolMetadata(round, seq uint64, prev simplex.Digest) simplex.ProtocolMetadata { - return simplex.ProtocolMetadata{ +func NewProtocolMetadata(round, seq uint64, prev common.Digest) common.ProtocolMetadata { + return common.ProtocolMetadata{ Round: round, Seq: seq, Prev: prev, diff --git a/testutil/record.go b/testutil/record.go index c36eb197..edc05d78 100644 --- a/testutil/record.go +++ b/testutil/record.go @@ -6,64 +6,64 @@ package testutil import ( "testing" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" "github.com/ava-labs/simplex/record" "github.com/stretchr/testify/require" ) // NewEmptyNotarization creates a new empty notarization -func NewEmptyNotarization(nodes []simplex.NodeID, round uint64) *simplex.EmptyNotarization { +func NewEmptyNotarization(nodes []common.NodeID, round uint64) *common.EmptyNotarization { var qc TestQC for i, node := range nodes { - qc = append(qc, simplex.Signature{Signer: node, Value: []byte{byte(i)}}) + qc = append(qc, common.Signature{Signer: node, Value: []byte{byte(i)}}) } - return &simplex.EmptyNotarization{ + return &common.EmptyNotarization{ QC: qc, - Vote: simplex.ToBeSignedEmptyVote{EmptyVoteMetadata: simplex.EmptyVoteMetadata{ + Vote: common.ToBeSignedEmptyVote{EmptyVoteMetadata: common.EmptyVoteMetadata{ Round: round, }}, } } -func NewNotarization(logger simplex.Logger, signatureAggregator simplex.SignatureAggregator, block simplex.VerifiedBlock, ids []simplex.NodeID) (simplex.Notarization, error) { - votesForCurrentRound := make(map[string]*simplex.Vote) +func NewNotarization(logger common.Logger, signatureAggregator common.SignatureAggregator, block common.VerifiedBlock, ids []common.NodeID) (common.Notarization, error) { + votesForCurrentRound := make(map[string]*common.Vote) for _, id := range ids { vote, err := NewTestVote(block, id) if err != nil { - return simplex.Notarization{}, err + return common.Notarization{}, err } votesForCurrentRound[string(id)] = vote } - notarization, err := simplex.NewNotarization(logger, signatureAggregator, votesForCurrentRound, block.BlockHeader()) + notarization, err := common.NewNotarization(logger, signatureAggregator, votesForCurrentRound, block.BlockHeader()) return notarization, err } -func NewNotarizationRecord(logger simplex.Logger, signatureAggregator simplex.SignatureAggregator, block simplex.VerifiedBlock, ids []simplex.NodeID) ([]byte, error) { +func NewNotarizationRecord(logger common.Logger, signatureAggregator common.SignatureAggregator, block common.VerifiedBlock, ids []common.NodeID) ([]byte, error) { notarization, err := NewNotarization(logger, signatureAggregator, block, ids) if err != nil { return nil, err } - record := simplex.NewQuorumRecord(notarization.QC.Bytes(), notarization.Vote.Bytes(), record.NotarizationRecordType) + record := common.NewQuorumRecord(notarization.QC.Bytes(), notarization.Vote.Bytes(), record.NotarizationRecordType) return record, nil } // creates a new finalization -func NewFinalizationRecord(t *testing.T, signatureAggregator simplex.SignatureAggregator, block simplex.VerifiedBlock, ids []simplex.NodeID) (simplex.Finalization, []byte) { - finalizations := make([]*simplex.FinalizeVote, len(ids)) +func NewFinalizationRecord(t *testing.T, signatureAggregator common.SignatureAggregator, block common.VerifiedBlock, ids []common.NodeID) (common.Finalization, []byte) { + finalizations := make([]*common.FinalizeVote, len(ids)) for i, id := range ids { finalizations[i] = NewTestFinalizeVote(t, block, id) } - finalization, err := simplex.NewFinalization(signatureAggregator, finalizations) + finalization, err := common.NewFinalization(signatureAggregator, finalizations) require.NoError(t, err) - record := simplex.NewQuorumRecord(finalization.QC.Bytes(), finalization.Finalization.Bytes(), record.FinalizationRecordType) + record := common.NewQuorumRecord(finalization.QC.Bytes(), finalization.Finalization.Bytes(), record.FinalizationRecordType) return finalization, record } diff --git a/testutil/storage.go b/testutil/storage.go index dc8af15d..5dfc41aa 100644 --- a/testutil/storage.go +++ b/testutil/storage.go @@ -11,14 +11,14 @@ import ( "testing" "time" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" "github.com/stretchr/testify/require" ) type InMemStorage struct { data map[uint64]struct { - simplex.VerifiedBlock - simplex.Finalization + common.VerifiedBlock + common.Finalization } lock sync.Mutex @@ -28,8 +28,8 @@ type InMemStorage struct { func NewInMemStorage() *InMemStorage { s := &InMemStorage{ data: make(map[uint64]struct { - simplex.VerifiedBlock - simplex.Finalization + common.VerifiedBlock + common.Finalization }), } @@ -58,7 +58,7 @@ func (mem *InMemStorage) Clone() *InMemStorage { return clone } -func (mem *InMemStorage) WaitForBlockCommit(seq uint64) simplex.VerifiedBlock { +func (mem *InMemStorage) WaitForBlockCommit(seq uint64) common.VerifiedBlock { mem.lock.Lock() defer mem.lock.Unlock() @@ -81,18 +81,18 @@ func (mem *InMemStorage) EnsureNoBlockCommit(t *testing.T, seq uint64) { }, time.Second, time.Millisecond*100, "block %d has been committed but shouldn't have been", seq) } -func (mem *InMemStorage) Retrieve(seq uint64) (simplex.VerifiedBlock, simplex.Finalization, error) { +func (mem *InMemStorage) Retrieve(seq uint64) (common.VerifiedBlock, common.Finalization, error) { mem.lock.Lock() defer mem.lock.Unlock() item, ok := mem.data[seq] if !ok { - return nil, simplex.Finalization{}, fmt.Errorf("%w: seq %d", simplex.ErrBlockNotFound, seq) + return nil, common.Finalization{}, fmt.Errorf("%w: seq %d", common.ErrBlockNotFound, seq) } return item.VerifiedBlock, item.Finalization, nil } -func (mem *InMemStorage) Index(ctx context.Context, block simplex.VerifiedBlock, certificate simplex.Finalization) error { +func (mem *InMemStorage) Index(ctx context.Context, block common.VerifiedBlock, certificate common.Finalization) error { mem.lock.Lock() defer mem.lock.Unlock() @@ -108,8 +108,8 @@ func (mem *InMemStorage) Index(ctx context.Context, block simplex.VerifiedBlock, } mem.data[seq] = struct { - simplex.VerifiedBlock - simplex.Finalization + common.VerifiedBlock + common.Finalization }{block, certificate, } diff --git a/testutil/util.go b/testutil/util.go index a52b0eef..fe3efd07 100644 --- a/testutil/util.go +++ b/testutil/util.go @@ -10,12 +10,13 @@ import ( "testing" "time" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" + "github.com/ava-labs/simplex/simplex" "github.com/stretchr/testify/require" ) // DefaultTestNodeEpochConfig returns a default epoch config for a given node. -func DefaultTestNodeEpochConfig(t *testing.T, nodeID simplex.NodeID, comm simplex.Communication, bb simplex.BlockBuilder) (simplex.EpochConfig, *TestWAL, *InMemStorage) { +func DefaultTestNodeEpochConfig(t *testing.T, nodeID common.NodeID, comm common.Communication, bb common.BlockBuilder) (simplex.EpochConfig, *TestWAL, *InMemStorage) { l := MakeLogger(t, int(nodeID[0])) storage := NewInMemStorage() wal := NewTestWAL(t) @@ -32,7 +33,7 @@ func DefaultTestNodeEpochConfig(t *testing.T, nodeID simplex.NodeID, comm simple Verifier: &testVerifier{}, Storage: storage, BlockBuilder: bb, - SignatureAggregatorCreator: func(weights []simplex.Node) simplex.SignatureAggregator { + SignatureAggregatorCreator: func(weights []common.Node) common.SignatureAggregator { return &TestSignatureAggregator{N: len(weights)} }, BlockDeserializer: &BlockDeserializer{}, @@ -44,11 +45,11 @@ func DefaultTestNodeEpochConfig(t *testing.T, nodeID simplex.NodeID, comm simple type AnyBlock interface { // BlockHeader encodes a succinct and collision-free representation of a block. - BlockHeader() simplex.BlockHeader + BlockHeader() common.BlockHeader } -func NewTestVote(block AnyBlock, id simplex.NodeID) (*simplex.Vote, error) { - vote := simplex.ToBeSignedVote{ +func NewTestVote(block AnyBlock, id common.NodeID) (*common.Vote, error) { + vote := common.ToBeSignedVote{ BlockHeader: block.BlockHeader(), } sig, err := vote.Sign(&TestSigner{}) @@ -56,8 +57,8 @@ func NewTestVote(block AnyBlock, id simplex.NodeID) (*simplex.Vote, error) { return nil, err } - return &simplex.Vote{ - Signature: simplex.Signature{ + return &common.Vote{ + Signature: common.Signature{ Signer: id, Value: sig, }, @@ -65,46 +66,46 @@ func NewTestVote(block AnyBlock, id simplex.NodeID) (*simplex.Vote, error) { }, nil } -func InjectTestVote(t *testing.T, e *simplex.Epoch, block simplex.VerifiedBlock, id simplex.NodeID) { +func InjectTestVote(t *testing.T, e *simplex.Epoch, block common.VerifiedBlock, id common.NodeID) { vote, err := NewTestVote(block, id) require.NoError(t, err) - err = e.HandleMessage(&simplex.Message{ + err = e.HandleMessage(&common.Message{ VoteMessage: vote, }, id) require.NoError(t, err) } -func NewTestFinalizeVote(t *testing.T, block simplex.VerifiedBlock, id simplex.NodeID) *simplex.FinalizeVote { - f := simplex.ToBeSignedFinalization{BlockHeader: block.BlockHeader()} +func NewTestFinalizeVote(t *testing.T, block common.VerifiedBlock, id common.NodeID) *common.FinalizeVote { + f := common.ToBeSignedFinalization{BlockHeader: block.BlockHeader()} sig, err := f.Sign(&TestSigner{}) require.NoError(t, err) - return &simplex.FinalizeVote{ - Signature: simplex.Signature{ + return &common.FinalizeVote{ + Signature: common.Signature{ Signer: id, Value: sig, }, - Finalization: simplex.ToBeSignedFinalization{ + Finalization: common.ToBeSignedFinalization{ BlockHeader: block.BlockHeader(), }, } } -func InjectTestFinalization(t *testing.T, e *simplex.Epoch, finalization *simplex.Finalization, from simplex.NodeID) { - err := e.HandleMessage(&simplex.Message{ +func InjectTestFinalization(t *testing.T, e *simplex.Epoch, finalization *common.Finalization, from common.NodeID) { + err := e.HandleMessage(&common.Message{ Finalization: finalization, }, from) require.NoError(t, err) } -func InjectTestFinalizeVote(t *testing.T, e *simplex.Epoch, block simplex.VerifiedBlock, id simplex.NodeID) { - err := e.HandleMessage(&simplex.Message{ +func InjectTestFinalizeVote(t *testing.T, e *simplex.Epoch, block common.VerifiedBlock, id common.NodeID) { + err := e.HandleMessage(&common.Message{ FinalizeVote: NewTestFinalizeVote(t, block, id), }, id) require.NoError(t, err) } -func InjectTestNotarization(t *testing.T, e *simplex.Epoch, notarization simplex.Notarization, id simplex.NodeID) { - err := e.HandleMessage(&simplex.Message{ +func InjectTestNotarization(t *testing.T, e *simplex.Epoch, notarization common.Notarization, id common.NodeID) { + err := e.HandleMessage(&common.Message{ Notarization: ¬arization, }, id) require.NoError(t, err) @@ -114,8 +115,8 @@ type testQCDeserializer struct { t *testing.T } -func (t *testQCDeserializer) DeserializeQuorumCertificate(bytes []byte) (simplex.QuorumCertificate, error) { - var qc []simplex.Signature +func (t *testQCDeserializer) DeserializeQuorumCertificate(bytes []byte) (common.QuorumCertificate, error) { + var qc []common.Signature rest, err := asn1.Unmarshal(bytes, &qc) require.NoError(t.t, err) require.Empty(t.t, rest) @@ -125,7 +126,7 @@ func (t *testQCDeserializer) DeserializeQuorumCertificate(bytes []byte) (simplex type TestSignatureAggregator struct { Err error N int - IsQuorumFunc func(signatures []simplex.NodeID) bool + IsQuorumFunc func(signatures []common.NodeID) bool } func (t *TestSignatureAggregator) AppendSignatures(existing []byte, sigs ...[]byte) ([]byte, error) { @@ -139,11 +140,11 @@ func (t *TestSignatureAggregator) AppendSignatures(existing []byte, sigs ...[]by return result, nil } -func (t *TestSignatureAggregator) Aggregate(signatures []simplex.Signature) (simplex.QuorumCertificate, error) { +func (t *TestSignatureAggregator) Aggregate(signatures []common.Signature) (common.QuorumCertificate, error) { return TestQC(signatures), t.Err } -func (t *TestSignatureAggregator) IsQuorum(signers []simplex.NodeID) bool { +func (t *TestSignatureAggregator) IsQuorum(signers []common.NodeID) bool { if t.IsQuorumFunc != nil { return t.IsQuorumFunc(signers) } @@ -154,10 +155,10 @@ func (t *TestSignatureAggregator) IsQuorum(signers []simplex.NodeID) bool { return len(signers) >= simplex.Quorum(t.N) } -type TestQC []simplex.Signature +type TestQC []common.Signature -func (t TestQC) Signers() []simplex.NodeID { - res := make([]simplex.NodeID, 0, len(t)) +func (t TestQC) Signers() []common.NodeID { + res := make([]common.NodeID, 0, len(t)) for _, sig := range t { res = append(res, sig.Signer) } @@ -186,11 +187,11 @@ func (t *TestSigner) Sign([]byte) ([]byte, error) { type testVerifier struct { } -func (t *testVerifier) VerifyBlock(simplex.VerifiedBlock) error { +func (t *testVerifier) VerifyBlock(common.VerifiedBlock) error { return nil } -func (t *testVerifier) Verify(_ []byte, _ []byte, _ simplex.NodeID) error { +func (t *testVerifier) Verify(_ []byte, _ []byte, _ common.NodeID) error { return nil } @@ -253,12 +254,12 @@ func WaitForBlockProposerTimeout(t *testing.T, e *simplex.Epoch, startTime *time } } -func GenerateNodeID(t *testing.T) simplex.NodeID { +func GenerateNodeID(t *testing.T) common.NodeID { b := make([]byte, 32) // fill with cryptographically secure random data _, err := rand.Read(b) require.NoError(t, err) - return simplex.NodeID(b) + return common.NodeID(b) } diff --git a/testutil/wal.go b/testutil/wal.go index 795530dc..0c107770 100644 --- a/testutil/wal.go +++ b/testutil/wal.go @@ -9,14 +9,14 @@ import ( "sync" "testing" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" "github.com/ava-labs/simplex/record" "github.com/ava-labs/simplex/wal" "github.com/stretchr/testify/require" ) type TestWAL struct { - simplex.WriteAheadLog + common.WriteAheadLog t *testing.T lock sync.Mutex signal sync.Cond @@ -89,7 +89,7 @@ func (tw *TestWAL) AssertNotarization(round uint64) uint16 { for _, rawRecord := range rawRecords { if binary.BigEndian.Uint16(rawRecord[:2]) == record.NotarizationRecordType { - _, vote, err := simplex.ParseNotarizationRecord(rawRecord) + _, vote, err := common.ParseNotarizationRecord(rawRecord) require.NoError(tw.t, err) if vote.Round == round { @@ -97,7 +97,7 @@ func (tw *TestWAL) AssertNotarization(round uint64) uint16 { } } if binary.BigEndian.Uint16(rawRecord[:2]) == record.EmptyNotarizationRecordType { - _, vote, err := simplex.ParseEmptyNotarizationRecord(rawRecord) + _, vote, err := common.ParseEmptyNotarizationRecord(rawRecord) require.NoError(tw.t, err) if vote.Round == round { @@ -121,7 +121,7 @@ func (tw *TestWAL) AssertEmptyVote(round uint64) { for _, rawRecord := range rawRecords { if binary.BigEndian.Uint16(rawRecord[:2]) == record.EmptyVoteRecordType { - vote, err := simplex.ParseEmptyVoteRecord(rawRecord) + vote, err := common.ParseEmptyVoteRecord(rawRecord) require.NoError(tw.t, err) if vote.Round == round { @@ -145,7 +145,7 @@ func (tw *TestWAL) AssertBlockProposal(round uint64) { for _, rawRecord := range rawRecords { if binary.BigEndian.Uint16(rawRecord[:2]) == record.BlockRecordType { - bh, _, err := simplex.ParseBlockRecord(rawRecord) + bh, _, err := common.ParseBlockRecord(rawRecord) require.NoError(tw.t, err) if bh.Round == round { @@ -168,7 +168,7 @@ func (tw *TestWAL) ContainsNotarization(round uint64) bool { for _, rawRecord := range rawRecords { if binary.BigEndian.Uint16(rawRecord[:2]) == record.NotarizationRecordType { - _, vote, err := simplex.ParseNotarizationRecord(rawRecord) + _, vote, err := common.ParseNotarizationRecord(rawRecord) require.NoError(tw.t, err) if vote.Round == round { @@ -189,7 +189,7 @@ func (tw *TestWAL) ContainsEmptyVote(round uint64) bool { for _, rawRecord := range rawRecords { if binary.BigEndian.Uint16(rawRecord[:2]) == record.EmptyVoteRecordType { - vote, err := simplex.ParseEmptyVoteRecord(rawRecord) + vote, err := common.ParseEmptyVoteRecord(rawRecord) require.NoError(tw.t, err) if vote.Round == round { @@ -210,7 +210,7 @@ func (tw *TestWAL) ContainsEmptyNotarization(round uint64) bool { for _, rawRecord := range rawRecords { if binary.BigEndian.Uint16(rawRecord[:2]) == record.EmptyNotarizationRecordType { - _, vote, err := simplex.ParseEmptyNotarizationRecord(rawRecord) + _, vote, err := common.ParseEmptyNotarizationRecord(rawRecord) require.NoError(tw.t, err) if vote.Round == round { @@ -232,7 +232,7 @@ type walRound struct { } // AssertHealthy checks that the WAL has at most one of each record type per round. -func (tw *TestWAL) AssertHealthy(bd simplex.BlockDeserializer, qcd simplex.QCDeserializer) { +func (tw *TestWAL) AssertHealthy(bd common.BlockDeserializer, qcd common.QCDeserializer) { ctx := context.Background() records, err := tw.WriteAheadLog.ReadAll() require.NoError(tw.t, err) @@ -244,7 +244,7 @@ func (tw *TestWAL) AssertHealthy(bd simplex.BlockDeserializer, qcd simplex.QCDes switch recordType { case record.BlockRecordType: - block, err := simplex.BlockFromRecord(ctx, bd, r) + block, err := common.BlockFromRecord(ctx, bd, r) require.NoError(tw.t, err) round := block.BlockHeader().Round if _, exists := rounds[round]; !exists { @@ -253,7 +253,7 @@ func (tw *TestWAL) AssertHealthy(bd simplex.BlockDeserializer, qcd simplex.QCDes require.False(tw.t, rounds[round].blockRecord, "duplicate block record for round %d", round) rounds[round].blockRecord = true case record.NotarizationRecordType: - _, vote, err := simplex.ParseNotarizationRecord(r) + _, vote, err := common.ParseNotarizationRecord(r) require.NoError(tw.t, err) round := vote.Round if _, exists := rounds[round]; !exists { @@ -262,7 +262,7 @@ func (tw *TestWAL) AssertHealthy(bd simplex.BlockDeserializer, qcd simplex.QCDes require.False(tw.t, rounds[round].notarizationRecord, "duplicate notarization record for round %d", round) rounds[round].notarizationRecord = true case record.EmptyNotarizationRecordType: - _, vote, err := simplex.ParseEmptyNotarizationRecord(r) + _, vote, err := common.ParseEmptyNotarizationRecord(r) require.NoError(tw.t, err) round := vote.Round if _, exists := rounds[round]; !exists { @@ -271,7 +271,7 @@ func (tw *TestWAL) AssertHealthy(bd simplex.BlockDeserializer, qcd simplex.QCDes require.False(tw.t, rounds[round].emptyNotarizationRecord, "duplicate empty notarization record for round %d", round) rounds[round].emptyNotarizationRecord = true case record.EmptyVoteRecordType: - vote, err := simplex.ParseEmptyVoteRecord(r) + vote, err := common.ParseEmptyVoteRecord(r) require.NoError(tw.t, err) round := vote.Round if _, exists := rounds[round]; !exists { @@ -280,7 +280,7 @@ func (tw *TestWAL) AssertHealthy(bd simplex.BlockDeserializer, qcd simplex.QCDes require.False(tw.t, rounds[round].emptyVoteRecord, "duplicate empty vote record for round %d", round) rounds[round].emptyVoteRecord = true case record.FinalizationRecordType: - finalization, err := simplex.FinalizationFromRecord(r, qcd) + finalization, err := common.FinalizationFromRecord(r, qcd) require.NoError(tw.t, err) round := finalization.Finalization.Round if _, exists := rounds[round]; !exists { diff --git a/wal/gc.go b/wal/gc.go index 4ad3e759..601a68f4 100644 --- a/wal/gc.go +++ b/wal/gc.go @@ -7,7 +7,7 @@ import ( "encoding/base64" "fmt" - "github.com/ava-labs/simplex" + "github.com/ava-labs/simplex/common" ) // Creator creates a DeletableWAL. Returns an error upon failure. @@ -28,7 +28,7 @@ type TruncateableWAL interface { // DeletableWAL is a WAL that can be deleted. type DeletableWAL interface { - simplex.WriteAheadLog + common.WriteAheadLog // Delete deletes the WAL file and after it is called, // it should no longer be used. Delete() error