diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 30087593b8..69094658ad 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,7 @@ name: CI env: + go-version: "1.21" GCLOUD_KEY: ${{ secrets.GCLOUD_KEY }} PROJECT_NAME: ${{ secrets.PROJECT_NAME }} CLUSTER_NAME: ${{ secrets.CLUSTER_NAME }} @@ -65,7 +66,7 @@ jobs: uses: actions/setup-go@v4 with: check-latest: true - go-version-file: "go.mod" + go-version: ${{ env.go-version }} - name: fmt, tidy, generate run: | make install @@ -88,7 +89,7 @@ jobs: uses: actions/setup-go@v4 with: check-latest: true - go-version-file: "go.mod" + go-version: ${{ env.go-version }} - name: setup env run: make install - name: staticcheck @@ -126,7 +127,7 @@ jobs: uses: actions/setup-go@v4 with: check-latest: true - go-version-file: "go.mod" + go-version: ${{ env.go-version }} cache: ${{ runner.arch != 'arm64' }} - name: setup env run: make install @@ -174,7 +175,7 @@ jobs: uses: actions/setup-go@v4 with: check-latest: true - go-version-file: "go.mod" + go-version: ${{ env.go-version }} cache: ${{ runner.arch != 'arm64' }} - name: Add OpenCL support - Ubuntu if: ${{ matrix.os == 'ubuntu-latest' }} @@ -242,7 +243,7 @@ jobs: uses: actions/setup-go@v4 with: check-latest: true - go-version-file: "go.mod" + go-version: ${{ env.go-version }} cache: ${{ runner.arch != 'arm64' }} - name: Add OpenCL support - Ubuntu if: ${{ matrix.os == 'ubuntu-latest' }} diff --git a/.github/workflows/systest.yml b/.github/workflows/systest.yml index 576db71eac..1a5c276a90 100644 --- a/.github/workflows/systest.yml +++ b/.github/workflows/systest.yml @@ -77,7 +77,7 @@ jobs: run: gcloud container clusters get-credentials ${{ secrets.CI_CLUSTER_NAME }} --region ${{ secrets.CI_REGION_NAME }} --project ${{ secrets.CI_GCP_PROJECT_ID }} - name: Login to Docker Hub - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c8b8cee07..54a9347f18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,12 +9,25 @@ See [RELEASE](./RELEASE.md) for workflow instructions. A new config `poet-request-timeout` has been added, that defines the timeout for requesting PoET proofs. It defaults to 9 minutes so there is enough time to retry if the request fails. +Config option and flag `p2p-disable-legacy-discovery` and `disable-dht` have been dropped. DHT has been the +only p2p discovery mechanism since release v1.1.2. + +Support for old certificate sync protocol is dropped. This update is incompatible with v1.0.x series. + ### Highlights ### Features +* [#5031](https://github.com/spacemeshos/go-spacemesh/pull/5031) Nodes will also fetch from PoET 112 for round 4 if they were able to register to PoET 110. + ### Improvements +* [#4998](https://github.com/spacemeshos/go-spacemesh/pull/4998) First phase of state size reduction. + Ephemeral data are deleted and state compacted at the time of upgrade. In steady-state, data is pruned periodically. +* [#5021](https://github.com/spacemeshos/go-spacemesh/pull/5021) Drop support for old certificate sync protocol. +* [#5024](https://github.com/spacemeshos/go-spacemesh/pull/5024) Active set will be saved in state separately from ballots. +* [#5035](https://github.com/spacemeshos/go-spacemesh/pull/5035) Fix possible nil pointer panic when node fails to persist nipost builder state. + ## v1.1.5 ### Upgrade information @@ -35,7 +48,7 @@ active set will not be gossipped together with proposals. That was the main netw * `postdata_metadata.json` is now updated atomically to prevent corruption of the file. * [#4956](https://github.com/spacemeshos/go-spacemesh/pull/4956) Active set is will not be gossipped in every proposal. Active set usually contains list of atxs that targets current epoch. As the number of atxs grows this object grows as well. -* [#4993](https://github.com/spacemeshos/go-spacemesh/pull/4993) Drop proposals after genering a block. This limits growth of the state. +* [#4993](https://github.com/spacemeshos/go-spacemesh/pull/4993) Drop proposals after generating a block. This limits growth of the state. ## v1.1.4 @@ -53,7 +66,7 @@ to set lower expected latency in the network, eventually reducing layer time. ### Improvements -* [#4879](https://github.com/spacemeshos/go-spacemesh/pull/4795) Makes majority calculation weighted for optimistic filtering. +* [#4879](https://github.com/spacemeshos/go-spacemesh/pull/4879) Makes majority calculation weighted for optimistic filtering. The network will start using the new algorithm at layer 18_000 (2023-09-14 20:00:00 +0000 UTC) * [#4923](https://github.com/spacemeshos/go-spacemesh/pull/4923) Faster ballot eligibility validation. Improves sync speed. * [#4934](https://github.com/spacemeshos/go-spacemesh/pull/4934) Ensure state is synced before participating in tortoise consensus. diff --git a/Makefile b/Makefile index 2fbfc923ad..24bdec9714 100644 --- a/Makefile +++ b/Makefile @@ -46,8 +46,8 @@ install: git lfs install go mod download curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s v1.54.2 - go install github.com/spacemeshos/go-scale/scalegen@v1.1.11 - go install go.uber.org/mock/mockgen@v0.2.0 + go install github.com/spacemeshos/go-scale/scalegen@v1.1.12 + go install go.uber.org/mock/mockgen@v0.3.0 go install gotest.tools/gotestsum@v1.10.1 go install honnef.co/go/tools/cmd/staticcheck@v0.4.5 .PHONY: install diff --git a/activation/activation.go b/activation/activation.go index a1fe0611d8..7dc4b55ef8 100644 --- a/activation/activation.go +++ b/activation/activation.go @@ -343,7 +343,14 @@ func (b *Builder) verifyInitialPost(ctx context.Context, post *types.Post, metad if err != nil { b.log.With().Panic("failed to fetch commitment ATX ID.", log.Err(err)) } - err = b.validator.Post(ctx, b.nodeID, commitmentAtxId, post, metadata, b.postSetupProvider.LastOpts().NumUnits) + err = b.validator.Post( + ctx, + b.nodeID, + commitmentAtxId, + post, + metadata, + b.postSetupProvider.LastOpts().NumUnits, + ) switch { case errors.Is(err, context.Canceled): // If the context was canceled, we don't want to emit or log errors just propagate the cancellation signal. diff --git a/activation/activation_test.go b/activation/activation_test.go index 8e5179b8bd..1a9e9ace1d 100644 --- a/activation/activation_test.go +++ b/activation/activation_test.go @@ -261,7 +261,7 @@ func TestBuilder_StartSmeshingCoinbase(t *testing.T) { tab.mpost.EXPECT().LastOpts().Return(&PostSetupOpts{}).AnyTimes() tab.mpost.EXPECT().CommitmentAtx().Return(tab.goldenATXID, nil).AnyTimes() tab.mpost.EXPECT().GenerateProof(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(&types.Post{}, &types.PostMetadata{}, nil) - tab.mValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(nil) + tab.mValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(nil) tab.mclock.EXPECT().AwaitLayer(gomock.Any()).Return(make(chan struct{})).AnyTimes() require.NoError(t, tab.StartSmeshing(coinbase, postSetupOpts)) require.Equal(t, coinbase, tab.Coinbase()) @@ -285,7 +285,7 @@ func TestBuilder_RestartSmeshing(t *testing.T) { Challenge: shared.ZeroChallenge, }, nil) tab.mpost.EXPECT().Reset().AnyTimes() - tab.mValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(nil) + tab.mValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(nil) tab.mpost.EXPECT().Config().AnyTimes() ch := make(chan struct{}) close(ch) @@ -441,7 +441,7 @@ func TestBuilder_StopSmeshing_OnPoSTError(t *testing.T) { tab.mpost.EXPECT().CommitmentAtx().Return(types.EmptyATXID, nil).AnyTimes() tab.mpost.EXPECT().LastOpts().Return(&PostSetupOpts{}).AnyTimes() tab.mpost.EXPECT().GenerateProof(gomock.Any(), gomock.Any(), gomock.Any()).Return(&types.Post{}, &types.PostMetadata{}, nil).AnyTimes() - tab.mValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(nil) + tab.mValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(nil) ch := make(chan struct{}) close(ch) now := time.Now() @@ -1146,7 +1146,7 @@ func TestBuilder_InitialProofGeneratedOnce(t *testing.T) { tab.mpost.EXPECT().GenerateProof(gomock.Any(), shared.ZeroChallenge, gomock.Any()).Return(&types.Post{}, &types.PostMetadata{}, nil) tab.mpost.EXPECT().LastOpts().Return(&PostSetupOpts{}) tab.mpost.EXPECT().CommitmentAtx().Return(tab.goldenATXID, nil) - tab.mValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(nil) + tab.mValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(nil) require.NoError(t, tab.generateInitialPost(context.Background())) posEpoch := postGenesisEpoch + 1 @@ -1173,12 +1173,12 @@ func TestBuilder_InitialProofGeneratedOnce(t *testing.T) { func TestBuilder_InitialPostIsPersisted(t *testing.T) { tab := newTestBuilder(t, WithPoetConfig(PoetConfig{PhaseShift: layerDuration * 4})) tab.mpost.EXPECT().Config().AnyTimes().Return(PostConfig{}) - tab.mpost.EXPECT().LastOpts().Return(&PostSetupOpts{}).Times(3) + tab.mpost.EXPECT().LastOpts().Return(&PostSetupOpts{}).AnyTimes() tab.mpost.EXPECT().CommitmentAtx().Return(tab.goldenATXID, nil).Times(3) tab.mpost.EXPECT().GenerateProof(gomock.Any(), shared.ZeroChallenge, gomock.Any()).Return(&types.Post{}, &types.PostMetadata{ Challenge: shared.ZeroChallenge, }, nil) - tab.mValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(nil) + tab.mValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(nil) require.NoError(t, tab.generateInitialPost(context.Background())) // GenerateProof() should not be called again diff --git a/activation/handler_test.go b/activation/handler_test.go index 8c86a7beae..5f573b16b9 100644 --- a/activation/handler_test.go +++ b/activation/handler_test.go @@ -218,7 +218,7 @@ func TestHandler_SyntacticallyValidateAtx(t *testing.T) { atxHdlr.mclock.EXPECT().CurrentLayer().Return(currentLayer) require.NoError(t, atxHdlr.SyntacticallyValidate(context.Background(), atx)) - atxHdlr.mValidator.EXPECT().NIPost(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(uint64(1), nil) + atxHdlr.mValidator.EXPECT().NIPost(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(uint64(1), nil) atxHdlr.mValidator.EXPECT().NIPostChallenge(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) atxHdlr.mValidator.EXPECT().PositioningAtx(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) _, err := atxHdlr.SyntacticallyValidateDeps(context.Background(), atx) @@ -241,7 +241,7 @@ func TestHandler_SyntacticallyValidateAtx(t *testing.T) { atxHdlr.mclock.EXPECT().CurrentLayer().Return(currentLayer) require.NoError(t, atxHdlr.SyntacticallyValidate(context.Background(), atx)) - atxHdlr.mValidator.EXPECT().NIPost(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(uint64(1), nil) + atxHdlr.mValidator.EXPECT().NIPost(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(uint64(1), nil) atxHdlr.mValidator.EXPECT().NIPostChallenge(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) atxHdlr.mValidator.EXPECT().PositioningAtx(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) atxHdlr.mValidator.EXPECT().VRFNonce(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) @@ -262,7 +262,7 @@ func TestHandler_SyntacticallyValidateAtx(t *testing.T) { atxHdlr.mclock.EXPECT().CurrentLayer().Return(currentLayer) require.NoError(t, atxHdlr.SyntacticallyValidate(context.Background(), atx)) - atxHdlr.mValidator.EXPECT().NIPost(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(uint64(1), nil) + atxHdlr.mValidator.EXPECT().NIPost(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(uint64(1), nil) atxHdlr.mValidator.EXPECT().NIPostChallenge(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) atxHdlr.mValidator.EXPECT().PositioningAtx(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) vAtx, err := atxHdlr.SyntacticallyValidateDeps(context.Background(), atx) @@ -284,7 +284,7 @@ func TestHandler_SyntacticallyValidateAtx(t *testing.T) { atxHdlr.mclock.EXPECT().CurrentLayer().Return(currentLayer) require.NoError(t, atxHdlr.SyntacticallyValidate(context.Background(), atx)) - atxHdlr.mValidator.EXPECT().NIPost(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(uint64(1), nil) + atxHdlr.mValidator.EXPECT().NIPost(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(uint64(1), nil) atxHdlr.mValidator.EXPECT().NIPostChallenge(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) atxHdlr.mValidator.EXPECT().PositioningAtx(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) atxHdlr.mValidator.EXPECT().VRFNonce(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) @@ -334,11 +334,11 @@ func TestHandler_SyntacticallyValidateAtx(t *testing.T) { require.NoError(t, SignAndFinalizeAtx(sig, atx)) atxHdlr.mclock.EXPECT().CurrentLayer().Return(currentLayer) - atxHdlr.mValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) + atxHdlr.mValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) atxHdlr.mValidator.EXPECT().VRFNonce(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) require.NoError(t, atxHdlr.SyntacticallyValidate(context.Background(), atx)) atxHdlr.mValidator.EXPECT().InitialNIPostChallenge(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) - atxHdlr.mValidator.EXPECT().NIPost(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(uint64(1), nil) + atxHdlr.mValidator.EXPECT().NIPost(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(uint64(1), nil) atxHdlr.mValidator.EXPECT().PositioningAtx(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) _, err := atxHdlr.SyntacticallyValidateDeps(context.Background(), atx) require.NoError(t, err) @@ -516,7 +516,7 @@ func TestHandler_SyntacticallyValidateAtx(t *testing.T) { atxHdlr.mclock.EXPECT().CurrentLayer().Return(currentLayer) atxHdlr.mValidator.EXPECT().VRFNonce(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()) - atxHdlr.mValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(errors.New("failed post validation")) + atxHdlr.mValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(errors.New("failed post validation")) err := atxHdlr.SyntacticallyValidate(context.Background(), atx) require.ErrorContains(t, err, "failed post validation") }) @@ -1245,8 +1245,8 @@ func TestHandler_AtxWeight(t *testing.T) { atxHdlr.mockFetch.EXPECT().RegisterPeerHashes(peer, []types.Hash32{proofRef}) atxHdlr.mockFetch.EXPECT().GetPoetProof(gomock.Any(), proofRef) atxHdlr.mValidator.EXPECT().VRFNonce(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()) - atxHdlr.mValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()) - atxHdlr.mValidator.EXPECT().NIPost(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(leaves, nil) + atxHdlr.mValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()) + atxHdlr.mValidator.EXPECT().NIPost(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(leaves, nil) atxHdlr.mValidator.EXPECT().InitialNIPostChallenge(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) atxHdlr.mValidator.EXPECT().PositioningAtx(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) atxHdlr.mbeacon.EXPECT().OnAtx(gomock.Any()) @@ -1289,7 +1289,7 @@ func TestHandler_AtxWeight(t *testing.T) { }) atxHdlr.mockFetch.EXPECT().GetPoetProof(gomock.Any(), proofRef) atxHdlr.mockFetch.EXPECT().GetAtxs(gomock.Any(), gomock.Any()) - atxHdlr.mValidator.EXPECT().NIPost(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(leaves, nil) + atxHdlr.mValidator.EXPECT().NIPost(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(leaves, nil) atxHdlr.mValidator.EXPECT().NIPostChallenge(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) atxHdlr.mValidator.EXPECT().PositioningAtx(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) atxHdlr.mbeacon.EXPECT().OnAtx(gomock.Any()) @@ -1343,8 +1343,8 @@ func TestHandler_WrongHash(t *testing.T) { atxHdlr.mockFetch.EXPECT().RegisterPeerHashes(peer, []types.Hash32{proofRef}) atxHdlr.mockFetch.EXPECT().GetPoetProof(gomock.Any(), proofRef) atxHdlr.mValidator.EXPECT().VRFNonce(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()) - atxHdlr.mValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()) - atxHdlr.mValidator.EXPECT().NIPost(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(uint64(111), nil) + atxHdlr.mValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()) + atxHdlr.mValidator.EXPECT().NIPost(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(uint64(111), nil) atxHdlr.mValidator.EXPECT().InitialNIPostChallenge(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) atxHdlr.mValidator.EXPECT().PositioningAtx(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) err = atxHdlr.HandleSyncedAtx(context.Background(), types.RandomHash(), peer, buf) diff --git a/activation/interface.go b/activation/interface.go index 3295c14c4d..d413546f21 100644 --- a/activation/interface.go +++ b/activation/interface.go @@ -25,10 +25,10 @@ type PostVerifier interface { type nipostValidator interface { InitialNIPostChallenge(challenge *types.NIPostChallenge, atxs atxProvider, goldenATXID types.ATXID) error NIPostChallenge(challenge *types.NIPostChallenge, atxs atxProvider, nodeID types.NodeID) error - NIPost(ctx context.Context, nodeId types.NodeID, atxId types.ATXID, NIPost *types.NIPost, expectedChallenge types.Hash32, numUnits uint32, opts ...verifying.OptionFunc) (uint64, error) + NIPost(ctx context.Context, nodeId types.NodeID, atxId types.ATXID, NIPost *types.NIPost, expectedChallenge types.Hash32, numUnits uint32) (uint64, error) NumUnits(cfg *PostConfig, numUnits uint32) error - Post(ctx context.Context, nodeId types.NodeID, atxId types.ATXID, Post *types.Post, PostMetadata *types.PostMetadata, numUnits uint32, opts ...verifying.OptionFunc) error + Post(ctx context.Context, nodeId types.NodeID, atxId types.ATXID, Post *types.Post, PostMetadata *types.PostMetadata, numUnits uint32) error PostMetadata(cfg *PostConfig, metadata *types.PostMetadata) error VRFNonce(nodeId types.NodeID, commitmentAtxId types.ATXID, vrfNonce *types.VRFPostIndex, PostMetadata *types.PostMetadata, numUnits uint32) error diff --git a/activation/mocks.go b/activation/mocks.go index 14176cbc12..b4e7ac44e9 100644 --- a/activation/mocks.go +++ b/activation/mocks.go @@ -1,6 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: ./interface.go - +// +// Generated by this command: +// +// mockgen -typed -package=activation -destination=./mocks.go -source=./interface.go +// // Package activation is a generated GoMock package. package activation @@ -46,7 +50,7 @@ func (m *MockAtxReceiver) OnAtx(arg0 *types.ActivationTxHeader) { } // OnAtx indicates an expected call of OnAtx. -func (mr *MockAtxReceiverMockRecorder) OnAtx(arg0 interface{}) *AtxReceiverOnAtxCall { +func (mr *MockAtxReceiverMockRecorder) OnAtx(arg0 any) *AtxReceiverOnAtxCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OnAtx", reflect.TypeOf((*MockAtxReceiver)(nil).OnAtx), arg0) return &AtxReceiverOnAtxCall{Call: call} @@ -139,7 +143,7 @@ func (c *PostVerifierCloseCall) DoAndReturn(f func() error) *PostVerifierCloseCa // Verify mocks base method. func (m_2 *MockPostVerifier) Verify(ctx context.Context, p *shared.Proof, m *shared.ProofMetadata, opts ...verifying.OptionFunc) error { m_2.ctrl.T.Helper() - varargs := []interface{}{ctx, p, m} + varargs := []any{ctx, p, m} for _, a := range opts { varargs = append(varargs, a) } @@ -149,9 +153,9 @@ func (m_2 *MockPostVerifier) Verify(ctx context.Context, p *shared.Proof, m *sha } // Verify indicates an expected call of Verify. -func (mr *MockPostVerifierMockRecorder) Verify(ctx, p, m interface{}, opts ...interface{}) *PostVerifierVerifyCall { +func (mr *MockPostVerifierMockRecorder) Verify(ctx, p, m any, opts ...any) *PostVerifierVerifyCall { mr.mock.ctrl.T.Helper() - varargs := append([]interface{}{ctx, p, m}, opts...) + varargs := append([]any{ctx, p, m}, opts...) call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Verify", reflect.TypeOf((*MockPostVerifier)(nil).Verify), varargs...) return &PostVerifierVerifyCall{Call: call} } @@ -211,7 +215,7 @@ func (m *MocknipostValidator) InitialNIPostChallenge(challenge *types.NIPostChal } // InitialNIPostChallenge indicates an expected call of InitialNIPostChallenge. -func (mr *MocknipostValidatorMockRecorder) InitialNIPostChallenge(challenge, atxs, goldenATXID interface{}) *nipostValidatorInitialNIPostChallengeCall { +func (mr *MocknipostValidatorMockRecorder) InitialNIPostChallenge(challenge, atxs, goldenATXID any) *nipostValidatorInitialNIPostChallengeCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InitialNIPostChallenge", reflect.TypeOf((*MocknipostValidator)(nil).InitialNIPostChallenge), challenge, atxs, goldenATXID) return &nipostValidatorInitialNIPostChallengeCall{Call: call} @@ -241,23 +245,18 @@ func (c *nipostValidatorInitialNIPostChallengeCall) DoAndReturn(f func(*types.NI } // NIPost mocks base method. -func (m *MocknipostValidator) NIPost(ctx context.Context, nodeId types.NodeID, atxId types.ATXID, NIPost *types.NIPost, expectedChallenge types.Hash32, numUnits uint32, opts ...verifying.OptionFunc) (uint64, error) { +func (m *MocknipostValidator) NIPost(ctx context.Context, nodeId types.NodeID, atxId types.ATXID, NIPost *types.NIPost, expectedChallenge types.Hash32, numUnits uint32) (uint64, error) { m.ctrl.T.Helper() - varargs := []interface{}{ctx, nodeId, atxId, NIPost, expectedChallenge, numUnits} - for _, a := range opts { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "NIPost", varargs...) + ret := m.ctrl.Call(m, "NIPost", ctx, nodeId, atxId, NIPost, expectedChallenge, numUnits) ret0, _ := ret[0].(uint64) ret1, _ := ret[1].(error) return ret0, ret1 } // NIPost indicates an expected call of NIPost. -func (mr *MocknipostValidatorMockRecorder) NIPost(ctx, nodeId, atxId, NIPost, expectedChallenge, numUnits interface{}, opts ...interface{}) *nipostValidatorNIPostCall { +func (mr *MocknipostValidatorMockRecorder) NIPost(ctx, nodeId, atxId, NIPost, expectedChallenge, numUnits any) *nipostValidatorNIPostCall { mr.mock.ctrl.T.Helper() - varargs := append([]interface{}{ctx, nodeId, atxId, NIPost, expectedChallenge, numUnits}, opts...) - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NIPost", reflect.TypeOf((*MocknipostValidator)(nil).NIPost), varargs...) + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NIPost", reflect.TypeOf((*MocknipostValidator)(nil).NIPost), ctx, nodeId, atxId, NIPost, expectedChallenge, numUnits) return &nipostValidatorNIPostCall{Call: call} } @@ -273,13 +272,13 @@ func (c *nipostValidatorNIPostCall) Return(arg0 uint64, arg1 error) *nipostValid } // Do rewrite *gomock.Call.Do -func (c *nipostValidatorNIPostCall) Do(f func(context.Context, types.NodeID, types.ATXID, *types.NIPost, types.Hash32, uint32, ...verifying.OptionFunc) (uint64, error)) *nipostValidatorNIPostCall { +func (c *nipostValidatorNIPostCall) Do(f func(context.Context, types.NodeID, types.ATXID, *types.NIPost, types.Hash32, uint32) (uint64, error)) *nipostValidatorNIPostCall { c.Call = c.Call.Do(f) return c } // DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *nipostValidatorNIPostCall) DoAndReturn(f func(context.Context, types.NodeID, types.ATXID, *types.NIPost, types.Hash32, uint32, ...verifying.OptionFunc) (uint64, error)) *nipostValidatorNIPostCall { +func (c *nipostValidatorNIPostCall) DoAndReturn(f func(context.Context, types.NodeID, types.ATXID, *types.NIPost, types.Hash32, uint32) (uint64, error)) *nipostValidatorNIPostCall { c.Call = c.Call.DoAndReturn(f) return c } @@ -293,7 +292,7 @@ func (m *MocknipostValidator) NIPostChallenge(challenge *types.NIPostChallenge, } // NIPostChallenge indicates an expected call of NIPostChallenge. -func (mr *MocknipostValidatorMockRecorder) NIPostChallenge(challenge, atxs, nodeID interface{}) *nipostValidatorNIPostChallengeCall { +func (mr *MocknipostValidatorMockRecorder) NIPostChallenge(challenge, atxs, nodeID any) *nipostValidatorNIPostChallengeCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NIPostChallenge", reflect.TypeOf((*MocknipostValidator)(nil).NIPostChallenge), challenge, atxs, nodeID) return &nipostValidatorNIPostChallengeCall{Call: call} @@ -331,7 +330,7 @@ func (m *MocknipostValidator) NumUnits(cfg *PostConfig, numUnits uint32) error { } // NumUnits indicates an expected call of NumUnits. -func (mr *MocknipostValidatorMockRecorder) NumUnits(cfg, numUnits interface{}) *nipostValidatorNumUnitsCall { +func (mr *MocknipostValidatorMockRecorder) NumUnits(cfg, numUnits any) *nipostValidatorNumUnitsCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NumUnits", reflect.TypeOf((*MocknipostValidator)(nil).NumUnits), cfg, numUnits) return &nipostValidatorNumUnitsCall{Call: call} @@ -369,7 +368,7 @@ func (m *MocknipostValidator) PositioningAtx(id types.ATXID, atxs atxProvider, g } // PositioningAtx indicates an expected call of PositioningAtx. -func (mr *MocknipostValidatorMockRecorder) PositioningAtx(id, atxs, goldenATXID, pubepoch interface{}) *nipostValidatorPositioningAtxCall { +func (mr *MocknipostValidatorMockRecorder) PositioningAtx(id, atxs, goldenATXID, pubepoch any) *nipostValidatorPositioningAtxCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PositioningAtx", reflect.TypeOf((*MocknipostValidator)(nil).PositioningAtx), id, atxs, goldenATXID, pubepoch) return &nipostValidatorPositioningAtxCall{Call: call} @@ -399,22 +398,17 @@ func (c *nipostValidatorPositioningAtxCall) DoAndReturn(f func(types.ATXID, atxP } // Post mocks base method. -func (m *MocknipostValidator) Post(ctx context.Context, nodeId types.NodeID, atxId types.ATXID, Post *types.Post, PostMetadata *types.PostMetadata, numUnits uint32, opts ...verifying.OptionFunc) error { +func (m *MocknipostValidator) Post(ctx context.Context, nodeId types.NodeID, atxId types.ATXID, Post *types.Post, PostMetadata *types.PostMetadata, numUnits uint32) error { m.ctrl.T.Helper() - varargs := []interface{}{ctx, nodeId, atxId, Post, PostMetadata, numUnits} - for _, a := range opts { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "Post", varargs...) + ret := m.ctrl.Call(m, "Post", ctx, nodeId, atxId, Post, PostMetadata, numUnits) ret0, _ := ret[0].(error) return ret0 } // Post indicates an expected call of Post. -func (mr *MocknipostValidatorMockRecorder) Post(ctx, nodeId, atxId, Post, PostMetadata, numUnits interface{}, opts ...interface{}) *nipostValidatorPostCall { +func (mr *MocknipostValidatorMockRecorder) Post(ctx, nodeId, atxId, Post, PostMetadata, numUnits any) *nipostValidatorPostCall { mr.mock.ctrl.T.Helper() - varargs := append([]interface{}{ctx, nodeId, atxId, Post, PostMetadata, numUnits}, opts...) - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Post", reflect.TypeOf((*MocknipostValidator)(nil).Post), varargs...) + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Post", reflect.TypeOf((*MocknipostValidator)(nil).Post), ctx, nodeId, atxId, Post, PostMetadata, numUnits) return &nipostValidatorPostCall{Call: call} } @@ -430,13 +424,13 @@ func (c *nipostValidatorPostCall) Return(arg0 error) *nipostValidatorPostCall { } // Do rewrite *gomock.Call.Do -func (c *nipostValidatorPostCall) Do(f func(context.Context, types.NodeID, types.ATXID, *types.Post, *types.PostMetadata, uint32, ...verifying.OptionFunc) error) *nipostValidatorPostCall { +func (c *nipostValidatorPostCall) Do(f func(context.Context, types.NodeID, types.ATXID, *types.Post, *types.PostMetadata, uint32) error) *nipostValidatorPostCall { c.Call = c.Call.Do(f) return c } // DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *nipostValidatorPostCall) DoAndReturn(f func(context.Context, types.NodeID, types.ATXID, *types.Post, *types.PostMetadata, uint32, ...verifying.OptionFunc) error) *nipostValidatorPostCall { +func (c *nipostValidatorPostCall) DoAndReturn(f func(context.Context, types.NodeID, types.ATXID, *types.Post, *types.PostMetadata, uint32) error) *nipostValidatorPostCall { c.Call = c.Call.DoAndReturn(f) return c } @@ -450,7 +444,7 @@ func (m *MocknipostValidator) PostMetadata(cfg *PostConfig, metadata *types.Post } // PostMetadata indicates an expected call of PostMetadata. -func (mr *MocknipostValidatorMockRecorder) PostMetadata(cfg, metadata interface{}) *nipostValidatorPostMetadataCall { +func (mr *MocknipostValidatorMockRecorder) PostMetadata(cfg, metadata any) *nipostValidatorPostMetadataCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PostMetadata", reflect.TypeOf((*MocknipostValidator)(nil).PostMetadata), cfg, metadata) return &nipostValidatorPostMetadataCall{Call: call} @@ -488,7 +482,7 @@ func (m *MocknipostValidator) VRFNonce(nodeId types.NodeID, commitmentAtxId type } // VRFNonce indicates an expected call of VRFNonce. -func (mr *MocknipostValidatorMockRecorder) VRFNonce(nodeId, commitmentAtxId, vrfNonce, PostMetadata, numUnits interface{}) *nipostValidatorVRFNonceCall { +func (mr *MocknipostValidatorMockRecorder) VRFNonce(nodeId, commitmentAtxId, vrfNonce, PostMetadata, numUnits any) *nipostValidatorVRFNonceCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "VRFNonce", reflect.TypeOf((*MocknipostValidator)(nil).VRFNonce), nodeId, commitmentAtxId, vrfNonce, PostMetadata, numUnits) return &nipostValidatorVRFNonceCall{Call: call} @@ -549,7 +543,7 @@ func (m *MocklayerClock) AwaitLayer(layerID types.LayerID) <-chan struct{} { } // AwaitLayer indicates an expected call of AwaitLayer. -func (mr *MocklayerClockMockRecorder) AwaitLayer(layerID interface{}) *layerClockAwaitLayerCall { +func (mr *MocklayerClockMockRecorder) AwaitLayer(layerID any) *layerClockAwaitLayerCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AwaitLayer", reflect.TypeOf((*MocklayerClock)(nil).AwaitLayer), layerID) return &layerClockAwaitLayerCall{Call: call} @@ -625,7 +619,7 @@ func (m *MocklayerClock) LayerToTime(arg0 types.LayerID) time.Time { } // LayerToTime indicates an expected call of LayerToTime. -func (mr *MocklayerClockMockRecorder) LayerToTime(arg0 interface{}) *layerClockLayerToTimeCall { +func (mr *MocklayerClockMockRecorder) LayerToTime(arg0 any) *layerClockLayerToTimeCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LayerToTime", reflect.TypeOf((*MocklayerClock)(nil).LayerToTime), arg0) return &layerClockLayerToTimeCall{Call: call} @@ -687,7 +681,7 @@ func (m *MocknipostBuilder) BuildNIPost(ctx context.Context, challenge *types.NI } // BuildNIPost indicates an expected call of BuildNIPost. -func (mr *MocknipostBuilderMockRecorder) BuildNIPost(ctx, challenge interface{}) *nipostBuilderBuildNIPostCall { +func (mr *MocknipostBuilderMockRecorder) BuildNIPost(ctx, challenge any) *nipostBuilderBuildNIPostCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BuildNIPost", reflect.TypeOf((*MocknipostBuilder)(nil).BuildNIPost), ctx, challenge) return &nipostBuilderBuildNIPostCall{Call: call} @@ -761,7 +755,7 @@ func (m *MocknipostBuilder) UpdatePoETProvers(arg0 []PoetProvingServiceClient) { } // UpdatePoETProvers indicates an expected call of UpdatePoETProvers. -func (mr *MocknipostBuilderMockRecorder) UpdatePoETProvers(arg0 interface{}) *nipostBuilderUpdatePoETProversCall { +func (mr *MocknipostBuilderMockRecorder) UpdatePoETProvers(arg0 any) *nipostBuilderUpdatePoETProversCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdatePoETProvers", reflect.TypeOf((*MocknipostBuilder)(nil).UpdatePoETProvers), arg0) return &nipostBuilderUpdatePoETProversCall{Call: call} @@ -822,7 +816,7 @@ func (m *MockatxHandler) AwaitAtx(id types.ATXID) chan struct{} { } // AwaitAtx indicates an expected call of AwaitAtx. -func (mr *MockatxHandlerMockRecorder) AwaitAtx(id interface{}) *atxHandlerAwaitAtxCall { +func (mr *MockatxHandlerMockRecorder) AwaitAtx(id any) *atxHandlerAwaitAtxCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AwaitAtx", reflect.TypeOf((*MockatxHandler)(nil).AwaitAtx), id) return &atxHandlerAwaitAtxCall{Call: call} @@ -858,7 +852,7 @@ func (m *MockatxHandler) UnsubscribeAtx(id types.ATXID) { } // UnsubscribeAtx indicates an expected call of UnsubscribeAtx. -func (mr *MockatxHandlerMockRecorder) UnsubscribeAtx(id interface{}) *atxHandlerUnsubscribeAtxCall { +func (mr *MockatxHandlerMockRecorder) UnsubscribeAtx(id any) *atxHandlerUnsubscribeAtxCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UnsubscribeAtx", reflect.TypeOf((*MockatxHandler)(nil).UnsubscribeAtx), id) return &atxHandlerUnsubscribeAtxCall{Call: call} @@ -981,7 +975,7 @@ func (m *MockatxProvider) GetAtxHeader(id types.ATXID) (*types.ActivationTxHeade } // GetAtxHeader indicates an expected call of GetAtxHeader. -func (mr *MockatxProviderMockRecorder) GetAtxHeader(id interface{}) *atxProviderGetAtxHeaderCall { +func (mr *MockatxProviderMockRecorder) GetAtxHeader(id any) *atxProviderGetAtxHeaderCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAtxHeader", reflect.TypeOf((*MockatxProvider)(nil).GetAtxHeader), id) return &atxProviderGetAtxHeaderCall{Call: call} @@ -1043,7 +1037,7 @@ func (m *MockpostSetupProvider) Benchmark(p PostSetupProvider) (int, error) { } // Benchmark indicates an expected call of Benchmark. -func (mr *MockpostSetupProviderMockRecorder) Benchmark(p interface{}) *postSetupProviderBenchmarkCall { +func (mr *MockpostSetupProviderMockRecorder) Benchmark(p any) *postSetupProviderBenchmarkCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Benchmark", reflect.TypeOf((*MockpostSetupProvider)(nil).Benchmark), p) return &postSetupProviderBenchmarkCall{Call: call} @@ -1152,7 +1146,7 @@ func (c *postSetupProviderConfigCall) DoAndReturn(f func() PostConfig) *postSetu // GenerateProof mocks base method. func (m *MockpostSetupProvider) GenerateProof(ctx context.Context, challenge []byte, options ...proving.OptionFunc) (*types.Post, *types.PostMetadata, error) { m.ctrl.T.Helper() - varargs := []interface{}{ctx, challenge} + varargs := []any{ctx, challenge} for _, a := range options { varargs = append(varargs, a) } @@ -1164,9 +1158,9 @@ func (m *MockpostSetupProvider) GenerateProof(ctx context.Context, challenge []b } // GenerateProof indicates an expected call of GenerateProof. -func (mr *MockpostSetupProviderMockRecorder) GenerateProof(ctx, challenge interface{}, options ...interface{}) *postSetupProviderGenerateProofCall { +func (mr *MockpostSetupProviderMockRecorder) GenerateProof(ctx, challenge any, options ...any) *postSetupProviderGenerateProofCall { mr.mock.ctrl.T.Helper() - varargs := append([]interface{}{ctx, challenge}, options...) + varargs := append([]any{ctx, challenge}, options...) call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GenerateProof", reflect.TypeOf((*MockpostSetupProvider)(nil).GenerateProof), varargs...) return &postSetupProviderGenerateProofCall{Call: call} } @@ -1241,7 +1235,7 @@ func (m *MockpostSetupProvider) PrepareInitializer(ctx context.Context, opts Pos } // PrepareInitializer indicates an expected call of PrepareInitializer. -func (mr *MockpostSetupProviderMockRecorder) PrepareInitializer(ctx, opts interface{}) *postSetupProviderPrepareInitializerCall { +func (mr *MockpostSetupProviderMockRecorder) PrepareInitializer(ctx, opts any) *postSetupProviderPrepareInitializerCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PrepareInitializer", reflect.TypeOf((*MockpostSetupProvider)(nil).PrepareInitializer), ctx, opts) return &postSetupProviderPrepareInitializerCall{Call: call} @@ -1356,7 +1350,7 @@ func (m *MockpostSetupProvider) StartSession(context context.Context) error { } // StartSession indicates an expected call of StartSession. -func (mr *MockpostSetupProviderMockRecorder) StartSession(context interface{}) *postSetupProviderStartSessionCall { +func (mr *MockpostSetupProviderMockRecorder) StartSession(context any) *postSetupProviderStartSessionCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StartSession", reflect.TypeOf((*MockpostSetupProvider)(nil).StartSession), context) return &postSetupProviderStartSessionCall{Call: call} @@ -1530,7 +1524,7 @@ func (m *MockSmeshingProvider) SetCoinbase(coinbase types.Address) { } // SetCoinbase indicates an expected call of SetCoinbase. -func (mr *MockSmeshingProviderMockRecorder) SetCoinbase(coinbase interface{}) *SmeshingProviderSetCoinbaseCall { +func (mr *MockSmeshingProviderMockRecorder) SetCoinbase(coinbase any) *SmeshingProviderSetCoinbaseCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetCoinbase", reflect.TypeOf((*MockSmeshingProvider)(nil).SetCoinbase), coinbase) return &SmeshingProviderSetCoinbaseCall{Call: call} @@ -1644,7 +1638,7 @@ func (m *MockSmeshingProvider) StartSmeshing(arg0 types.Address, arg1 PostSetupO } // StartSmeshing indicates an expected call of StartSmeshing. -func (mr *MockSmeshingProviderMockRecorder) StartSmeshing(arg0, arg1 interface{}) *SmeshingProviderStartSmeshingCall { +func (mr *MockSmeshingProviderMockRecorder) StartSmeshing(arg0, arg1 any) *SmeshingProviderStartSmeshingCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StartSmeshing", reflect.TypeOf((*MockSmeshingProvider)(nil).StartSmeshing), arg0, arg1) return &SmeshingProviderStartSmeshingCall{Call: call} @@ -1682,7 +1676,7 @@ func (m *MockSmeshingProvider) StopSmeshing(arg0 bool) error { } // StopSmeshing indicates an expected call of StopSmeshing. -func (mr *MockSmeshingProviderMockRecorder) StopSmeshing(arg0 interface{}) *SmeshingProviderStopSmeshingCall { +func (mr *MockSmeshingProviderMockRecorder) StopSmeshing(arg0 any) *SmeshingProviderStopSmeshingCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StopSmeshing", reflect.TypeOf((*MockSmeshingProvider)(nil).StopSmeshing), arg0) return &SmeshingProviderStopSmeshingCall{Call: call} @@ -1720,7 +1714,7 @@ func (m *MockSmeshingProvider) UpdatePoETServers(ctx context.Context, endpoints } // UpdatePoETServers indicates an expected call of UpdatePoETServers. -func (mr *MockSmeshingProviderMockRecorder) UpdatePoETServers(ctx, endpoints interface{}) *SmeshingProviderUpdatePoETServersCall { +func (mr *MockSmeshingProviderMockRecorder) UpdatePoETServers(ctx, endpoints any) *SmeshingProviderUpdatePoETServersCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdatePoETServers", reflect.TypeOf((*MockSmeshingProvider)(nil).UpdatePoETServers), ctx, endpoints) return &SmeshingProviderUpdatePoETServersCall{Call: call} diff --git a/activation/nipost.go b/activation/nipost.go index cf1a125286..227ccd45db 100644 --- a/activation/nipost.go +++ b/activation/nipost.go @@ -12,7 +12,6 @@ import ( "github.com/spacemeshos/merkle-tree" "github.com/spacemeshos/poet/shared" "github.com/spacemeshos/post/proving" - "github.com/spacemeshos/post/verifying" "golang.org/x/exp/slices" "golang.org/x/sync/errgroup" @@ -301,7 +300,6 @@ func (nb *NIPostBuilder) BuildNIPost(ctx context.Context, challenge *types.NIPos proof, proofMetadata, nb.postSetupProvider.LastOpts().NumUnits, - verifying.WithLabelScryptParams(nb.postSetupProvider.LastOpts().Scrypt), ); err != nil { events.EmitInvalidPostProof() return nil, fmt.Errorf("failed to verify Post: %w", err) @@ -321,6 +319,14 @@ func (nb *NIPostBuilder) BuildNIPost(ctx context.Context, challenge *types.NIPos return nb.state.NIPost, nil } +// withConditionalTimeout returns a context.WithTimeout if the timeout is greater than 0, otherwise it returns the original context. +func withConditionalTimeout(ctx context.Context, timeout time.Duration) (context.Context, context.CancelFunc) { + if timeout > 0 { + return context.WithTimeout(ctx, timeout) + } + return ctx, func() {} +} + // Submit the challenge to a single PoET. func (nb *NIPostBuilder) submitPoetChallenge(ctx context.Context, client PoetProvingServiceClient, prefix, challenge []byte, signature types.EdSignature, nodeID types.NodeID) (*types.PoetRequest, error) { poetServiceID, err := client.PoetServiceID(ctx) @@ -330,7 +336,7 @@ func (nb *NIPostBuilder) submitPoetChallenge(ctx context.Context, client PoetPro logger := nb.log.WithContext(ctx).WithFields(log.String("poet_id", hex.EncodeToString(poetServiceID.ServiceID))) logger.Debug("querying for poet pow parameters") - powCtx, cancel := context.WithTimeout(ctx, nb.poetCfg.RequestTimeout) + powCtx, cancel := withConditionalTimeout(ctx, nb.poetCfg.RequestTimeout) defer cancel() powParams, err := client.PowParams(powCtx) if err != nil { @@ -347,7 +353,7 @@ func (nb *NIPostBuilder) submitPoetChallenge(ctx context.Context, client PoetPro logger.Debug("submitting challenge to poet proving service") - submitCtx, cancel := context.WithTimeout(ctx, nb.poetCfg.RequestTimeout) + submitCtx, cancel := withConditionalTimeout(ctx, nb.poetCfg.RequestTimeout) defer cancel() round, err := client.Submit(submitCtx, prefix, challenge, signature, nodeID, PoetPoW{ Nonce: nonce, @@ -409,57 +415,77 @@ func membersContainChallenge(members []types.Member, challenge types.Hash32) (ui return 0, fmt.Errorf("challenge is not a member of the proof") } -// TODO(mafa): remove after epoch 4 ends; https://github.com/spacemeshos/go-spacemesh/issues/4968 -func (nb *NIPostBuilder) addPoet111ForPubEpoch4(ctx context.Context) error { - // because PoET 111 had a hardware issue when challenges for round 3 were submitted, no node could submit to it - // 111 was recovered with the PoET 110 DB, so all successful submissions to 110 should be able to be fetched from there as well +func (nb *NIPostBuilder) addPoETMitigation(ctx context.Context, from, to string, pubEpoch types.EpochID) error { + clientTo, ok := nb.poetProvers[to] + if !ok { + // Target PoET is not in the list, no action necessary + return nil + } - client111, ok := nb.poetProvers["https://poet-111.spacemesh.network"] + clientFrom, ok := nb.poetProvers[from] if !ok { - // poet 111 is not in the list, no action necessary + // Source PoET is not in the list, cannot apply mitigation return nil } - nb.log.Info("pub epoch 4 mitigation: PoET 111 is in the list of PoETs, adding it to the state as well") - client110 := nb.poetProvers["https://poet-110.spacemesh.network"] + nb.log.With().Info("poet mitigation: target and source are in the list of PoETs, applying mitigation", + log.String("state_from", from), + log.String("target_poet", to), + log.Uint32("pub_epoch", pubEpoch.Uint32()), + ) - ID110, err := client110.PoetServiceID(ctx) + idFrom, err := clientFrom.PoetServiceID(ctx) if err != nil { - return fmt.Errorf("failed to get PoET 110 id: %w", err) + return fmt.Errorf("failed to get id for PoET %s: %w", from, err) } - ID111, err := client111.PoetServiceID(ctx) + idTo, err := clientTo.PoetServiceID(ctx) if err != nil { - return fmt.Errorf("failed to get PoET 111 id: %w", err) + return fmt.Errorf("failed to get id for PoET %s: %w", to, err) } - if slices.IndexFunc(nb.state.PoetRequests, func(r types.PoetRequest) bool { return bytes.Equal(r.PoetServiceID.ServiceID, ID111.ServiceID) }) != -1 { + if slices.IndexFunc(nb.state.PoetRequests, func(r types.PoetRequest) bool { return bytes.Equal(r.PoetServiceID.ServiceID, idTo.ServiceID) }) != -1 { nb.log.Info("PoET 111 is already in the state, no action necessary") return nil } - poet110 := slices.IndexFunc(nb.state.PoetRequests, func(r types.PoetRequest) bool { - return bytes.Equal(r.PoetServiceID.ServiceID, ID110.ServiceID) + poetFromIdx := slices.IndexFunc(nb.state.PoetRequests, func(r types.PoetRequest) bool { + return bytes.Equal(r.PoetServiceID.ServiceID, idFrom.ServiceID) }) - if poet110 == -1 { + if poetFromIdx == -1 { return fmt.Errorf("poet 110 is not in the state, cannot add poet 111") } - poet111 := nb.state.PoetRequests[poet110] - poet111.PoetServiceID.ServiceID = ID111.ServiceID - nb.state.PoetRequests = append(nb.state.PoetRequests, poet111) + poetToReq := nb.state.PoetRequests[poetFromIdx] + poetToReq.PoetServiceID.ServiceID = idTo.ServiceID + nb.state.PoetRequests = append(nb.state.PoetRequests, poetToReq) nb.persistState() - nb.log.Info("pub epoch 4 mitigation: PoET 111 added to the state") + nb.log.With().Info("poet mitigation: target PoET added to the state", + log.String("target_poet", to), + log.Uint32("pub_epoch", pubEpoch.Uint32()), + ) return nil } func (nb *NIPostBuilder) getBestProof(ctx context.Context, challenge types.Hash32, publishEpoch types.EpochID) (types.PoetProofRef, *types.MerkleProof, error) { - // TODO(mafa): remove after next PoET round; https://github.com/spacemeshos/go-spacemesh/issues/4968 - if publishEpoch == 4 { - err := nb.addPoet111ForPubEpoch4(ctx) + switch publishEpoch { + case 4: + // because PoET 111 had a hardware issue when challenges for round 3 were submitted, no node could submit to it + // 111 was recovered with the PoET 110 DB, so all successful submissions to 110 should be able to be fetched from there as well + // TODO(mafa): remove after next PoET round; https://github.com/spacemeshos/go-spacemesh/issues/4968 + err := nb.addPoETMitigation(ctx, "https://poet-110.spacemesh.network", "https://poet-111.spacemesh.network", 4) if err != nil { nb.log.With().Error("pub epoch 4 mitigation: failed to add PoET 111 to state for pub epoch 4", log.Err(err)) } + case 5: + // PoET 112 came online after the registration window for round 4 ended, so no node could submit to it + // 112 was initialized with the PoET 110 DB, so all successful submissions to 110 should be able to be fetched from there as well + // TODO(mafa): remove after next PoET round; https://github.com/spacemeshos/go-spacemesh/issues/5030 + err := nb.addPoETMitigation(ctx, "https://poet-110.spacemesh.network", "https://poet-112.spacemesh.network", 5) + if err != nil { + nb.log.With().Error("pub epoch 5 mitigation: failed to add PoET 112 to state for pub epoch 5", log.Err(err)) + } + default: } type poetProof struct { @@ -479,14 +505,14 @@ func (nb *NIPostBuilder) getBestProof(ctx context.Context, challenge types.Hash3 round := r.PoetRound.ID waitDeadline := proofDeadline(r.PoetRound.End.IntoTime(), nb.poetCfg.CycleGap) eg.Go(func() error { - logger.With().Info("waiting till poet round end", log.Duration("wait time", time.Until(waitDeadline))) + logger.With().Info("waiting until poet round end", log.Duration("wait time", time.Until(waitDeadline))) select { case <-ctx.Done(): return fmt.Errorf("waiting to query proof: %w", ctx.Err()) case <-time.After(time.Until(waitDeadline)): } - getProofsCtx, cancel := context.WithTimeout(ctx, nb.poetCfg.RequestTimeout) + getProofsCtx, cancel := withConditionalTimeout(ctx, nb.poetCfg.RequestTimeout) defer cancel() proof, members, err := client.Proof(getProofsCtx, round) if err != nil { diff --git a/activation/nipost_mocks.go b/activation/nipost_mocks.go index cdfce1f420..5d832724eb 100644 --- a/activation/nipost_mocks.go +++ b/activation/nipost_mocks.go @@ -1,6 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: ./nipost.go - +// +// Generated by this command: +// +// mockgen -typed -package=activation -destination=./nipost_mocks.go -source=./nipost.go PoetProvingServiceClient +// // Package activation is a generated GoMock package. package activation @@ -83,7 +87,7 @@ func (m *MockPoetProvingServiceClient) PoetServiceID(arg0 context.Context) (type } // PoetServiceID indicates an expected call of PoetServiceID. -func (mr *MockPoetProvingServiceClientMockRecorder) PoetServiceID(arg0 interface{}) *PoetProvingServiceClientPoetServiceIDCall { +func (mr *MockPoetProvingServiceClientMockRecorder) PoetServiceID(arg0 any) *PoetProvingServiceClientPoetServiceIDCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PoetServiceID", reflect.TypeOf((*MockPoetProvingServiceClient)(nil).PoetServiceID), arg0) return &PoetProvingServiceClientPoetServiceIDCall{Call: call} @@ -122,7 +126,7 @@ func (m *MockPoetProvingServiceClient) PowParams(ctx context.Context) (*PoetPowP } // PowParams indicates an expected call of PowParams. -func (mr *MockPoetProvingServiceClientMockRecorder) PowParams(ctx interface{}) *PoetProvingServiceClientPowParamsCall { +func (mr *MockPoetProvingServiceClientMockRecorder) PowParams(ctx any) *PoetProvingServiceClientPowParamsCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PowParams", reflect.TypeOf((*MockPoetProvingServiceClient)(nil).PowParams), ctx) return &PoetProvingServiceClientPowParamsCall{Call: call} @@ -162,7 +166,7 @@ func (m *MockPoetProvingServiceClient) Proof(ctx context.Context, roundID string } // Proof indicates an expected call of Proof. -func (mr *MockPoetProvingServiceClientMockRecorder) Proof(ctx, roundID interface{}) *PoetProvingServiceClientProofCall { +func (mr *MockPoetProvingServiceClientMockRecorder) Proof(ctx, roundID any) *PoetProvingServiceClientProofCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Proof", reflect.TypeOf((*MockPoetProvingServiceClient)(nil).Proof), ctx, roundID) return &PoetProvingServiceClientProofCall{Call: call} @@ -201,7 +205,7 @@ func (m *MockPoetProvingServiceClient) Submit(ctx context.Context, prefix, chall } // Submit indicates an expected call of Submit. -func (mr *MockPoetProvingServiceClientMockRecorder) Submit(ctx, prefix, challenge, signature, nodeID, pow interface{}) *PoetProvingServiceClientSubmitCall { +func (mr *MockPoetProvingServiceClientMockRecorder) Submit(ctx, prefix, challenge, signature, nodeID, pow any) *PoetProvingServiceClientSubmitCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Submit", reflect.TypeOf((*MockPoetProvingServiceClient)(nil).Submit), ctx, prefix, challenge, signature, nodeID, pow) return &PoetProvingServiceClientSubmitCall{Call: call} @@ -264,7 +268,7 @@ func (m *MockpoetDbAPI) GetProof(arg0 types.PoetProofRef) (*types.PoetProof, *ty } // GetProof indicates an expected call of GetProof. -func (mr *MockpoetDbAPIMockRecorder) GetProof(arg0 interface{}) *poetDbAPIGetProofCall { +func (mr *MockpoetDbAPIMockRecorder) GetProof(arg0 any) *poetDbAPIGetProofCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetProof", reflect.TypeOf((*MockpoetDbAPI)(nil).GetProof), arg0) return &poetDbAPIGetProofCall{Call: call} @@ -302,7 +306,7 @@ func (m *MockpoetDbAPI) ValidateAndStore(ctx context.Context, proofMessage *type } // ValidateAndStore indicates an expected call of ValidateAndStore. -func (mr *MockpoetDbAPIMockRecorder) ValidateAndStore(ctx, proofMessage interface{}) *poetDbAPIValidateAndStoreCall { +func (mr *MockpoetDbAPIMockRecorder) ValidateAndStore(ctx, proofMessage any) *poetDbAPIValidateAndStoreCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidateAndStore", reflect.TypeOf((*MockpoetDbAPI)(nil).ValidateAndStore), ctx, proofMessage) return &poetDbAPIValidateAndStoreCall{Call: call} diff --git a/activation/nipost_state.go b/activation/nipost_state.go index 67e422c0a9..53b536090f 100644 --- a/activation/nipost_state.go +++ b/activation/nipost_state.go @@ -22,30 +22,30 @@ const ( ) func write(path string, data []byte) error { - tmp, err := os.Create(fmt.Sprintf("%s.tmp", path)) + tmpName := fmt.Sprintf("%s.tmp", path) + tmp, err := os.Create(tmpName) if err != nil { - return fmt.Errorf("create temporary file %s: %w", tmp.Name(), err) + return fmt.Errorf("create temporary file %s: %w", tmpName, err) } + defer tmp.Close() checksum := crc64.New(crc64.MakeTable(crc64.ISO)) w := io.MultiWriter(tmp, checksum) - if _, err = w.Write(data); err != nil { - _ = tmp.Close() + if _, err := w.Write(data); err != nil { return fmt.Errorf("write data %v: %w", tmp.Name(), err) } crc := make([]byte, crc64.Size) binary.BigEndian.PutUint64(crc, checksum.Sum64()) - if _, err = tmp.Write(crc); err != nil { - _ = tmp.Close() + if _, err := tmp.Write(crc); err != nil { return fmt.Errorf("write checksum %s: %w", tmp.Name(), err) } - if err = tmp.Close(); err != nil { + if err := tmp.Close(); err != nil { return fmt.Errorf("failed to close tmp file %s: %w", tmp.Name(), err) } - if err = atomic.ReplaceFile(tmp.Name(), path); err != nil { + if err := atomic.ReplaceFile(tmp.Name(), path); err != nil { return fmt.Errorf("save file from %s, %s: %w", tmp.Name(), path, err) } @@ -57,7 +57,6 @@ func read(path string) ([]byte, error) { if err != nil { return nil, fmt.Errorf("open file %s: %w", path, err) } - defer file.Close() fInfo, err := file.Stat() @@ -70,20 +69,19 @@ func read(path string) ([]byte, error) { data := make([]byte, fInfo.Size()-crc64.Size) checksum := crc64.New(crc64.MakeTable(crc64.ISO)) - if _, err = io.TeeReader(file, checksum).Read(data); err != nil { + if _, err := io.TeeReader(file, checksum).Read(data); err != nil { return nil, fmt.Errorf("read file %s: %w", path, err) } saved := make([]byte, crc64.Size) - if _, err = file.Read(saved); err != nil { + if _, err := file.Read(saved); err != nil { return nil, fmt.Errorf("read checksum %s: %w", path, err) } savedChecksum := binary.BigEndian.Uint64(saved) if savedChecksum != checksum.Sum64() { - return nil, fmt.Errorf( - "wrong checksum 0x%X, computed 0x%X", savedChecksum, checksum.Sum64()) + return nil, fmt.Errorf("wrong checksum 0x%X, computed 0x%X", savedChecksum, checksum.Sum64()) } return data, nil diff --git a/activation/nipost_test.go b/activation/nipost_test.go index e7993e5cd9..1cbce2c9a2 100644 --- a/activation/nipost_test.go +++ b/activation/nipost_test.go @@ -10,7 +10,6 @@ import ( "github.com/spacemeshos/go-scale/tester" "github.com/spacemeshos/poet/logging" "github.com/spacemeshos/post/proving" - "github.com/spacemeshos/post/verifying" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" @@ -61,7 +60,7 @@ func TestNIPostBuilderWithMocks(t *testing.T) { postProvider.EXPECT().GenerateProof(gomock.Any(), gomock.Any(), gomock.Any()) nipostValidator := NewMocknipostValidator(ctrl) - nipostValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(nil) + nipostValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(nil) poetProvider := defaultPoetServiceMock(t, []byte("poet"), "http://localhost:9999") poetProvider.EXPECT().Proof(gomock.Any(), "").Return(&types.PoetProofMessage{ @@ -113,7 +112,7 @@ func TestPostSetup(t *testing.T) { mclock := defaultLayerClockMock(t) nipostValidator := NewMocknipostValidator(gomock.NewController(t)) - nipostValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(1).Return(nil) + nipostValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(1).Return(nil) nb, err := NewNIPostBuilder( postProvider.id, @@ -154,7 +153,7 @@ func TestNIPostBuilderWithClients(t *testing.T) { require.NoError(t, err) defer verifier.Close() - v := NewValidator(poetDb, postProvider.Config(), logger, verifier) + v := NewValidator(poetDb, postProvider.Config(), postProvider.opts.Scrypt, logger, verifier) nipost := buildNIPost(t, postProvider, challenge, poetDb, v) _, err = v.NIPost( context.Background(), @@ -163,7 +162,6 @@ func TestNIPostBuilderWithClients(t *testing.T) { nipost, challenge.Hash(), postProvider.opts.NumUnits, - verifying.WithLabelScryptParams(postProvider.opts.Scrypt), ) require.NoError(t, err) } @@ -198,7 +196,7 @@ func buildNIPost(tb testing.TB, postProvider *testPostManager, nipostChallenge t PhaseShift: epoch / 5, CycleGap: epoch / 10, GracePeriod: epoch / 10, - RequestTimeout: epoch / 20, + RequestTimeout: epoch / 10, RequestRetryDelay: epoch / 100, MaxRequestRetries: 10, } @@ -213,7 +211,7 @@ func buildNIPost(tb testing.TB, postProvider *testPostManager, nipostChallenge t poetDb, []string{poetProver.RestURL().String()}, tb.TempDir(), - logtest.New(tb), + logtest.New(tb, zapcore.DebugLevel), signer, poetCfg, mclock, @@ -245,7 +243,7 @@ func TestNewNIPostBuilderNotInitialized(t *testing.T) { PhaseShift: epoch / 5, CycleGap: epoch / 10, GracePeriod: epoch / 10, - RequestTimeout: epoch / 20, + RequestTimeout: epoch / 10, RequestRetryDelay: epoch / 100, MaxRequestRetries: 10, } @@ -262,7 +260,7 @@ func TestNewNIPostBuilderNotInitialized(t *testing.T) { mclock := defaultLayerClockMock(t) nipostValidator := NewMocknipostValidator(ctrl) - nipostValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(1).Return(nil) + nipostValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(1).Return(nil) nb, err := NewNIPostBuilder( postProvider.id, @@ -293,7 +291,7 @@ func TestNewNIPostBuilderNotInitialized(t *testing.T) { verifier, err := NewPostVerifier(postProvider.cfg, logger) r.NoError(err) defer verifier.Close() - v := NewValidator(poetDb, postProvider.cfg, logger, verifier) + v := NewValidator(poetDb, postProvider.cfg, postProvider.opts.Scrypt, logger, verifier) _, err = v.NIPost( context.Background(), postProvider.id, @@ -301,7 +299,6 @@ func TestNewNIPostBuilderNotInitialized(t *testing.T) { nipost, challenge.Hash(), postProvider.opts.NumUnits, - verifying.WithLabelScryptParams(postProvider.opts.Scrypt), ) r.NoError(err) } @@ -364,7 +361,7 @@ func TestNIPostBuilder_BuildNIPost(t *testing.T) { req.NoError(err) postProvider.EXPECT().GenerateProof(gomock.Any(), gomock.Any(), gomock.Any()) - nipostValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()) + nipostValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()) nipost, err := nb.BuildNIPost(context.Background(), &challenge) req.NoError(err) req.NotNil(nipost) @@ -414,7 +411,7 @@ func TestNIPostBuilder_BuildNIPost(t *testing.T) { ) req.NoError(err) postProvider.EXPECT().GenerateProof(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) - nipostValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(1).Return(nil) + nipostValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(1).Return(nil) // check that proof ref is not called again nipost, err = nb.BuildNIPost(context.Background(), &challenge2) req.NoError(err) @@ -423,7 +420,7 @@ func TestNIPostBuilder_BuildNIPost(t *testing.T) { // test state not loading if other challenge provided poetDb.EXPECT().ValidateAndStore(gomock.Any(), gomock.Any()).Return(nil) postProvider.EXPECT().GenerateProof(gomock.Any(), gomock.Any(), gomock.Any()) - nipostValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()) + nipostValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()) nipost, err = nb.BuildNIPost(context.Background(), &challenge3) req.NoError(err) req.NotNil(nipost) @@ -485,7 +482,7 @@ func TestNIPostBuilder_ManyPoETs_SubmittingChallenge_DeadlineReached(t *testing. }, nil }, ) - nipostValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(1).Return(nil) + nipostValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(1).Return(nil) nb, err := NewNIPostBuilder( types.NodeID{1}, postProvider, @@ -561,7 +558,7 @@ func TestNIPostBuilder_ManyPoETs_AllFinished(t *testing.T) { }, nil }, ) - nipostValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(1).Return(nil) + nipostValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(1).Return(nil) nb, err := NewNIPostBuilder( types.NodeID{1}, postProvider, @@ -965,7 +962,7 @@ func TestNIPoSTBuilder_Continues_After_Interrupted(t *testing.T) { }, ) nipostValidator := NewMocknipostValidator(ctrl) - nipostValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(1).Return(nil) + nipostValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(1).Return(nil) nb, err := NewNIPostBuilder( types.NodeID{1}, postProvider, @@ -1042,88 +1039,116 @@ func TestConstructingMerkleProof(t *testing.T) { }) } -// TODO(mafa): remove after epoch 4 end; https://github.com/spacemeshos/go-spacemesh/issues/4968 func TestNIPostBuilder_Mainnet_PoetRound3_Workaround(t *testing.T) { t.Parallel() - challenge := types.NIPostChallenge{ - PublishEpoch: 4, - } - - ctrl := gomock.NewController(t) - postProvider := NewMockpostSetupProvider(ctrl) - postProvider.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) - postProvider.EXPECT().CommitmentAtx().Return(types.EmptyATXID, nil).AnyTimes() - postProvider.EXPECT().LastOpts().Return(&PostSetupOpts{}).AnyTimes() - postProvider.EXPECT().GenerateProof(gomock.Any(), gomock.Any(), gomock.Any()) - - nipostValidator := NewMocknipostValidator(ctrl) - nipostValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(nil) - - poets := make([]PoetProvingServiceClient, 0, 2) - { - poetProvider := NewMockPoetProvingServiceClient(ctrl) - poetProvider.EXPECT().Address().Return("https://poet-110.spacemesh.network") - poetProvider.EXPECT().PoetServiceID(gomock.Any()).Return(types.PoetServiceID{ServiceID: []byte("poet-110")}, nil).AnyTimes() - poetProvider.EXPECT().PowParams(gomock.Any()).AnyTimes().Return(&PoetPowParams{}, nil) - - // PoET 110 succeeds to submit - poetProvider.EXPECT().Submit(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(&types.PoetRound{}, nil) - - // proof is fetched from PoET 110 - poetProvider.EXPECT().Proof(gomock.Any(), "").Return(&types.PoetProofMessage{ - PoetProof: types.PoetProof{}, - }, []types.Member{types.Member(challenge.Hash())}, nil) - poets = append(poets, poetProvider) - } - - { - // PoET 111 fails submission - poetProvider := NewMockPoetProvingServiceClient(ctrl) - poetProvider.EXPECT().Address().Return("https://poet-111.spacemesh.network") - poetProvider.EXPECT().PoetServiceID(gomock.Any()).Return(types.PoetServiceID{}, errors.New("failed submission")) - - // proof is still fetched from PoET 111 - poetProvider.EXPECT().PoetServiceID(gomock.Any()).Return(types.PoetServiceID{ServiceID: []byte("poet-111")}, nil).AnyTimes() - poetProvider.EXPECT().Proof(gomock.Any(), "").Return(&types.PoetProofMessage{ - PoetProof: types.PoetProof{}, - }, []types.Member{types.Member(challenge.Hash())}, nil) - - poets = append(poets, poetProvider) - } - - poetDb := NewMockpoetDbAPI(ctrl) - poetDb.EXPECT().ValidateAndStore(gomock.Any(), gomock.Any()).Return(nil).Times(2) - mclock := NewMocklayerClock(ctrl) - genesis := time.Now().Add(-time.Duration(1) * layerDuration) - mclock.EXPECT().LayerToTime(gomock.Any()).AnyTimes().DoAndReturn( - func(got types.LayerID) time.Time { - return genesis.Add(layerDuration * time.Duration(got)) + tt := []struct { + name string + from string + to string + epoch types.EpochID + }{ + { + // TODO(mafa): remove after epoch 4 end; https://github.com/spacemeshos/go-spacemesh/issues/4968 + name: "epoch 4: PoET 111 restore with PoET 110", + from: "https://poet-110.spacemesh.network", + to: "https://poet-111.spacemesh.network", + epoch: 4, }, - ) + { + // TODO(mafa): remove after epoch 5 end; https://github.com/spacemeshos/go-spacemesh/issues/5030 + name: "epoch 5: PoET 112 restore with PoET 110", + from: "https://poet-110.spacemesh.network", + to: "https://poet-112.spacemesh.network", + epoch: 5, + }, + } - sig, err := signing.NewEdSigner() - require.NoError(t, err) - poetCfg := PoetConfig{ - PhaseShift: layerDuration * layersPerEpoch / 2, + for _, tc := range tt { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + challenge := types.NIPostChallenge{ + PublishEpoch: tc.epoch, + } + + ctrl := gomock.NewController(t) + postProvider := NewMockpostSetupProvider(ctrl) + postProvider.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) + postProvider.EXPECT().CommitmentAtx().Return(types.EmptyATXID, nil).AnyTimes() + postProvider.EXPECT().LastOpts().Return(&PostSetupOpts{}).AnyTimes() + postProvider.EXPECT().GenerateProof(gomock.Any(), gomock.Any(), gomock.Any()) + + nipostValidator := NewMocknipostValidator(ctrl) + nipostValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(nil) + + poets := make([]PoetProvingServiceClient, 0, 2) + { + poetProvider := NewMockPoetProvingServiceClient(ctrl) + poetProvider.EXPECT().Address().Return(tc.from) + poetProvider.EXPECT().PoetServiceID(gomock.Any()).Return(types.PoetServiceID{ServiceID: []byte("poet-from")}, nil).AnyTimes() + poetProvider.EXPECT().PowParams(gomock.Any()).AnyTimes().Return(&PoetPowParams{}, nil) + + // PoET succeeds to submit + poetProvider.EXPECT().Submit(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(&types.PoetRound{}, nil) + + // proof is fetched from PoET + poetProvider.EXPECT().Proof(gomock.Any(), "").Return(&types.PoetProofMessage{ + PoetProof: types.PoetProof{}, + }, []types.Member{types.Member(challenge.Hash())}, nil) + poets = append(poets, poetProvider) + } + + { + // PoET fails submission + poetProvider := NewMockPoetProvingServiceClient(ctrl) + poetProvider.EXPECT().Address().Return(tc.to) + poetProvider.EXPECT().PoetServiceID(gomock.Any()).Return(types.PoetServiceID{}, errors.New("failed submission")) + + // proof is still fetched from PoET + poetProvider.EXPECT().PoetServiceID(gomock.Any()).Return(types.PoetServiceID{ServiceID: []byte("poet-to")}, nil).AnyTimes() + poetProvider.EXPECT().Proof(gomock.Any(), "").Return(&types.PoetProofMessage{ + PoetProof: types.PoetProof{}, + }, []types.Member{types.Member(challenge.Hash())}, nil) + + poets = append(poets, poetProvider) + } + + poetDb := NewMockpoetDbAPI(ctrl) + poetDb.EXPECT().ValidateAndStore(gomock.Any(), gomock.Any()).Return(nil).Times(2) + mclock := NewMocklayerClock(ctrl) + genesis := time.Now().Add(-time.Duration(1) * layerDuration) + mclock.EXPECT().LayerToTime(gomock.Any()).AnyTimes().DoAndReturn( + func(got types.LayerID) time.Time { + return genesis.Add(layerDuration * time.Duration(got)) + }, + ) + + sig, err := signing.NewEdSigner() + require.NoError(t, err) + poetCfg := PoetConfig{ + PhaseShift: layerDuration * layersPerEpoch / 2, + } + nb, err := NewNIPostBuilder( + types.NodeID{1}, + postProvider, + poetDb, + []string{}, + t.TempDir(), + logtest.New(t, zapcore.DebugLevel), + sig, + poetCfg, + mclock, + WithNipostValidator(nipostValidator), + withPoetClients(poets), + ) + require.NoError(t, err) + nipost, err := nb.BuildNIPost(context.Background(), &challenge) + require.NoError(t, err) + require.NotNil(t, nipost) + }) } - nb, err := NewNIPostBuilder( - types.NodeID{1}, - postProvider, - poetDb, - []string{}, - t.TempDir(), - logtest.New(t, zapcore.DebugLevel), - sig, - poetCfg, - mclock, - WithNipostValidator(nipostValidator), - withPoetClients(poets), - ) - require.NoError(t, err) - nipost, err := nb.BuildNIPost(context.Background(), &challenge) - require.NoError(t, err) - require.NotNil(t, nipost) } func FuzzBuilderStateConsistency(f *testing.F) { diff --git a/activation/poet_client_test.go b/activation/poet_client_test.go index fb58a43dff..b749b0d14a 100644 --- a/activation/poet_client_test.go +++ b/activation/poet_client_test.go @@ -6,8 +6,8 @@ import ( "net/http/httptest" "testing" - "github.com/spacemeshos/poet/config" rpcapi "github.com/spacemeshos/poet/release/proto/go/rpc/api/v1" + "github.com/spacemeshos/poet/server" "github.com/stretchr/testify/require" "google.golang.org/protobuf/encoding/protojson" @@ -15,12 +15,12 @@ import ( ) func Test_HTTPPoetClient_ParsesURL(t *testing.T) { - cfg := config.DefaultConfig() + cfg := server.DefaultRoundConfig() t.Run("add http if missing", func(t *testing.T) { client, err := NewHTTPPoetClient("bla", PoetConfig{ - PhaseShift: cfg.Service.PhaseShift, - CycleGap: cfg.Service.CycleGap, + PhaseShift: cfg.PhaseShift, + CycleGap: cfg.CycleGap, }) require.NoError(t, err) require.Equal(t, "http://bla", client.baseURL.String()) @@ -28,8 +28,8 @@ func Test_HTTPPoetClient_ParsesURL(t *testing.T) { t.Run("do not change scheme if present", func(t *testing.T) { client, err := NewHTTPPoetClient("https://bla", PoetConfig{ - PhaseShift: cfg.Service.PhaseShift, - CycleGap: cfg.Service.CycleGap, + PhaseShift: cfg.PhaseShift, + CycleGap: cfg.CycleGap, }) require.NoError(t, err) require.Equal(t, "https://bla", client.baseURL.String()) @@ -49,10 +49,10 @@ func Test_HTTPPoetClient_Submit(t *testing.T) { })) defer ts.Close() - cfg := config.DefaultConfig() + cfg := server.DefaultRoundConfig() client, err := NewHTTPPoetClient(ts.URL, PoetConfig{ - PhaseShift: cfg.Service.PhaseShift, - CycleGap: cfg.Service.CycleGap, + PhaseShift: cfg.PhaseShift, + CycleGap: cfg.CycleGap, }, withCustomHttpClient(ts.Client())) require.NoError(t, err) @@ -73,10 +73,10 @@ func Test_HTTPPoetClient_Address(t *testing.T) { })) defer ts.Close() - cfg := config.DefaultConfig() + cfg := server.DefaultRoundConfig() client, err := NewHTTPPoetClient(ts.URL, PoetConfig{ - PhaseShift: cfg.Service.PhaseShift, - CycleGap: cfg.Service.CycleGap, + PhaseShift: cfg.PhaseShift, + CycleGap: cfg.CycleGap, }, withCustomHttpClient(ts.Client())) require.NoError(t, err) @@ -84,7 +84,7 @@ func Test_HTTPPoetClient_Address(t *testing.T) { } func Test_HTTPPoetClient_Address_Mainnet(t *testing.T) { - poetCfg := config.DefaultConfig() + poetCfg := server.DefaultRoundConfig() poETServers := []string{ "https://mainnet-poet-0.spacemesh.network", @@ -97,8 +97,8 @@ func Test_HTTPPoetClient_Address_Mainnet(t *testing.T) { for _, url := range poETServers { t.Run(url, func(t *testing.T) { client, err := NewHTTPPoetClient(url, PoetConfig{ - PhaseShift: poetCfg.Service.PhaseShift, - CycleGap: poetCfg.Service.CycleGap, + PhaseShift: poetCfg.PhaseShift, + CycleGap: poetCfg.CycleGap, }) require.NoError(t, err) require.Equal(t, url, client.Address()) @@ -119,10 +119,10 @@ func Test_HTTPPoetClient_Proof(t *testing.T) { })) defer ts.Close() - cfg := config.DefaultConfig() + cfg := server.DefaultRoundConfig() client, err := NewHTTPPoetClient(ts.URL, PoetConfig{ - PhaseShift: cfg.Service.PhaseShift, - CycleGap: cfg.Service.CycleGap, + PhaseShift: cfg.PhaseShift, + CycleGap: cfg.CycleGap, }, withCustomHttpClient(ts.Client())) require.NoError(t, err) @@ -143,10 +143,10 @@ func Test_HTTPPoetClient_PoetServiceID(t *testing.T) { })) defer ts.Close() - cfg := config.DefaultConfig() + cfg := server.DefaultRoundConfig() client, err := NewHTTPPoetClient(ts.URL, PoetConfig{ - PhaseShift: cfg.Service.PhaseShift, - CycleGap: cfg.Service.CycleGap, + PhaseShift: cfg.PhaseShift, + CycleGap: cfg.CycleGap, }, withCustomHttpClient(ts.Client())) require.NoError(t, err) diff --git a/activation/poet_test.go b/activation/poet_test.go index 7145820165..5599ed4a8b 100644 --- a/activation/poet_test.go +++ b/activation/poet_test.go @@ -8,6 +8,7 @@ import ( "net/url" "testing" + "github.com/spacemeshos/poet/shared" "github.com/stretchr/testify/require" "go.uber.org/zap/zaptest" "golang.org/x/sync/errgroup" @@ -41,14 +42,29 @@ func TestHTTPPoet(t *testing.T) { client, err := NewHTTPPoetClient(c.RestURL().String(), DefaultPoetConfig(), WithLogger(zaptest.NewLogger(t))) require.NoError(t, err) + resp, err := client.PowParams(context.Background()) + r.NoError(err) + signer, err := signing.NewEdSigner(signing.WithPrefix([]byte("prefix"))) require.NoError(t, err) ch := types.RandomHash() + nonce, err := shared.FindSubmitPowNonce( + context.Background(), + resp.Challenge, + ch.Bytes(), + signer.NodeID().Bytes(), + uint(resp.Difficulty), + ) + r.NoError(err) + signature := signer.Sign(signing.POET, ch.Bytes()) prefix := bytes.Join([][]byte{signer.Prefix(), {byte(signing.POET)}}, nil) - poetRound, err := client.Submit(context.Background(), prefix, ch.Bytes(), signature, signer.NodeID(), PoetPoW{}) + poetRound, err := client.Submit(context.Background(), prefix, ch.Bytes(), signature, signer.NodeID(), PoetPoW{ + Nonce: nonce, + Params: *resp, + }) r.NoError(err) r.NotNil(poetRound) } diff --git a/activation/poet_test_harness.go b/activation/poet_test_harness.go index 83108ecfdb..1351c37ab0 100644 --- a/activation/poet_test_harness.go +++ b/activation/poet_test_harness.go @@ -5,9 +5,7 @@ import ( "net/url" "time" - "github.com/spacemeshos/poet/config" "github.com/spacemeshos/poet/server" - "github.com/spacemeshos/poet/service" ) // HTTPPoetTestHarness utilizes a local self-contained poet server instance @@ -23,35 +21,35 @@ func (h *HTTPPoetTestHarness) RestURL() *url.URL { } } -type HTTPPoetOpt func(*config.Config) +type HTTPPoetOpt func(*server.Config) func WithGenesis(genesis time.Time) HTTPPoetOpt { - return func(cfg *config.Config) { - cfg.Service.Genesis = service.Genesis(genesis) + return func(cfg *server.Config) { + cfg.Genesis = server.Genesis(genesis) } } func WithEpochDuration(epoch time.Duration) HTTPPoetOpt { - return func(cfg *config.Config) { - cfg.Service.EpochDuration = epoch + return func(cfg *server.Config) { + cfg.Round.EpochDuration = epoch } } func WithPhaseShift(phase time.Duration) HTTPPoetOpt { - return func(cfg *config.Config) { - cfg.Service.PhaseShift = phase + return func(cfg *server.Config) { + cfg.Round.PhaseShift = phase } } func WithCycleGap(gap time.Duration) HTTPPoetOpt { - return func(cfg *config.Config) { - cfg.Service.CycleGap = gap + return func(cfg *server.Config) { + cfg.Round.CycleGap = gap } } // NewHTTPPoetTestHarness returns a new instance of HTTPPoetHarness. func NewHTTPPoetTestHarness(ctx context.Context, poetdir string, opts ...HTTPPoetOpt) (*HTTPPoetTestHarness, error) { - cfg := config.DefaultConfig() + cfg := server.DefaultConfig() cfg.PoetDir = poetdir cfg.RawRESTListener = "localhost:0" cfg.RawRPCListener = "localhost:0" @@ -60,10 +58,7 @@ func NewHTTPPoetTestHarness(ctx context.Context, poetdir string, opts ...HTTPPoe opt(cfg) } - cfg, err := config.SetupConfig(cfg) - if err != nil { - return nil, err - } + server.SetupConfig(cfg) poet, err := server.New(ctx, *cfg) if err != nil { diff --git a/activation/poetdb_test.go b/activation/poetdb_test.go index a96147b341..c1ef5a5831 100644 --- a/activation/poetdb_test.go +++ b/activation/poetdb_test.go @@ -28,9 +28,7 @@ var ( func getPoetProof(t *testing.T) types.PoetProofMessage { createProofOnce.Do(func() { - members := [][]byte{memberHash[:]} - challenge, err := prover.CalcTreeRoot(members) - require.NoError(t, err) + challenge := memberHash[:] leaves, merkleProof, err := prover.GenerateProofWithoutPersistency( context.Background(), diff --git a/activation/post_verifier_test.go b/activation/post_verifier_test.go index e1932cabd6..6c12d3d893 100644 --- a/activation/post_verifier_test.go +++ b/activation/post_verifier_test.go @@ -13,6 +13,7 @@ import ( "github.com/spacemeshos/go-spacemesh/activation" "github.com/spacemeshos/go-spacemesh/log" + "github.com/spacemeshos/go-spacemesh/log/logtest" ) func TestOffloadingPostVerifier(t *testing.T) { @@ -40,7 +41,7 @@ func TestOffloadingPostVerifier(t *testing.T) { } func TestPostVerifierDetectsInvalidProof(t *testing.T) { - verifier, err := activation.NewPostVerifier(activation.PostConfig{}, log.NewDefault(t.Name())) + verifier, err := activation.NewPostVerifier(activation.PostConfig{}, logtest.New(t)) require.NoError(t, err) defer verifier.Close() require.Error(t, verifier.Verify(context.Background(), &shared.Proof{}, &shared.ProofMetadata{})) diff --git a/activation/validation.go b/activation/validation.go index 7e11748012..4b8b82852d 100644 --- a/activation/validation.go +++ b/activation/validation.go @@ -8,6 +8,7 @@ import ( "github.com/spacemeshos/merkle-tree" poetShared "github.com/spacemeshos/poet/shared" + "github.com/spacemeshos/post/config" "github.com/spacemeshos/post/shared" "github.com/spacemeshos/post/verifying" @@ -40,13 +41,14 @@ func (e *ErrAtxNotFound) Is(target error) bool { type Validator struct { poetDb poetDbAPI cfg PostConfig + scrypt config.ScryptParams log log.Log postVerifier PostVerifier } // NewValidator returns a new NIPost validator. -func NewValidator(poetDb poetDbAPI, cfg PostConfig, log log.Log, postVerifier PostVerifier) *Validator { - return &Validator{poetDb, cfg, log, postVerifier} +func NewValidator(poetDb poetDbAPI, cfg PostConfig, scrypt config.ScryptParams, log log.Log, postVerifier PostVerifier) *Validator { + return &Validator{poetDb, cfg, scrypt, log, postVerifier} } // NIPost validates a NIPost, given a node id and expected challenge. It returns an error if the NIPost is invalid. @@ -54,7 +56,7 @@ func NewValidator(poetDb poetDbAPI, cfg PostConfig, log log.Log, postVerifier Po // Some of the Post metadata fields validation values is ought to eventually be derived from // consensus instead of local configuration. If so, their validation should be removed to contextual validation, // while still syntactically-validate them here according to locally configured min/max values. -func (v *Validator) NIPost(ctx context.Context, nodeId types.NodeID, commitmentAtxId types.ATXID, nipost *types.NIPost, expectedChallenge types.Hash32, numUnits uint32, opts ...verifying.OptionFunc) (uint64, error) { +func (v *Validator) NIPost(ctx context.Context, nodeId types.NodeID, commitmentAtxId types.ATXID, nipost *types.NIPost, expectedChallenge types.Hash32, numUnits uint32) (uint64, error) { if err := v.NumUnits(&v.cfg, numUnits); err != nil { return 0, err } @@ -63,7 +65,7 @@ func (v *Validator) NIPost(ctx context.Context, nodeId types.NodeID, commitmentA return 0, err } - if err := v.Post(ctx, nodeId, commitmentAtxId, nipost.Post, nipost.PostMetadata, numUnits, opts...); err != nil { + if err := v.Post(ctx, nodeId, commitmentAtxId, nipost.Post, nipost.PostMetadata, numUnits); err != nil { return 0, fmt.Errorf("invalid Post: %w", err) } @@ -113,7 +115,7 @@ func validateMerkleProof(leaf []byte, proof *types.MerkleProof, expectedRoot []b // Post validates a Proof of Space-Time (PoST). It returns nil if validation passed or an error indicating why // validation failed. -func (v *Validator) Post(ctx context.Context, nodeId types.NodeID, commitmentAtxId types.ATXID, PoST *types.Post, PostMetadata *types.PostMetadata, numUnits uint32, opts ...verifying.OptionFunc) error { +func (v *Validator) Post(ctx context.Context, nodeId types.NodeID, commitmentAtxId types.ATXID, PoST *types.Post, PostMetadata *types.PostMetadata, numUnits uint32) error { p := (*shared.Proof)(PoST) m := &shared.ProofMetadata{ @@ -124,10 +126,8 @@ func (v *Validator) Post(ctx context.Context, nodeId types.NodeID, commitmentAtx LabelsPerUnit: PostMetadata.LabelsPerUnit, } - opts = append(opts, verifying.WithPowCreator(nodeId.Bytes())) - start := time.Now() - if err := v.postVerifier.Verify(ctx, p, m, opts...); err != nil { + if err := v.postVerifier.Verify(ctx, p, m, verifying.WithPowCreator(nodeId.Bytes()), verifying.WithLabelScryptParams(v.scrypt)); err != nil { return fmt.Errorf("verify PoST: %w", err) } metrics.PostVerificationLatency.Observe(time.Since(start).Seconds()) @@ -152,7 +152,7 @@ func (*Validator) PostMetadata(cfg *PostConfig, metadata *types.PostMetadata) er return nil } -func (*Validator) VRFNonce(nodeId types.NodeID, commitmentAtxId types.ATXID, vrfNonce *types.VRFPostIndex, PostMetadata *types.PostMetadata, numUnits uint32) error { +func (v *Validator) VRFNonce(nodeId types.NodeID, commitmentAtxId types.ATXID, vrfNonce *types.VRFPostIndex, PostMetadata *types.PostMetadata, numUnits uint32) error { if vrfNonce == nil { return errors.New("VRFNonce is nil") } @@ -164,7 +164,7 @@ func (*Validator) VRFNonce(nodeId types.NodeID, commitmentAtxId types.ATXID, vrf LabelsPerUnit: PostMetadata.LabelsPerUnit, } - if err := verifying.VerifyVRFNonce((*uint64)(vrfNonce), meta); err != nil { + if err := verifying.VerifyVRFNonce((*uint64)(vrfNonce), meta, verifying.WithPowCreator(nodeId.Bytes()), verifying.WithLabelScryptParams(v.scrypt)); err != nil { return fmt.Errorf("verify VRF nonce: %w", err) } return nil diff --git a/activation/validation_test.go b/activation/validation_test.go index 45b49b59e6..3997cf9c19 100644 --- a/activation/validation_test.go +++ b/activation/validation_test.go @@ -6,9 +6,9 @@ import ( "fmt" "testing" + "github.com/spacemeshos/post/config" "github.com/spacemeshos/post/initialization" "github.com/spacemeshos/post/shared" - "github.com/spacemeshos/post/verifying" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" @@ -48,7 +48,7 @@ func Test_Validation_VRFNonce(t *testing.T) { nonce := (*types.VRFPostIndex)(init.Nonce()) - v := NewValidator(poetDbAPI, postCfg, logtest.New(t).WithName("validator"), nil) + v := NewValidator(poetDbAPI, postCfg, initOpts.Scrypt, logtest.New(t).WithName("validator"), nil) // Act & Assert t.Run("valid vrf nonce", func(t *testing.T) { @@ -89,7 +89,7 @@ func Test_Validation_InitialNIPostChallenge(t *testing.T) { postCfg := DefaultPostConfig() goldenATXID := types.ATXID{2, 3, 4} - v := NewValidator(poetDbAPI, postCfg, logtest.New(t).WithName("validator"), nil) + v := NewValidator(poetDbAPI, postCfg, config.ScryptParams{}, logtest.New(t).WithName("validator"), nil) // Act & Assert t.Run("valid initial nipost challenge passes", func(t *testing.T) { @@ -157,7 +157,7 @@ func Test_Validation_NIPostChallenge(t *testing.T) { poetDbAPI := NewMockpoetDbAPI(ctrl) postCfg := DefaultPostConfig() - v := NewValidator(poetDbAPI, postCfg, logtest.New(t).WithName("validator"), nil) + v := NewValidator(poetDbAPI, postCfg, config.ScryptParams{}, logtest.New(t).WithName("validator"), nil) // Act & Assert t.Run("valid nipost challenge passes", func(t *testing.T) { @@ -283,7 +283,7 @@ func Test_Validation_Post(t *testing.T) { postCfg := DefaultPostConfig() postVerifier := NewMockPostVerifier(ctrl) - v := NewValidator(poetDbAPI, postCfg, logtest.New(t).WithName("validator"), postVerifier) + v := NewValidator(poetDbAPI, postCfg, config.ScryptParams{}, logtest.New(t).WithName("validator"), postVerifier) post := types.Post{} meta := types.PostMetadata{} @@ -305,7 +305,7 @@ func Test_Validation_PositioningAtx(t *testing.T) { poetDbAPI := NewMockpoetDbAPI(ctrl) postCfg := DefaultPostConfig() - v := NewValidator(poetDbAPI, postCfg, logtest.New(t).WithName("validator"), nil) + v := NewValidator(poetDbAPI, postCfg, config.ScryptParams{}, logtest.New(t).WithName("validator"), nil) // Act & Assert t.Run("valid nipost challenge passes", func(t *testing.T) { @@ -409,7 +409,7 @@ func Test_Validate_NumUnits(t *testing.T) { poetDbAPI := NewMockpoetDbAPI(ctrl) postCfg := DefaultPostConfig() - v := NewValidator(poetDbAPI, postCfg, logtest.New(t).WithName("validator"), nil) + v := NewValidator(poetDbAPI, postCfg, config.ScryptParams{}, logtest.New(t).WithName("validator"), nil) // Act & Assert t.Run("valid number of num units passes", func(t *testing.T) { @@ -443,7 +443,7 @@ func Test_Validate_PostMetadata(t *testing.T) { poetDbAPI := NewMockpoetDbAPI(ctrl) postCfg := DefaultPostConfig() - v := NewValidator(poetDbAPI, postCfg, logtest.New(t).WithName("validator"), nil) + v := NewValidator(poetDbAPI, postCfg, config.ScryptParams{}, logtest.New(t).WithName("validator"), nil) // Act & Assert t.Run("valid post metadata", func(t *testing.T) { @@ -485,39 +485,37 @@ func TestValidator_Validate(t *testing.T) { r.NoError(err) defer verifier.Close() - v := NewValidator(poetDb, postProvider.cfg, logger, verifier) + v := NewValidator(poetDb, postProvider.cfg, postProvider.opts.Scrypt, logger, verifier) nipost := buildNIPost(t, postProvider, challenge, poetDb, v) - opts := []verifying.OptionFunc{verifying.WithLabelScryptParams(postProvider.opts.Scrypt)} - - _, err = v.NIPost(context.Background(), postProvider.id, postProvider.commitmentAtxId, nipost, challengeHash, postProvider.opts.NumUnits, opts...) + _, err = v.NIPost(context.Background(), postProvider.id, postProvider.commitmentAtxId, nipost, challengeHash, postProvider.opts.NumUnits) r.NoError(err) - _, err = v.NIPost(context.Background(), postProvider.id, postProvider.commitmentAtxId, nipost, types.BytesToHash([]byte("lerner")), postProvider.opts.NumUnits, opts...) + _, err = v.NIPost(context.Background(), postProvider.id, postProvider.commitmentAtxId, nipost, types.BytesToHash([]byte("lerner")), postProvider.opts.NumUnits) r.Contains(err.Error(), "invalid membership proof") newNIPost := *nipost newNIPost.Post = &types.Post{} - _, err = v.NIPost(context.Background(), postProvider.id, postProvider.commitmentAtxId, &newNIPost, challengeHash, postProvider.opts.NumUnits, opts...) + _, err = v.NIPost(context.Background(), postProvider.id, postProvider.commitmentAtxId, &newNIPost, challengeHash, postProvider.opts.NumUnits) r.Contains(err.Error(), "invalid Post") newPostCfg := postProvider.cfg newPostCfg.MinNumUnits = postProvider.opts.NumUnits + 1 - v = NewValidator(poetDb, newPostCfg, logtest.New(t).WithName("validator"), nil) - _, err = v.NIPost(context.Background(), postProvider.id, postProvider.commitmentAtxId, nipost, challengeHash, postProvider.opts.NumUnits, opts...) + v = NewValidator(poetDb, newPostCfg, postProvider.opts.Scrypt, logtest.New(t).WithName("validator"), nil) + _, err = v.NIPost(context.Background(), postProvider.id, postProvider.commitmentAtxId, nipost, challengeHash, postProvider.opts.NumUnits) r.EqualError(err, fmt.Sprintf("invalid `numUnits`; expected: >=%d, given: %d", newPostCfg.MinNumUnits, postProvider.opts.NumUnits)) newPostCfg = postProvider.cfg newPostCfg.MaxNumUnits = postProvider.opts.NumUnits - 1 - v = NewValidator(poetDb, newPostCfg, logtest.New(t).WithName("validator"), nil) - _, err = v.NIPost(context.Background(), postProvider.id, postProvider.commitmentAtxId, nipost, challengeHash, postProvider.opts.NumUnits, opts...) + v = NewValidator(poetDb, newPostCfg, postProvider.opts.Scrypt, logtest.New(t).WithName("validator"), nil) + _, err = v.NIPost(context.Background(), postProvider.id, postProvider.commitmentAtxId, nipost, challengeHash, postProvider.opts.NumUnits) r.EqualError(err, fmt.Sprintf("invalid `numUnits`; expected: <=%d, given: %d", newPostCfg.MaxNumUnits, postProvider.opts.NumUnits)) newPostCfg = postProvider.cfg newPostCfg.LabelsPerUnit = nipost.PostMetadata.LabelsPerUnit + 1 - v = NewValidator(poetDb, newPostCfg, logtest.New(t).WithName("validator"), nil) - _, err = v.NIPost(context.Background(), postProvider.id, postProvider.commitmentAtxId, nipost, challengeHash, postProvider.opts.NumUnits, opts...) + v = NewValidator(poetDb, newPostCfg, postProvider.opts.Scrypt, logtest.New(t).WithName("validator"), nil) + _, err = v.NIPost(context.Background(), postProvider.id, postProvider.commitmentAtxId, nipost, challengeHash, postProvider.opts.NumUnits) r.EqualError(err, fmt.Sprintf("invalid `LabelsPerUnit`; expected: >=%d, given: %d", newPostCfg.LabelsPerUnit, nipost.PostMetadata.LabelsPerUnit)) } diff --git a/api/grpcserver/grpcserver_test.go b/api/grpcserver/grpcserver_test.go index 5d6eb29077..6ba1b85ed6 100644 --- a/api/grpcserver/grpcserver_test.go +++ b/api/grpcserver/grpcserver_test.go @@ -50,6 +50,7 @@ import ( "github.com/spacemeshos/go-spacemesh/signing" "github.com/spacemeshos/go-spacemesh/sql" "github.com/spacemeshos/go-spacemesh/sql/accounts" + "github.com/spacemeshos/go-spacemesh/sql/activesets" "github.com/spacemeshos/go-spacemesh/sql/atxs" "github.com/spacemeshos/go-spacemesh/sql/identities" "github.com/spacemeshos/go-spacemesh/system" @@ -58,7 +59,6 @@ import ( const ( labelsPerUnit = 2048 - bitsPerLabel = 8 numUnits = 2 genTimeUnix = 1000000 layerDuration = 10 * time.Second @@ -71,7 +71,6 @@ const ( accountBalance = 8675301 accountCounter = 0 rewardAmount = 5551234 - activesetSize = 10001 ) var ( @@ -214,8 +213,7 @@ func TestMain(m *testing.M) { // These create circular dependencies so they have to be initialized // after the global vars ballot1.AtxID = globalAtx.ID() - ballot1.EpochData = &types.EpochData{} - ballot1.ActiveSet = []types.ATXID{globalAtx.ID(), globalAtx2.ID()} + ballot1.EpochData = &types.EpochData{ActiveSetHash: types.ATXIDList{globalAtx.ID(), globalAtx2.ID()}.Hash()} globalTx = NewTx(0, addr1, signer1) globalTx2 = NewTx(1, addr2, signer2) @@ -1043,7 +1041,9 @@ func TestMeshService(t *testing.T) { genesis := time.Unix(genTimeUnix, 0) genTime.EXPECT().GenesisTime().Return(genesis) genTime.EXPECT().CurrentLayer().Return(layerCurrent).AnyTimes() - grpcService := NewMeshService(datastore.NewCachedDB(sql.InMemory(), logtest.New(t)), meshAPIMock, conStateAPI, genTime, layersPerEpoch, types.Hash20{}, layerDuration, layerAvgSize, txsPerProposal) + db := datastore.NewCachedDB(sql.InMemory(), logtest.New(t)) + grpcService := NewMeshService(db, meshAPIMock, conStateAPI, genTime, layersPerEpoch, types.Hash20{}, layerDuration, layerAvgSize, txsPerProposal) + require.NoError(t, activesets.Add(db, ballot1.EpochData.ActiveSetHash, &types.EpochActiveSet{Set: types.ATXIDList{globalAtx.ID(), globalAtx2.ID()}})) t.Cleanup(launchServer(t, cfg, grpcService)) ctx, cancel := context.WithTimeout(context.Background(), time.Second) @@ -2163,7 +2163,9 @@ func TestLayerStream_comprehensive(t *testing.T) { ctrl := gomock.NewController(t) genTime := NewMockgenesisTimeAPI(ctrl) - grpcService := NewMeshService(datastore.NewCachedDB(sql.InMemory(), logtest.New(t)), meshAPIMock, conStateAPI, genTime, layersPerEpoch, types.Hash20{}, layerDuration, layerAvgSize, txsPerProposal) + db := datastore.NewCachedDB(sql.InMemory(), logtest.New(t)) + grpcService := NewMeshService(db, meshAPIMock, conStateAPI, genTime, layersPerEpoch, types.Hash20{}, layerDuration, layerAvgSize, txsPerProposal) + require.NoError(t, activesets.Add(db, ballot1.EpochData.ActiveSetHash, &types.EpochActiveSet{Set: types.ATXIDList{globalAtx.ID(), globalAtx2.ID()}})) t.Cleanup(launchServer(t, cfg, grpcService)) ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) diff --git a/api/grpcserver/mesh_service.go b/api/grpcserver/mesh_service.go index 1c0bec36d2..c8a9a8aa81 100644 --- a/api/grpcserver/mesh_service.go +++ b/api/grpcserver/mesh_service.go @@ -18,6 +18,7 @@ import ( "github.com/spacemeshos/go-spacemesh/datastore" "github.com/spacemeshos/go-spacemesh/events" "github.com/spacemeshos/go-spacemesh/sql" + "github.com/spacemeshos/go-spacemesh/sql/activesets" ) // MeshService exposes mesh data such as accounts, blocks, and transactions. @@ -124,8 +125,6 @@ func (s MeshService) getFilteredTransactions(from types.LayerID, address types.A func (s MeshService) getFilteredActivations(ctx context.Context, startLayer types.LayerID, addr types.Address) (activations []*types.VerifiedActivationTx, err error) { // We have no way to look up activations by coinbase so we have no choice but to read all of them. - // TODO: index activations by layer (and maybe by coinbase) - // See https://github.com/spacemeshos/go-spacemesh/issues/2064. var atxids []types.ATXID for l := startLayer; !l.After(s.mesh.LatestLayer()); l = l.Add(1) { layer, err := s.mesh.GetLayer(l) @@ -133,8 +132,12 @@ func (s MeshService) getFilteredActivations(ctx context.Context, startLayer type return nil, status.Errorf(codes.Internal, "error retrieving layer data") } for _, b := range layer.Ballots() { - if b.EpochData != nil && b.ActiveSet != nil { - atxids = append(atxids, b.ActiveSet...) + if b.EpochData != nil { + actives, err := activesets.Get(s.cdb, b.EpochData.ActiveSetHash) + if err != nil { + return nil, status.Errorf(codes.Internal, "error retrieving active set %s (%s)", b.ID().String(), b.EpochData.ActiveSetHash.ShortString()) + } + atxids = append(atxids, actives.Set...) } } } @@ -334,8 +337,12 @@ func (s MeshService) readLayer(ctx context.Context, layerID types.LayerID, layer } for _, b := range layer.Ballots() { - if b.EpochData != nil && b.ActiveSet != nil { - activations = append(activations, b.ActiveSet...) + if b.EpochData != nil { + actives, err := activesets.Get(s.cdb, b.EpochData.ActiveSetHash) + if err != nil { + return nil, status.Errorf(codes.Internal, "error retrieving active set %s (%s)", b.ID().String(), b.EpochData.ActiveSetHash.ShortString()) + } + activations = append(activations, actives.Set...) } } diff --git a/api/grpcserver/mocks.go b/api/grpcserver/mocks.go index f0c3b13b0d..4f632a778f 100644 --- a/api/grpcserver/mocks.go +++ b/api/grpcserver/mocks.go @@ -1,6 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: ./interface.go - +// +// Generated by this command: +// +// mockgen -typed -package=grpcserver -destination=./mocks.go -source=./interface.go +// // Package grpcserver is a generated GoMock package. package grpcserver @@ -149,7 +153,7 @@ func (m *MockconservativeState) GetBalance(arg0 types.Address) (uint64, error) { } // GetBalance indicates an expected call of GetBalance. -func (mr *MockconservativeStateMockRecorder) GetBalance(arg0 interface{}) *conservativeStateGetBalanceCall { +func (mr *MockconservativeStateMockRecorder) GetBalance(arg0 any) *conservativeStateGetBalanceCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBalance", reflect.TypeOf((*MockconservativeState)(nil).GetBalance), arg0) return &conservativeStateGetBalanceCall{Call: call} @@ -188,7 +192,7 @@ func (m *MockconservativeState) GetLayerStateRoot(arg0 types.LayerID) (types.Has } // GetLayerStateRoot indicates an expected call of GetLayerStateRoot. -func (mr *MockconservativeStateMockRecorder) GetLayerStateRoot(arg0 interface{}) *conservativeStateGetLayerStateRootCall { +func (mr *MockconservativeStateMockRecorder) GetLayerStateRoot(arg0 any) *conservativeStateGetLayerStateRootCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLayerStateRoot", reflect.TypeOf((*MockconservativeState)(nil).GetLayerStateRoot), arg0) return &conservativeStateGetLayerStateRootCall{Call: call} @@ -227,7 +231,7 @@ func (m *MockconservativeState) GetMeshTransaction(arg0 types.TransactionID) (*t } // GetMeshTransaction indicates an expected call of GetMeshTransaction. -func (mr *MockconservativeStateMockRecorder) GetMeshTransaction(arg0 interface{}) *conservativeStateGetMeshTransactionCall { +func (mr *MockconservativeStateMockRecorder) GetMeshTransaction(arg0 any) *conservativeStateGetMeshTransactionCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMeshTransaction", reflect.TypeOf((*MockconservativeState)(nil).GetMeshTransaction), arg0) return &conservativeStateGetMeshTransactionCall{Call: call} @@ -266,7 +270,7 @@ func (m *MockconservativeState) GetMeshTransactions(arg0 []types.TransactionID) } // GetMeshTransactions indicates an expected call of GetMeshTransactions. -func (mr *MockconservativeStateMockRecorder) GetMeshTransactions(arg0 interface{}) *conservativeStateGetMeshTransactionsCall { +func (mr *MockconservativeStateMockRecorder) GetMeshTransactions(arg0 any) *conservativeStateGetMeshTransactionsCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMeshTransactions", reflect.TypeOf((*MockconservativeState)(nil).GetMeshTransactions), arg0) return &conservativeStateGetMeshTransactionsCall{Call: call} @@ -305,7 +309,7 @@ func (m *MockconservativeState) GetNonce(arg0 types.Address) (types.Nonce, error } // GetNonce indicates an expected call of GetNonce. -func (mr *MockconservativeStateMockRecorder) GetNonce(arg0 interface{}) *conservativeStateGetNonceCall { +func (mr *MockconservativeStateMockRecorder) GetNonce(arg0 any) *conservativeStateGetNonceCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNonce", reflect.TypeOf((*MockconservativeState)(nil).GetNonce), arg0) return &conservativeStateGetNonceCall{Call: call} @@ -344,7 +348,7 @@ func (m *MockconservativeState) GetProjection(arg0 types.Address) (uint64, uint6 } // GetProjection indicates an expected call of GetProjection. -func (mr *MockconservativeStateMockRecorder) GetProjection(arg0 interface{}) *conservativeStateGetProjectionCall { +func (mr *MockconservativeStateMockRecorder) GetProjection(arg0 any) *conservativeStateGetProjectionCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetProjection", reflect.TypeOf((*MockconservativeState)(nil).GetProjection), arg0) return &conservativeStateGetProjectionCall{Call: call} @@ -422,7 +426,7 @@ func (m *MockconservativeState) GetTransactionsByAddress(arg0, arg1 types.LayerI } // GetTransactionsByAddress indicates an expected call of GetTransactionsByAddress. -func (mr *MockconservativeStateMockRecorder) GetTransactionsByAddress(arg0, arg1, arg2 interface{}) *conservativeStateGetTransactionsByAddressCall { +func (mr *MockconservativeStateMockRecorder) GetTransactionsByAddress(arg0, arg1, arg2 any) *conservativeStateGetTransactionsByAddressCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTransactionsByAddress", reflect.TypeOf((*MockconservativeState)(nil).GetTransactionsByAddress), arg0, arg1, arg2) return &conservativeStateGetTransactionsByAddressCall{Call: call} @@ -460,7 +464,7 @@ func (m *MockconservativeState) Validation(raw types.RawTx) system.ValidationReq } // Validation indicates an expected call of Validation. -func (mr *MockconservativeStateMockRecorder) Validation(raw interface{}) *conservativeStateValidationCall { +func (mr *MockconservativeStateMockRecorder) Validation(raw any) *conservativeStateValidationCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Validation", reflect.TypeOf((*MockconservativeState)(nil).Validation), raw) return &conservativeStateValidationCall{Call: call} @@ -521,7 +525,7 @@ func (m *Mocksyncer) IsSynced(arg0 context.Context) bool { } // IsSynced indicates an expected call of IsSynced. -func (mr *MocksyncerMockRecorder) IsSynced(arg0 interface{}) *syncerIsSyncedCall { +func (mr *MocksyncerMockRecorder) IsSynced(arg0 any) *syncerIsSyncedCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsSynced", reflect.TypeOf((*Mocksyncer)(nil).IsSynced), arg0) return &syncerIsSyncedCall{Call: call} @@ -582,7 +586,7 @@ func (m *MocktxValidator) VerifyAndCacheTx(arg0 context.Context, arg1 []byte) er } // VerifyAndCacheTx indicates an expected call of VerifyAndCacheTx. -func (mr *MocktxValidatorMockRecorder) VerifyAndCacheTx(arg0, arg1 interface{}) *txValidatorVerifyAndCacheTxCall { +func (mr *MocktxValidatorMockRecorder) VerifyAndCacheTx(arg0, arg1 any) *txValidatorVerifyAndCacheTxCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "VerifyAndCacheTx", reflect.TypeOf((*MocktxValidator)(nil).VerifyAndCacheTx), arg0, arg1) return &txValidatorVerifyAndCacheTxCall{Call: call} @@ -644,7 +648,7 @@ func (m *MockatxProvider) GetFullAtx(id types.ATXID) (*types.VerifiedActivationT } // GetFullAtx indicates an expected call of GetFullAtx. -func (mr *MockatxProviderMockRecorder) GetFullAtx(id interface{}) *atxProviderGetFullAtxCall { +func (mr *MockatxProviderMockRecorder) GetFullAtx(id any) *atxProviderGetFullAtxCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetFullAtx", reflect.TypeOf((*MockatxProvider)(nil).GetFullAtx), id) return &atxProviderGetFullAtxCall{Call: call} @@ -683,7 +687,7 @@ func (m *MockatxProvider) GetMalfeasanceProof(id types.NodeID) (*types.Malfeasan } // GetMalfeasanceProof indicates an expected call of GetMalfeasanceProof. -func (mr *MockatxProviderMockRecorder) GetMalfeasanceProof(id interface{}) *atxProviderGetMalfeasanceProofCall { +func (mr *MockatxProviderMockRecorder) GetMalfeasanceProof(id any) *atxProviderGetMalfeasanceProofCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMalfeasanceProof", reflect.TypeOf((*MockatxProvider)(nil).GetMalfeasanceProof), id) return &atxProviderGetMalfeasanceProofCall{Call: call} @@ -784,7 +788,7 @@ func (m *MockpostSetupProvider) Benchmark(p activation.PostSetupProvider) (int, } // Benchmark indicates an expected call of Benchmark. -func (mr *MockpostSetupProviderMockRecorder) Benchmark(p interface{}) *postSetupProviderBenchmarkCall { +func (mr *MockpostSetupProviderMockRecorder) Benchmark(p any) *postSetupProviderBenchmarkCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Benchmark", reflect.TypeOf((*MockpostSetupProvider)(nil).Benchmark), p) return &postSetupProviderBenchmarkCall{Call: call} @@ -1021,7 +1025,7 @@ func (m *Mockpeers) ConnectedPeerInfo(arg0 p2p.Peer) *p2p.PeerInfo { } // ConnectedPeerInfo indicates an expected call of ConnectedPeerInfo. -func (mr *MockpeersMockRecorder) ConnectedPeerInfo(arg0 interface{}) *peersConnectedPeerInfoCall { +func (mr *MockpeersMockRecorder) ConnectedPeerInfo(arg0 any) *peersConnectedPeerInfoCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ConnectedPeerInfo", reflect.TypeOf((*Mockpeers)(nil).ConnectedPeerInfo), arg0) return &peersConnectedPeerInfoCall{Call: call} @@ -1220,7 +1224,7 @@ func (m *MockmeshAPI) GetATXs(arg0 context.Context, arg1 []types.ATXID) (map[typ } // GetATXs indicates an expected call of GetATXs. -func (mr *MockmeshAPIMockRecorder) GetATXs(arg0, arg1 interface{}) *meshAPIGetATXsCall { +func (mr *MockmeshAPIMockRecorder) GetATXs(arg0, arg1 any) *meshAPIGetATXsCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetATXs", reflect.TypeOf((*MockmeshAPI)(nil).GetATXs), arg0, arg1) return &meshAPIGetATXsCall{Call: call} @@ -1259,7 +1263,7 @@ func (m *MockmeshAPI) GetLayer(arg0 types.LayerID) (*types.Layer, error) { } // GetLayer indicates an expected call of GetLayer. -func (mr *MockmeshAPIMockRecorder) GetLayer(arg0 interface{}) *meshAPIGetLayerCall { +func (mr *MockmeshAPIMockRecorder) GetLayer(arg0 any) *meshAPIGetLayerCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLayer", reflect.TypeOf((*MockmeshAPI)(nil).GetLayer), arg0) return &meshAPIGetLayerCall{Call: call} @@ -1298,7 +1302,7 @@ func (m *MockmeshAPI) GetRewards(arg0 types.Address) ([]*types.Reward, error) { } // GetRewards indicates an expected call of GetRewards. -func (mr *MockmeshAPIMockRecorder) GetRewards(arg0 interface{}) *meshAPIGetRewardsCall { +func (mr *MockmeshAPIMockRecorder) GetRewards(arg0 any) *meshAPIGetRewardsCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRewards", reflect.TypeOf((*MockmeshAPI)(nil).GetRewards), arg0) return &meshAPIGetRewardsCall{Call: call} @@ -1413,7 +1417,7 @@ func (m *MockmeshAPI) MeshHash(arg0 types.LayerID) (types.Hash32, error) { } // MeshHash indicates an expected call of MeshHash. -func (mr *MockmeshAPIMockRecorder) MeshHash(arg0 interface{}) *meshAPIMeshHashCall { +func (mr *MockmeshAPIMockRecorder) MeshHash(arg0 any) *meshAPIMeshHashCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MeshHash", reflect.TypeOf((*MockmeshAPI)(nil).MeshHash), arg0) return &meshAPIMeshHashCall{Call: call} @@ -1513,7 +1517,7 @@ func (m *Mockoracle) ActiveSet(arg0 context.Context, arg1 types.EpochID) ([]type } // ActiveSet indicates an expected call of ActiveSet. -func (mr *MockoracleMockRecorder) ActiveSet(arg0, arg1 interface{}) *oracleActiveSetCall { +func (mr *MockoracleMockRecorder) ActiveSet(arg0, arg1 any) *oracleActiveSetCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ActiveSet", reflect.TypeOf((*Mockoracle)(nil).ActiveSet), arg0, arg1) return &oracleActiveSetCall{Call: call} diff --git a/beacon/mocks.go b/beacon/mocks.go index 94bdfd3e9d..9d62418cf4 100644 --- a/beacon/mocks.go +++ b/beacon/mocks.go @@ -1,6 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: ./interface.go - +// +// Generated by this command: +// +// mockgen -typed -package=beacon -destination=./mocks.go -source=./interface.go +// // Package beacon is a generated GoMock package. package beacon @@ -44,7 +48,7 @@ func (m *Mockcoin) FinishEpoch(arg0 context.Context, arg1 types.EpochID) { } // FinishEpoch indicates an expected call of FinishEpoch. -func (mr *MockcoinMockRecorder) FinishEpoch(arg0, arg1 interface{}) *coinFinishEpochCall { +func (mr *MockcoinMockRecorder) FinishEpoch(arg0, arg1 any) *coinFinishEpochCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FinishEpoch", reflect.TypeOf((*Mockcoin)(nil).FinishEpoch), arg0, arg1) return &coinFinishEpochCall{Call: call} @@ -80,7 +84,7 @@ func (m *Mockcoin) FinishRound(arg0 context.Context) { } // FinishRound indicates an expected call of FinishRound. -func (mr *MockcoinMockRecorder) FinishRound(arg0 interface{}) *coinFinishRoundCall { +func (mr *MockcoinMockRecorder) FinishRound(arg0 any) *coinFinishRoundCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FinishRound", reflect.TypeOf((*Mockcoin)(nil).FinishRound), arg0) return &coinFinishRoundCall{Call: call} @@ -119,7 +123,7 @@ func (m *Mockcoin) Get(arg0 context.Context, arg1 types.EpochID, arg2 types.Roun } // Get indicates an expected call of Get. -func (mr *MockcoinMockRecorder) Get(arg0, arg1, arg2 interface{}) *coinGetCall { +func (mr *MockcoinMockRecorder) Get(arg0, arg1, arg2 any) *coinGetCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*Mockcoin)(nil).Get), arg0, arg1, arg2) return &coinGetCall{Call: call} @@ -157,7 +161,7 @@ func (m *Mockcoin) HandleProposal(arg0 context.Context, arg1 p2p.Peer, arg2 []by } // HandleProposal indicates an expected call of HandleProposal. -func (mr *MockcoinMockRecorder) HandleProposal(arg0, arg1, arg2 interface{}) *coinHandleProposalCall { +func (mr *MockcoinMockRecorder) HandleProposal(arg0, arg1, arg2 any) *coinHandleProposalCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HandleProposal", reflect.TypeOf((*Mockcoin)(nil).HandleProposal), arg0, arg1, arg2) return &coinHandleProposalCall{Call: call} @@ -193,7 +197,7 @@ func (m *Mockcoin) StartEpoch(arg0 context.Context, arg1 types.EpochID) { } // StartEpoch indicates an expected call of StartEpoch. -func (mr *MockcoinMockRecorder) StartEpoch(arg0, arg1 interface{}) *coinStartEpochCall { +func (mr *MockcoinMockRecorder) StartEpoch(arg0, arg1 any) *coinStartEpochCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StartEpoch", reflect.TypeOf((*Mockcoin)(nil).StartEpoch), arg0, arg1) return &coinStartEpochCall{Call: call} @@ -229,7 +233,7 @@ func (m *Mockcoin) StartRound(arg0 context.Context, arg1 types.RoundID, arg2 *ty } // StartRound indicates an expected call of StartRound. -func (mr *MockcoinMockRecorder) StartRound(arg0, arg1, arg2 interface{}) *coinStartRoundCall { +func (mr *MockcoinMockRecorder) StartRound(arg0, arg1, arg2 any) *coinStartRoundCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StartRound", reflect.TypeOf((*Mockcoin)(nil).StartRound), arg0, arg1, arg2) return &coinStartRoundCall{Call: call} @@ -290,7 +294,7 @@ func (m *MockeligibilityChecker) PassStrictThreshold(arg0 types.VrfSignature) bo } // PassStrictThreshold indicates an expected call of PassStrictThreshold. -func (mr *MockeligibilityCheckerMockRecorder) PassStrictThreshold(arg0 interface{}) *eligibilityCheckerPassStrictThresholdCall { +func (mr *MockeligibilityCheckerMockRecorder) PassStrictThreshold(arg0 any) *eligibilityCheckerPassStrictThresholdCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PassStrictThreshold", reflect.TypeOf((*MockeligibilityChecker)(nil).PassStrictThreshold), arg0) return &eligibilityCheckerPassStrictThresholdCall{Call: call} @@ -328,7 +332,7 @@ func (m *MockeligibilityChecker) PassThreshold(arg0 types.VrfSignature) bool { } // PassThreshold indicates an expected call of PassThreshold. -func (mr *MockeligibilityCheckerMockRecorder) PassThreshold(arg0 interface{}) *eligibilityCheckerPassThresholdCall { +func (mr *MockeligibilityCheckerMockRecorder) PassThreshold(arg0 any) *eligibilityCheckerPassThresholdCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PassThreshold", reflect.TypeOf((*MockeligibilityChecker)(nil).PassThreshold), arg0) return &eligibilityCheckerPassThresholdCall{Call: call} @@ -389,7 +393,7 @@ func (m *MocklayerClock) AwaitLayer(arg0 types.LayerID) <-chan struct{} { } // AwaitLayer indicates an expected call of AwaitLayer. -func (mr *MocklayerClockMockRecorder) AwaitLayer(arg0 interface{}) *layerClockAwaitLayerCall { +func (mr *MocklayerClockMockRecorder) AwaitLayer(arg0 any) *layerClockAwaitLayerCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AwaitLayer", reflect.TypeOf((*MocklayerClock)(nil).AwaitLayer), arg0) return &layerClockAwaitLayerCall{Call: call} @@ -465,7 +469,7 @@ func (m *MocklayerClock) LayerToTime(arg0 types.LayerID) time.Time { } // LayerToTime indicates an expected call of LayerToTime. -func (mr *MocklayerClockMockRecorder) LayerToTime(arg0 interface{}) *layerClockLayerToTimeCall { +func (mr *MocklayerClockMockRecorder) LayerToTime(arg0 any) *layerClockLayerToTimeCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LayerToTime", reflect.TypeOf((*MocklayerClock)(nil).LayerToTime), arg0) return &layerClockLayerToTimeCall{Call: call} @@ -602,7 +606,7 @@ func (m *MockvrfSigner) Sign(msg []byte) types.VrfSignature { } // Sign indicates an expected call of Sign. -func (mr *MockvrfSignerMockRecorder) Sign(msg interface{}) *vrfSignerSignCall { +func (mr *MockvrfSignerMockRecorder) Sign(msg any) *vrfSignerSignCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Sign", reflect.TypeOf((*MockvrfSigner)(nil).Sign), msg) return &vrfSignerSignCall{Call: call} @@ -663,7 +667,7 @@ func (m *MockvrfVerifier) Verify(nodeID types.NodeID, msg []byte, sig types.VrfS } // Verify indicates an expected call of Verify. -func (mr *MockvrfVerifierMockRecorder) Verify(nodeID, msg, sig interface{}) *vrfVerifierVerifyCall { +func (mr *MockvrfVerifierMockRecorder) Verify(nodeID, msg, sig any) *vrfVerifierVerifyCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Verify", reflect.TypeOf((*MockvrfVerifier)(nil).Verify), nodeID, msg, sig) return &vrfVerifierVerifyCall{Call: call} @@ -725,7 +729,7 @@ func (m *MocknonceFetcher) VRFNonce(arg0 types.NodeID, arg1 types.EpochID) (type } // VRFNonce indicates an expected call of VRFNonce. -func (mr *MocknonceFetcherMockRecorder) VRFNonce(arg0, arg1 interface{}) *nonceFetcherVRFNonceCall { +func (mr *MocknonceFetcherMockRecorder) VRFNonce(arg0, arg1 any) *nonceFetcherVRFNonceCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "VRFNonce", reflect.TypeOf((*MocknonceFetcher)(nil).VRFNonce), arg0, arg1) return &nonceFetcherVRFNonceCall{Call: call} diff --git a/beacon/weakcoin/mocks.go b/beacon/weakcoin/mocks.go index 5cc05a37f9..1bc89bc68f 100644 --- a/beacon/weakcoin/mocks.go +++ b/beacon/weakcoin/mocks.go @@ -1,6 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: ./interface.go - +// +// Generated by this command: +// +// mockgen -typed -package=weakcoin -destination=./mocks.go -source=./interface.go +// // Package weakcoin is a generated GoMock package. package weakcoin @@ -119,7 +123,7 @@ func (m *MockvrfSigner) Sign(msg []byte) types.VrfSignature { } // Sign indicates an expected call of Sign. -func (mr *MockvrfSignerMockRecorder) Sign(msg interface{}) *vrfSignerSignCall { +func (mr *MockvrfSignerMockRecorder) Sign(msg any) *vrfSignerSignCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Sign", reflect.TypeOf((*MockvrfSigner)(nil).Sign), msg) return &vrfSignerSignCall{Call: call} @@ -180,7 +184,7 @@ func (m *MockvrfVerifier) Verify(nodeID types.NodeID, msg []byte, sig types.VrfS } // Verify indicates an expected call of Verify. -func (mr *MockvrfVerifierMockRecorder) Verify(nodeID, msg, sig interface{}) *vrfVerifierVerifyCall { +func (mr *MockvrfVerifierMockRecorder) Verify(nodeID, msg, sig any) *vrfVerifierVerifyCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Verify", reflect.TypeOf((*MockvrfVerifier)(nil).Verify), nodeID, msg, sig) return &vrfVerifierVerifyCall{Call: call} @@ -242,7 +246,7 @@ func (m *MocknonceFetcher) VRFNonce(arg0 types.NodeID, arg1 types.EpochID) (type } // VRFNonce indicates an expected call of VRFNonce. -func (mr *MocknonceFetcherMockRecorder) VRFNonce(arg0, arg1 interface{}) *nonceFetcherVRFNonceCall { +func (mr *MocknonceFetcherMockRecorder) VRFNonce(arg0, arg1 any) *nonceFetcherVRFNonceCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "VRFNonce", reflect.TypeOf((*MocknonceFetcher)(nil).VRFNonce), arg0, arg1) return &nonceFetcherVRFNonceCall{Call: call} @@ -303,7 +307,7 @@ func (m *Mockallowance) MinerAllowance(arg0 types.EpochID, arg1 types.NodeID) ui } // MinerAllowance indicates an expected call of MinerAllowance. -func (mr *MockallowanceMockRecorder) MinerAllowance(arg0, arg1 interface{}) *allowanceMinerAllowanceCall { +func (mr *MockallowanceMockRecorder) MinerAllowance(arg0, arg1 any) *allowanceMinerAllowanceCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MinerAllowance", reflect.TypeOf((*Mockallowance)(nil).MinerAllowance), arg0, arg1) return &allowanceMinerAllowanceCall{Call: call} diff --git a/blocks/generator.go b/blocks/generator.go index 21cc9ba476..3d5e389bd9 100644 --- a/blocks/generator.go +++ b/blocks/generator.go @@ -167,12 +167,6 @@ func (g *Generator) run() error { if len(g.optimisticOutput) > 0 { g.processOptimisticLayers(maxLayer) } - if err := proposals.Delete(g.cdb, out.Layer); err != nil { - g.logger.With().Error("failed to delete old proposals", - out.Layer, - log.Err(err), - ) - } case <-time.After(g.cfg.GenBlockInterval): if len(g.optimisticOutput) > 0 { g.processOptimisticLayers(maxLayer) diff --git a/blocks/generator_test.go b/blocks/generator_test.go index 6866363f2f..678438589d 100644 --- a/blocks/generator_test.go +++ b/blocks/generator_test.go @@ -25,6 +25,7 @@ import ( "github.com/spacemeshos/go-spacemesh/log/logtest" "github.com/spacemeshos/go-spacemesh/signing" "github.com/spacemeshos/go-spacemesh/sql" + "github.com/spacemeshos/go-spacemesh/sql/activesets" "github.com/spacemeshos/go-spacemesh/sql/atxs" "github.com/spacemeshos/go-spacemesh/sql/ballots" "github.com/spacemeshos/go-spacemesh/sql/layers" @@ -69,6 +70,7 @@ func createTestGenerator(t *testing.T) *testGenerator { mockCert: mocks.NewMockcertifier(ctrl), mockPatrol: mocks.NewMocklayerPatrol(ctrl), } + tg.mockMesh.EXPECT().ProcessedLayer().Return(types.LayerID(1)).AnyTimes() lg := logtest.New(t) cdb := datastore.NewCachedDB(sql.InMemory(), lg) tg.Generator = NewGenerator(cdb, tg.mockExec, tg.mockMesh, tg.mockFetch, tg.mockCert, tg.mockPatrol, @@ -191,10 +193,10 @@ func createProposal( EpochData: &types.EpochData{ Beacon: types.RandomBeacon(), EligibilityCount: uint32(layerSize * epochSize / len(activeSet)), + ActiveSetHash: activeSet.Hash(), }, }, EligibilityProofs: make([]types.VotingEligibility, numEligibility), - ActiveSet: activeSet, }, TxIDs: txIDs, MeshHash: meshHash, @@ -206,6 +208,7 @@ func createProposal( require.NoError(t, p.Initialize()) require.NoError(t, ballots.Add(db, &p.Ballot)) require.NoError(t, proposals.Add(db, p)) + activesets.Add(db, activeSet.Hash(), &types.EpochActiveSet{Set: activeSet}) return p } @@ -325,7 +328,11 @@ func Test_run(t *testing.T) { t.Run(tc.desc, func(t *testing.T) { tg := createTestGenerator(t) tg.cfg.BlockGasLimit = tc.gasLimit + tg.mockMesh = mocks.NewMockmeshProvider(gomock.NewController(t)) + tg.msh = tg.mockMesh layerID := types.GetEffectiveGenesis().Add(100) + processed := layerID - 1 + tg.mockMesh.EXPECT().ProcessedLayer().DoAndReturn(func() types.LayerID { return processed }).AnyTimes() require.NoError(t, layers.SetApplied(tg.cdb, layerID-1, types.EmptyBlockID)) var meshHash types.Hash32 if tc.optimistic { @@ -337,17 +344,7 @@ func Test_run(t *testing.T) { txIDs := createAndSaveTxs(t, numTXs, tg.cdb) signers, atxes := createATXs(t, tg.cdb, (layerID.GetEpoch() - 1).FirstLayer(), numProposals) activeSet := types.ToATXIDs(atxes) - // generate some proposals before this layer - oldest := layerID - 10 - for lid := oldest; lid < layerID; lid++ { - createProposals(t, tg.cdb, lid, types.EmptyLayerHash, signers, activeSet, txIDs) - } plist := createProposals(t, tg.cdb, layerID, meshHash, signers, activeSet, txIDs) - for lid := oldest; lid <= layerID; lid++ { - got, err := proposals.GetByLayer(tg.cdb, lid) - require.NoError(t, err) - require.Len(t, got, len(signers)) - } pids := types.ToProposalIDs(plist) tg.mockFetch.EXPECT().GetProposals(gomock.Any(), pids) @@ -398,6 +395,7 @@ func Test_run(t *testing.T) { tg.mockMesh.EXPECT().ProcessLayerPerHareOutput(gomock.Any(), layerID, gomock.Any(), tc.optimistic).DoAndReturn( func(_ context.Context, _ types.LayerID, got types.BlockID, _ bool) error { require.Equal(t, block.ID(), got) + processed = layerID return nil }) tg.mockPatrol.EXPECT().CompleteHare(layerID) @@ -405,13 +403,6 @@ func Test_run(t *testing.T) { tg.hareCh <- hare.LayerOutput{Ctx: context.Background(), Layer: layerID, Proposals: pids} require.Eventually(t, func() bool { return len(tg.hareCh) == 0 }, time.Second, 100*time.Millisecond) tg.Stop() - for lid := oldest; lid < layerID; lid++ { - _, err := proposals.GetByLayer(tg.cdb, lid) - require.ErrorIs(t, err, sql.ErrNotFound) - } - got, err := proposals.GetByLayer(tg.cdb, layerID) - require.NoError(t, err) - require.Len(t, got, len(signers)) }) } } diff --git a/blocks/interface.go b/blocks/interface.go index 84f0a8787e..05c686e49b 100644 --- a/blocks/interface.go +++ b/blocks/interface.go @@ -14,6 +14,7 @@ type layerPatrol interface { } type meshProvider interface { + ProcessedLayer() types.LayerID AddBlockWithTXs(context.Context, *types.Block) error ProcessLayerPerHareOutput(context.Context, types.LayerID, types.BlockID, bool) error } diff --git a/blocks/mocks/mocks.go b/blocks/mocks/mocks.go index 2bc31816d0..82f8fa08f9 100644 --- a/blocks/mocks/mocks.go +++ b/blocks/mocks/mocks.go @@ -1,6 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: ./interface.go - +// +// Generated by this command: +// +// mockgen -typed -package=mocks -destination=./mocks/mocks.go -source=./interface.go +// // Package mocks is a generated GoMock package. package mocks @@ -43,7 +47,7 @@ func (m *MocklayerPatrol) CompleteHare(arg0 types.LayerID) { } // CompleteHare indicates an expected call of CompleteHare. -func (mr *MocklayerPatrolMockRecorder) CompleteHare(arg0 interface{}) *layerPatrolCompleteHareCall { +func (mr *MocklayerPatrolMockRecorder) CompleteHare(arg0 any) *layerPatrolCompleteHareCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CompleteHare", reflect.TypeOf((*MocklayerPatrol)(nil).CompleteHare), arg0) return &layerPatrolCompleteHareCall{Call: call} @@ -104,7 +108,7 @@ func (m *MockmeshProvider) AddBlockWithTXs(arg0 context.Context, arg1 *types.Blo } // AddBlockWithTXs indicates an expected call of AddBlockWithTXs. -func (mr *MockmeshProviderMockRecorder) AddBlockWithTXs(arg0, arg1 interface{}) *meshProviderAddBlockWithTXsCall { +func (mr *MockmeshProviderMockRecorder) AddBlockWithTXs(arg0, arg1 any) *meshProviderAddBlockWithTXsCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddBlockWithTXs", reflect.TypeOf((*MockmeshProvider)(nil).AddBlockWithTXs), arg0, arg1) return &meshProviderAddBlockWithTXsCall{Call: call} @@ -142,7 +146,7 @@ func (m *MockmeshProvider) ProcessLayerPerHareOutput(arg0 context.Context, arg1 } // ProcessLayerPerHareOutput indicates an expected call of ProcessLayerPerHareOutput. -func (mr *MockmeshProviderMockRecorder) ProcessLayerPerHareOutput(arg0, arg1, arg2, arg3 interface{}) *meshProviderProcessLayerPerHareOutputCall { +func (mr *MockmeshProviderMockRecorder) ProcessLayerPerHareOutput(arg0, arg1, arg2, arg3 any) *meshProviderProcessLayerPerHareOutputCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProcessLayerPerHareOutput", reflect.TypeOf((*MockmeshProvider)(nil).ProcessLayerPerHareOutput), arg0, arg1, arg2, arg3) return &meshProviderProcessLayerPerHareOutputCall{Call: call} @@ -171,6 +175,44 @@ func (c *meshProviderProcessLayerPerHareOutputCall) DoAndReturn(f func(context.C return c } +// ProcessedLayer mocks base method. +func (m *MockmeshProvider) ProcessedLayer() types.LayerID { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ProcessedLayer") + ret0, _ := ret[0].(types.LayerID) + return ret0 +} + +// ProcessedLayer indicates an expected call of ProcessedLayer. +func (mr *MockmeshProviderMockRecorder) ProcessedLayer() *meshProviderProcessedLayerCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProcessedLayer", reflect.TypeOf((*MockmeshProvider)(nil).ProcessedLayer)) + return &meshProviderProcessedLayerCall{Call: call} +} + +// meshProviderProcessedLayerCall wrap *gomock.Call +type meshProviderProcessedLayerCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *meshProviderProcessedLayerCall) Return(arg0 types.LayerID) *meshProviderProcessedLayerCall { + c.Call = c.Call.Return(arg0) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *meshProviderProcessedLayerCall) Do(f func() types.LayerID) *meshProviderProcessedLayerCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *meshProviderProcessedLayerCall) DoAndReturn(f func() types.LayerID) *meshProviderProcessedLayerCall { + c.Call = c.Call.DoAndReturn(f) + return c +} + // Mockexecutor is a mock of executor interface. type Mockexecutor struct { ctrl *gomock.Controller @@ -204,7 +246,7 @@ func (m *Mockexecutor) ExecuteOptimistic(arg0 context.Context, arg1 types.LayerI } // ExecuteOptimistic indicates an expected call of ExecuteOptimistic. -func (mr *MockexecutorMockRecorder) ExecuteOptimistic(arg0, arg1, arg2, arg3, arg4 interface{}) *executorExecuteOptimisticCall { +func (mr *MockexecutorMockRecorder) ExecuteOptimistic(arg0, arg1, arg2, arg3, arg4 any) *executorExecuteOptimisticCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExecuteOptimistic", reflect.TypeOf((*Mockexecutor)(nil).ExecuteOptimistic), arg0, arg1, arg2, arg3, arg4) return &executorExecuteOptimisticCall{Call: call} @@ -265,7 +307,7 @@ func (m *MocklayerClock) AwaitLayer(layerID types.LayerID) <-chan struct{} { } // AwaitLayer indicates an expected call of AwaitLayer. -func (mr *MocklayerClockMockRecorder) AwaitLayer(layerID interface{}) *layerClockAwaitLayerCall { +func (mr *MocklayerClockMockRecorder) AwaitLayer(layerID any) *layerClockAwaitLayerCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AwaitLayer", reflect.TypeOf((*MocklayerClock)(nil).AwaitLayer), layerID) return &layerClockAwaitLayerCall{Call: call} @@ -364,7 +406,7 @@ func (m *Mockcertifier) CertifyIfEligible(arg0 context.Context, arg1 log.Log, ar } // CertifyIfEligible indicates an expected call of CertifyIfEligible. -func (mr *MockcertifierMockRecorder) CertifyIfEligible(arg0, arg1, arg2, arg3 interface{}) *certifierCertifyIfEligibleCall { +func (mr *MockcertifierMockRecorder) CertifyIfEligible(arg0, arg1, arg2, arg3 any) *certifierCertifyIfEligibleCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CertifyIfEligible", reflect.TypeOf((*Mockcertifier)(nil).CertifyIfEligible), arg0, arg1, arg2, arg3) return &certifierCertifyIfEligibleCall{Call: call} @@ -402,7 +444,7 @@ func (m *Mockcertifier) RegisterForCert(arg0 context.Context, arg1 types.LayerID } // RegisterForCert indicates an expected call of RegisterForCert. -func (mr *MockcertifierMockRecorder) RegisterForCert(arg0, arg1, arg2 interface{}) *certifierRegisterForCertCall { +func (mr *MockcertifierMockRecorder) RegisterForCert(arg0, arg1, arg2 any) *certifierRegisterForCertCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterForCert", reflect.TypeOf((*Mockcertifier)(nil).RegisterForCert), arg0, arg1, arg2) return &certifierRegisterForCertCall{Call: call} @@ -463,7 +505,7 @@ func (m *MocktortoiseProvider) GetMissingActiveSet(arg0 types.EpochID, arg1 []ty } // GetMissingActiveSet indicates an expected call of GetMissingActiveSet. -func (mr *MocktortoiseProviderMockRecorder) GetMissingActiveSet(arg0, arg1 interface{}) *tortoiseProviderGetMissingActiveSetCall { +func (mr *MocktortoiseProviderMockRecorder) GetMissingActiveSet(arg0, arg1 any) *tortoiseProviderGetMissingActiveSetCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMissingActiveSet", reflect.TypeOf((*MocktortoiseProvider)(nil).GetMissingActiveSet), arg0, arg1) return &tortoiseProviderGetMissingActiveSetCall{Call: call} diff --git a/blocks/utils.go b/blocks/utils.go index b75e1e8194..177c989154 100644 --- a/blocks/utils.go +++ b/blocks/utils.go @@ -68,14 +68,10 @@ func getProposalMetadata( if err != nil { return nil, err } - upgrade := lid.Uint32() >= types.OpUpgradeLayer() total := 0 for _, p := range proposals { key := p.MeshHash - cnt := 1 - if upgrade { - cnt = len(p.EligibilityProofs) - } + cnt := len(p.EligibilityProofs) total += cnt if _, ok := meshHashes[key]; !ok { meshHashes[key] = &meshState{ diff --git a/blocks/utils_test.go b/blocks/utils_test.go index f9bc11f066..6a9a6ea742 100644 --- a/blocks/utils_test.go +++ b/blocks/utils_test.go @@ -13,6 +13,7 @@ import ( "github.com/spacemeshos/go-spacemesh/log/logtest" "github.com/spacemeshos/go-spacemesh/signing" "github.com/spacemeshos/go-spacemesh/sql" + "github.com/spacemeshos/go-spacemesh/sql/activesets" "github.com/spacemeshos/go-spacemesh/sql/layers" ) @@ -103,7 +104,7 @@ func Test_getProposalMetadata(t *testing.T) { cfg := Config{OptFilterThreshold: 70} lid := types.LayerID(111) _, atxs := createATXs(t, cdb, (lid.GetEpoch() - 1).FirstLayer(), 10) - actives := types.ToATXIDs(atxs) + actives := types.ATXIDList(types.ToATXIDs(atxs)) props := make([]*types.Proposal, 0, 10) hash1 := types.Hash32{1, 2, 3} hash2 := types.Hash32{3, 2, 1} @@ -119,21 +120,19 @@ func Test_getProposalMetadata(t *testing.T) { for j := 0; j <= i; j++ { p.EligibilityProofs = append(p.EligibilityProofs, types.VotingEligibility{J: uint32(j + 1)}) } - p.EpochData = &types.EpochData{} - p.ActiveSet = actives + p.EpochData = &types.EpochData{ActiveSetHash: actives.Hash()} p.EpochData.EligibilityCount = uint32(i + 1) props = append(props, &p) } + require.NoError(t, activesets.Add(cdb, actives.Hash(), &types.EpochActiveSet{ + Epoch: lid.GetEpoch(), + Set: actives, + })) require.NoError(t, layers.SetMeshHash(cdb, lid-1, hash2)) - types.SetOpUpgradeLayer(lid.Uint32() + 1) - // only 5 / 10 proposals has the same state, threshold is 70 + // only 5 / 10 proposals has the same state + // eligibility wise 40 / 55 has the same state md, err := getProposalMetadata(context.Background(), lg, cdb, cfg, lid, props) require.NoError(t, err) - require.False(t, md.optFilter) - // eligibility wise 40 / 55 has the same state, threshold is 70 - types.SetOpUpgradeLayer(0) - md, err = getProposalMetadata(context.Background(), lg, cdb, cfg, lid, props) - require.NoError(t, err) require.True(t, md.optFilter) } diff --git a/bootstrap/mocks.go b/bootstrap/mocks.go index dd77862a21..be79259865 100644 --- a/bootstrap/mocks.go +++ b/bootstrap/mocks.go @@ -1,6 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: ./interface.go - +// +// Generated by this command: +// +// mockgen -typed -package=bootstrap -destination=./mocks.go -source=./interface.go +// // Package bootstrap is a generated GoMock package. package bootstrap diff --git a/bootstrap/updater.go b/bootstrap/updater.go index 7062975093..bda9b759b5 100644 --- a/bootstrap/updater.go +++ b/bootstrap/updater.go @@ -24,7 +24,6 @@ import ( "os" "path/filepath" "strconv" - "strings" "sync" "time" @@ -420,33 +419,6 @@ func validateData(cfg Config, update *Update) (*VerifiedUpdate, error) { return verified, nil } -func renameLegacyFile(fs afero.Fs, path string) string { - var idx int - for _, suffix := range []string{SuffixBoostrap, SuffixBeacon, SuffixActiveSet} { - if strings.HasSuffix(path, suffix) { - return path - } - } - for _, suffix := range []string{SuffixBoostrap, SuffixBeacon, SuffixActiveSet} { - idx = strings.Index(path, fmt.Sprintf("-%s-", suffix)) - if idx > -1 { - break - } - } - if idx < 0 { - return "" - } - newPath := path[:idx+suffixLen+1] - if exists, _ := afero.Exists(fs, newPath); exists { - _ = fs.Remove(path) - return "" - } - if err := fs.Rename(path, newPath); err != nil { - return "" - } - return newPath -} - func load(fs afero.Fs, cfg Config, current types.EpochID) ([]*VerifiedUpdate, error) { dir := bootstrapDir(cfg.DataDir) _, err := fs.Stat(dir) @@ -465,10 +437,7 @@ func load(fs afero.Fs, cfg Config, current types.EpochID) ([]*VerifiedUpdate, er return nil, fmt.Errorf("read epoch dir %v: %w", dir, err) } for _, f := range files { - persisted := renameLegacyFile(fs, filepath.Join(edir, f.Name())) - if persisted == "" { - continue - } + persisted := filepath.Join(edir, f.Name()) data, err := afero.ReadFile(fs, persisted) if err != nil { return nil, fmt.Errorf("read bootstrap file %v: %w", persisted, err) diff --git a/bootstrap/updater_test.go b/bootstrap/updater_test.go index 491d451468..c149140c54 100644 --- a/bootstrap/updater_test.go +++ b/bootstrap/updater_test.go @@ -122,97 +122,6 @@ func checkUpdate4(t *testing.T, got *bootstrap.VerifiedUpdate) { type checkFunc func(*testing.T, *bootstrap.VerifiedUpdate) -func TestLoad_BackwardCompatible(t *testing.T) { - epoch := 2 - tcs := []struct { - desc string - filenames []string - persisted, suffix string - }{ - { - desc: "legacy timestamp bootstrap", - filenames: []string{"epoch-2-update-bs-2023-08-10T06-00-08", "epoch-2-update-bs-2023-08-10T08-00-09"}, - persisted: "epoch-2-update-bs", - suffix: bootstrap.SuffixBoostrap, - }, - { - desc: "legacy timestamp beacon", - filenames: []string{"epoch-2-update-bc-2023-08-10T06-00-08", "epoch-2-update-bc-2023-08-10T08-00-09"}, - persisted: "epoch-2-update-bc", - suffix: bootstrap.SuffixBeacon, - }, - { - desc: "legacy timestamp active set", - filenames: []string{"epoch-2-update-as-2023-08-10T06-00-08", "epoch-2-update-as-2023-08-10T08-00-09"}, - persisted: "epoch-2-update-as", - suffix: bootstrap.SuffixActiveSet, - }, - { - desc: "legacy timestamp huh", - filenames: []string{"epoch-2-update-huh-2023-08-10T06-00-08"}, - }, - { - desc: "bootstrap", - filenames: []string{"epoch-2-update-bs"}, - persisted: "epoch-2-update-bs", - suffix: bootstrap.SuffixBoostrap, - }, - { - desc: "beacon", - filenames: []string{"epoch-2-update-bc"}, - persisted: "epoch-2-update-bc", - suffix: bootstrap.SuffixBeacon, - }, - { - desc: "active set", - filenames: []string{"epoch-2-update-as"}, - persisted: "epoch-2-update-as", - suffix: bootstrap.SuffixActiveSet, - }, - } - for _, tc := range tcs { - tc := tc - t.Run(tc.desc, func(t *testing.T) { - t.Parallel() - - cfg := bootstrap.DefaultConfig() - fs := afero.NewMemMapFs() - persistDir := filepath.Join(cfg.DataDir, bootstrap.DirName) - for _, file := range tc.filenames { - path := filepath.Join(persistDir, strconv.Itoa(epoch), file) - require.NoError(t, fs.MkdirAll(path, 0o700)) - require.NoError(t, afero.WriteFile(fs, path, []byte(update2), 0o400)) - } - mc := bootstrap.NewMocklayerClock(gomock.NewController(t)) - mc.EXPECT().CurrentLayer().Return(current.FirstLayer()) - updater := bootstrap.New( - mc, - bootstrap.WithConfig(cfg), - bootstrap.WithLogger(logtest.New(t)), - bootstrap.WithFilesystem(fs), - ) - require.NoError(t, updater.Load(context.Background())) - if tc.suffix != "" { - require.True(t, updater.Downloaded(types.EpochID(epoch), tc.suffix)) - } else { - require.False(t, updater.Downloaded(types.EpochID(epoch), bootstrap.SuffixBoostrap)) - require.False(t, updater.Downloaded(types.EpochID(epoch), bootstrap.SuffixActiveSet)) - require.False(t, updater.Downloaded(types.EpochID(epoch), bootstrap.SuffixBeacon)) - } - if tc.persisted != "" { - edir := filepath.Join(persistDir, strconv.Itoa(epoch)) - exists, err := afero.Exists(fs, filepath.Join(edir, tc.persisted)) - require.NoError(t, err) - require.True(t, exists) - all, err := afero.ReadDir(fs, edir) - require.NoError(t, err) - require.Len(t, all, 1) - require.Equal(t, tc.persisted, all[0].Name()) - } - }) - } -} - func TestLoad(t *testing.T) { tcs := []struct { desc string diff --git a/cmd/root.go b/cmd/root.go index e7f65e4412..8c7142a4ab 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -78,6 +78,8 @@ func AddCommands(cmd *cobra.Command) { cfg.DatabaseConnections, "configure number of active connections to enable parallel read requests") cmd.PersistentFlags().BoolVar(&cfg.DatabaseLatencyMetering, "db-latency-metering", cfg.DatabaseLatencyMetering, "if enabled collect latency histogram for every database query") + cmd.PersistentFlags().DurationVar(&cfg.DatabasePruneInterval, "db-prune-interval", + cfg.DatabasePruneInterval, "configure interval for database pruning") /** ======================== P2P Flags ========================== **/ @@ -115,7 +117,6 @@ func AddCommands(cmd *cobra.Command) { cfg.P2P.AdvertiseAddress, "libp2p address with identity (example: /dns4/bootnode.spacemesh.io/tcp/5003)") cmd.PersistentFlags().BoolVar(&cfg.P2P.Bootnode, "p2p-bootnode", cfg.P2P.Bootnode, "gossipsub and discovery will be running in a mode suitable for bootnode") - cmd.PersistentFlags().BoolVar(&cfg.P2P.DisableLegacyDiscovery, "p2p-disable-legacy-discovery", cfg.P2P.DisableLegacyDiscovery, "custom legacy discovery is disabled") cmd.PersistentFlags().BoolVar(&cfg.P2P.PrivateNetwork, "p2p-private-network", cfg.P2P.PrivateNetwork, "discovery will work in private mode. mostly useful for testing, don't set in public networks") /** ======================== TIME Flags ========================== **/ @@ -270,14 +271,6 @@ func AddCommands(cmd *cobra.Command) { cmd.PersistentFlags().StringVar(&cfg.TestConfig.SmesherKey, "testing-smesher-key", "", "import private smesher key for testing", ) - // TODO remove after sync protocol update - cmd.PersistentFlags().BoolVar(&cfg.Sync.UseNewProtocol, "use-new-opn", - cfg.Sync.UseNewProtocol, "use new opinions sync protocol", - ) - // TODO remove after sync protocol update - cmd.PersistentFlags().BoolVar(&cfg.FETCH.ServeNewProtocol, "serve-new-opn", - cfg.FETCH.ServeNewProtocol, "serve new opinions sync protocol", - ) // Bind Flags to config err := viper.BindPFlags(cmd.PersistentFlags()) diff --git a/common/types/ballot.go b/common/types/ballot.go index 087029cf22..47768c8106 100644 --- a/common/types/ballot.go +++ b/common/types/ballot.go @@ -289,12 +289,12 @@ func (b *Ballot) IsMalicious() bool { // MarshalLogObject implements logging encoder for Ballot. func (b *Ballot) MarshalLogObject(encoder log.ObjectEncoder) error { var ( - activeSetSize = 0 - beacon Beacon + activeHash Hash32 + beacon Beacon ) if b.EpochData != nil { - activeSetSize = len(b.ActiveSet) + activeHash = b.EpochData.ActiveSetHash beacon = b.EpochData.Beacon } @@ -309,7 +309,7 @@ func (b *Ballot) MarshalLogObject(encoder log.ObjectEncoder) error { encoder.AddInt("abstain", len(b.Votes.Abstain)) encoder.AddString("atx_id", b.AtxID.String()) encoder.AddString("ref_ballot", b.RefBallot.String()) - encoder.AddInt("active_set_size", activeSetSize) + encoder.AddString("active set hash", activeHash.ShortString()) encoder.AddString("beacon", beacon.ShortString()) encoder.AddObject("votes", &b.Votes) return nil @@ -332,7 +332,6 @@ func (b *Ballot) ToTortoiseData() *BallotTortoiseData { data.EpochData = &ReferenceData{ Beacon: b.EpochData.Beacon, Eligibilities: uint32(b.EpochData.EligibilityCount), - ActiveSet: b.ActiveSet, } } else { data.Ref = &b.RefBallot diff --git a/common/types/layer.go b/common/types/layer.go index b7b66f077e..2aee0cf74b 100644 --- a/common/types/layer.go +++ b/common/types/layer.go @@ -19,11 +19,6 @@ var ( // EmptyLayerHash is the layer hash for an empty layer. EmptyLayerHash = Hash32{} - - legacyLayer uint32 - - // layer at which optimistic filtering majority calculation is upgraded. - opUpgradeLayer uint32 ) // SetLayersPerEpoch sets global parameter of layers per epoch, all conversions from layer to epoch use this param. @@ -32,22 +27,6 @@ func SetLayersPerEpoch(layers uint32) { SetEffectiveGenesis(layers*2 - 1) } -func SetLegacyLayers(layer uint32) { - legacyLayer = layer -} - -func GetLegacyLayer() uint32 { - return legacyLayer -} - -func SetOpUpgradeLayer(layer uint32) { - opUpgradeLayer = layer -} - -func OpUpgradeLayer() uint32 { - return opUpgradeLayer -} - func SetEffectiveGenesis(layer uint32) { atomic.StoreUint32(&effectiveGenesis, layer) } diff --git a/common/types/tortoise_data.go b/common/types/tortoise_data.go index bc30259659..33b2153dfa 100644 --- a/common/types/tortoise_data.go +++ b/common/types/tortoise_data.go @@ -44,14 +44,12 @@ func (b *BallotTortoiseData) MarshalLogObject(encoder log.ObjectEncoder) error { } type ReferenceData struct { - Beacon Beacon `json:"beacon"` - ActiveSet []ATXID `json:"set"` - Eligibilities uint32 `json:"elig"` + Beacon Beacon `json:"beacon"` + Eligibilities uint32 `json:"elig"` } func (r *ReferenceData) MarshalLogObject(encoder log.ObjectEncoder) error { encoder.AddString("beacon", r.Beacon.String()) - encoder.AddInt("set size", len(r.ActiveSet)) encoder.AddUint32("elig", r.Eligibilities) return nil } diff --git a/config/config.go b/config/config.go index 3ebf4e9ec3..b0795bfbc5 100644 --- a/config/config.go +++ b/config/config.go @@ -94,7 +94,6 @@ type BaseConfig struct { ProfilerURL string `mapstructure:"profiler-url"` LayerDuration time.Duration `mapstructure:"layer-duration"` - LegacyLayer uint32 `mapstructure:"legacy-layer"` LayerAvgSize uint32 `mapstructure:"layer-average-size"` LayersPerEpoch uint32 `mapstructure:"layers-per-epoch"` @@ -109,8 +108,9 @@ type BaseConfig struct { OptFilterThreshold int `mapstructure:"optimistic-filtering-threshold"` TickSize uint64 `mapstructure:"tick-size"` - DatabaseConnections int `mapstructure:"db-connections"` - DatabaseLatencyMetering bool `mapstructure:"db-latency-metering"` + DatabaseConnections int `mapstructure:"db-connections"` + DatabaseLatencyMetering bool `mapstructure:"db-latency-metering"` + DatabasePruneInterval time.Duration `mapstructure:"db-prune-interval"` NetworkHRP string `mapstructure:"network-hrp"` @@ -174,20 +174,21 @@ func DefaultTestConfig() Config { // DefaultBaseConfig returns a default configuration for spacemesh. func defaultBaseConfig() BaseConfig { return BaseConfig{ - DataDirParent: defaultDataDir, - FileLock: filepath.Join(os.TempDir(), "spacemesh.lock"), - CollectMetrics: false, - MetricsPort: 1010, - ProfilerName: "gp-spacemesh", - LayerDuration: 30 * time.Second, - LayersPerEpoch: 3, - PoETServers: []string{"127.0.0.1"}, - TxsPerProposal: 100, - BlockGasLimit: math.MaxUint64, - OptFilterThreshold: 90, - TickSize: 100, - DatabaseConnections: 16, - NetworkHRP: "sm", + DataDirParent: defaultDataDir, + FileLock: filepath.Join(os.TempDir(), "spacemesh.lock"), + CollectMetrics: false, + MetricsPort: 1010, + ProfilerName: "gp-spacemesh", + LayerDuration: 30 * time.Second, + LayersPerEpoch: 3, + PoETServers: []string{"127.0.0.1"}, + TxsPerProposal: 100, + BlockGasLimit: math.MaxUint64, + OptFilterThreshold: 90, + TickSize: 100, + DatabaseConnections: 16, + DatabasePruneInterval: 30 * time.Minute, + NetworkHRP: "sm", } } diff --git a/config/mainnet.go b/config/mainnet.go index 6bdba311cb..9b28038c6e 100644 --- a/config/mainnet.go +++ b/config/mainnet.go @@ -8,6 +8,8 @@ import ( "runtime" "time" + "go.uber.org/zap/zapcore" + "github.com/spacemeshos/go-spacemesh/activation" "github.com/spacemeshos/go-spacemesh/api/grpcserver" "github.com/spacemeshos/go-spacemesh/beacon" @@ -36,18 +38,19 @@ func MainnetConfig() Config { if smeshing.ProvingOpts.Threads < 1 { smeshing.ProvingOpts.Threads = 1 } - + logging := DefaultLoggingConfig() + logging.TrtlLoggerLevel = zapcore.WarnLevel.String() return Config{ BaseConfig: BaseConfig{ - DataDirParent: defaultDataDir, - FileLock: filepath.Join(os.TempDir(), "spacemesh.lock"), - MetricsPort: 1010, - DatabaseConnections: 16, - NetworkHRP: "sm", + DataDirParent: defaultDataDir, + FileLock: filepath.Join(os.TempDir(), "spacemesh.lock"), + MetricsPort: 1010, + DatabaseConnections: 16, + DatabasePruneInterval: 30 * time.Minute, + NetworkHRP: "sm", LayerDuration: 5 * time.Minute, LayerAvgSize: 50, - LegacyLayer: 8180, LayersPerEpoch: 4032, TxsPerProposal: 700, // https://github.com/spacemeshos/go-spacemesh/issues/4559 @@ -78,7 +81,6 @@ func MainnetConfig() Config { // 1000 - is assumed minimal number of units // 5000 - half of the expected poet ticks MinimalActiveSetWeight: 1000 * 5000, - EmitEmptyActiveSet: 20000, }, HARE: hareConfig.Config{ N: 200, @@ -132,12 +134,11 @@ func MainnetConfig() Config { TIME: timeConfig.DefaultConfig(), SMESHING: smeshing, FETCH: fetch.DefaultConfig(), - LOGGING: DefaultLoggingConfig(), + LOGGING: logging, Sync: syncer.Config{ Interval: time.Minute, EpochEndFraction: 0.8, MaxStaleDuration: time.Hour, - UseNewProtocol: true, Standalone: false, GossipDuration: 50 * time.Second, }, diff --git a/config/presets/fastnet.go b/config/presets/fastnet.go index 4ccfe28ae6..e7bf8d0d19 100644 --- a/config/presets/fastnet.go +++ b/config/presets/fastnet.go @@ -22,6 +22,7 @@ func fastnet() config.Config { conf.NetworkHRP = "stest" types.SetNetworkHRP(conf.NetworkHRP) // set to generate coinbase conf.BaseConfig.OptFilterThreshold = 90 + conf.BaseConfig.DatabasePruneInterval = time.Minute // set for systest TestEquivocation conf.BaseConfig.MinerGoodAtxsPercent = 50 @@ -72,7 +73,8 @@ func fastnet() config.Config { conf.SMESHING.Start = false conf.SMESHING.Opts.ProviderID.SetInt64(int64(initialization.CPUProviderID())) conf.SMESHING.Opts.NumUnits = 2 - conf.SMESHING.Opts.Throttle = true + conf.SMESHING.Opts.ComputeBatchSize = 128 + conf.SMESHING.Opts.Scrypt.N = 2 // faster scrypt // Override proof of work flags to use light mode (less memory intensive) conf.SMESHING.ProvingOpts.Flags = postCfg.RecommendedPowFlags() diff --git a/config/presets/testnet.go b/config/presets/testnet.go index 8565f20112..03b005daec 100644 --- a/config/presets/testnet.go +++ b/config/presets/testnet.go @@ -108,6 +108,7 @@ func testnet() config.Config { PhaseShift: 12 * time.Hour, CycleGap: 2 * time.Hour, GracePeriod: 10 * time.Minute, + RequestTimeout: 550 * time.Second, // RequestRetryDelay * 2 * MaxRequestRetries*(MaxRequestRetries+1)/2 RequestRetryDelay: 5 * time.Second, MaxRequestRetries: 10, }, @@ -136,7 +137,6 @@ func testnet() config.Config { Interval: time.Minute, EpochEndFraction: 0.8, MaxStaleDuration: time.Hour, - UseNewProtocol: true, GossipDuration: 50 * time.Second, }, Recovery: checkpoint.DefaultConfig(), diff --git a/events/events.go b/events/events.go index 455aaf1032..169828d7e0 100644 --- a/events/events.go +++ b/events/events.go @@ -17,7 +17,7 @@ type UserEvent struct { } func EmitBeacon(epoch types.EpochID, beacon types.Beacon) { - const help = "Node computed randomness beacon, it will be used to determine eligibility to participate in the consensus." + const help = "Node computed randomness beacon, which will be used to determine consensus eligibility." emitUserEvent( help, false, @@ -31,7 +31,7 @@ func EmitBeacon(epoch types.EpochID, beacon types.Beacon) { } func EmitInitStart(smesher types.NodeID, commitment types.ATXID) { - const help = "Node started post data initialization. Note that init is noop if node restarted when init was ready." + const help = "Node started PoST data initialization. Initialization will not be performed again if already completed." emitUserEvent( help, false, @@ -45,7 +45,7 @@ func EmitInitStart(smesher types.NodeID, commitment types.ATXID) { } func EmitInitFailure(smesher types.NodeID, commitment types.ATXID, err error) { - const help = "Node failed post data initialization." + const help = "Node failed PoST data initialization." emitUserEvent( help, true, @@ -60,7 +60,7 @@ func EmitInitFailure(smesher types.NodeID, commitment types.ATXID, err error) { } func EmitInitComplete() { - const help = "Node completed post data initialization." + const help = "Node successfully completed PoST data initialization." emitUserEvent( help, false, @@ -71,8 +71,8 @@ func EmitInitComplete() { } func EmitPoetWaitRound(current, publish types.EpochID, wait time.Duration) { - const help = "Node needs to wait for poet registration window in current epoch to open. " + - "Once opened it will submit challenge and wait till poet round ends in publish epoch." + const help = "Node is waiting for PoET registration window in current epoch to open. " + + "After this it will submit challenge and wait until PoET round ends in publish epoch." emitUserEvent( help, false, @@ -91,9 +91,9 @@ type EventPoetWaitEnd struct { } func EmitPoetWaitProof(publish, target types.EpochID, wait time.Duration) { - const help = "Node needs to wait for poet to complete in publish epoch. " + - "Once completed, node fetches proof from poet and runs post on that proof. " + - "After that publish an ATX that will be eligible for rewards in target epoch." + const help = "Node is waiting for PoET to complete. " + + "After it's complete, the node will fetch the PoET proof, generate a PoST proof, " + + "and finally publish an ATX to establish eligibility for rewards in the target epoch." emitUserEvent( help, false, @@ -108,7 +108,7 @@ func EmitPoetWaitProof(publish, target types.EpochID, wait time.Duration) { } func EmitPostStart(challenge []byte) { - const help = "Node started post execution for the challenge from poet." + const help = "Node started PoST execution using the challenge from PoET." emitUserEvent( help, false, @@ -117,7 +117,7 @@ func EmitPostStart(challenge []byte) { } func EmitPostComplete(challenge []byte) { - const help = "Node finished post execution for challenge." + const help = "Node finished PoST execution using PoET challenge." emitUserEvent( help, false, @@ -126,7 +126,7 @@ func EmitPostComplete(challenge []byte) { } func EmitPostFailure() { - const help = "Node failed post execution." + const help = "Node failed PoST execution." emitUserEvent( help, true, @@ -148,8 +148,8 @@ func EmitAtxPublished( id types.ATXID, wait time.Duration, ) { - const help = "Published activation for the current epoch. " + - "Node needs to wait till the start of the target epoch in order to be eligible for rewards." + const help = "Node published activation for the current epoch. " + + "It now needs to wait until the target epoch when it will be eligible for rewards." emitUserEvent( help, false, @@ -171,9 +171,9 @@ func EmitEligibilities( activeSetSize uint32, eligibilities map[types.LayerID][]types.VotingEligibility, ) { - const help = "Computed eligibilities for the epoch. " + - "Rewards will be received after publishing proposals at specified layers. " + - "Total amount of rewards in SMH will be based on other participants in the layer." + const help = "Node computed eligibilities for the epoch. " + + "Rewards will be received after successfully publishing proposals at specified layers. " + + "The rewards actually received will be based on the number of other participants in each layer." emitUserEvent( help, false, @@ -201,7 +201,7 @@ func castEligibilities(proofs map[types.LayerID][]types.VotingEligibility) []*pb } func EmitProposal(layer types.LayerID, proposal types.ProposalID) { - const help = "Published proposal. Rewards will be received, once proposal is included into the block." + const help = "Node published proposal. Rewards will be received once proposal is included in the block." emitUserEvent( help, false, @@ -215,7 +215,7 @@ func EmitProposal(layer types.LayerID, proposal types.ProposalID) { } func EmitOwnMalfeasanceProof(id types.NodeID, mp *types.MalfeasanceProof) { - const help = "Committed malicious behavior. Identity will be canceled." + const help = "Node committed malicious behavior. Identity will be canceled." emitUserEvent( help, false, diff --git a/fetch/fetch.go b/fetch/fetch.go index be81263992..b5faf770e4 100644 --- a/fetch/fetch.go +++ b/fetch/fetch.go @@ -24,12 +24,10 @@ import ( const ( atxProtocol = "ax/1" lyrDataProtocol = "ld/1" - lyrOpnsProtocol = "lp/1" hashProtocol = "hs/1" meshHashProtocol = "mh/1" malProtocol = "ml/1" - - OpnProtocol = "lp/2" + OpnProtocol = "lp/2" cacheSize = 1000 ) @@ -85,7 +83,6 @@ type Config struct { BatchSize, QueueSize int RequestTimeout time.Duration // in seconds MaxRetriesForRequest int - ServeNewProtocol bool `mapstructure:"serve-new-opn"` } // DefaultConfig is the default config for the fetch component. @@ -97,7 +94,6 @@ func DefaultConfig() Config { BatchSize: 20, RequestTimeout: time.Second * time.Duration(10), MaxRetriesForRequest: 100, - ServeNewProtocol: true, } } @@ -192,16 +188,13 @@ func NewFetch(cdb *datastore.CachedDB, msh meshProvider, b system.BeaconGetter, server.WithLog(f.logger), } if len(f.servers) == 0 { - h := newHandler(cdb, bs, msh, b, f.cfg.ServeNewProtocol, f.logger) + h := newHandler(cdb, bs, msh, b, f.logger) f.servers[atxProtocol] = server.New(host, atxProtocol, h.handleEpochInfoReq, srvOpts...) f.servers[lyrDataProtocol] = server.New(host, lyrDataProtocol, h.handleLayerDataReq, srvOpts...) - f.servers[lyrOpnsProtocol] = server.New(host, lyrOpnsProtocol, h.handleLayerOpinionsReq, srvOpts...) f.servers[hashProtocol] = server.New(host, hashProtocol, h.handleHashReq, srvOpts...) f.servers[meshHashProtocol] = server.New(host, meshHashProtocol, h.handleMeshHashReq, srvOpts...) f.servers[malProtocol] = server.New(host, malProtocol, h.handleMaliciousIDsReq, srvOpts...) - if f.cfg.ServeNewProtocol { - f.servers[OpnProtocol] = server.New(host, OpnProtocol, h.handleLayerOpinionsReq2, srvOpts...) - } + f.servers[OpnProtocol] = server.New(host, OpnProtocol, h.handleLayerOpinionsReq2, srvOpts...) } return f } diff --git a/fetch/fetch_test.go b/fetch/fetch_test.go index 273ce9825a..7287432b95 100644 --- a/fetch/fetch_test.go +++ b/fetch/fetch_test.go @@ -28,7 +28,6 @@ type testFetch struct { mMalS *mocks.Mockrequester mAtxS *mocks.Mockrequester mLyrS *mocks.Mockrequester - mOpnS *mocks.Mockrequester mHashS *mocks.Mockrequester mMHashS *mocks.Mockrequester mOpn2S *mocks.Mockrequester @@ -53,7 +52,6 @@ func createFetch(tb testing.TB) *testFetch { mMalS: mocks.NewMockrequester(ctrl), mAtxS: mocks.NewMockrequester(ctrl), mLyrS: mocks.NewMockrequester(ctrl), - mOpnS: mocks.NewMockrequester(ctrl), mHashS: mocks.NewMockrequester(ctrl), mMHashS: mocks.NewMockrequester(ctrl), mOpn2S: mocks.NewMockrequester(ctrl), @@ -74,7 +72,6 @@ func createFetch(tb testing.TB) *testFetch { QueueSize: 1000, RequestTimeout: time.Second * time.Duration(3), MaxRetriesForRequest: 3, - ServeNewProtocol: true, } lg := logtest.New(tb) tf.Fetch = NewFetch(datastore.NewCachedDB(sql.InMemory(), lg), tf.mMesh, nil, nil, @@ -85,7 +82,6 @@ func createFetch(tb testing.TB) *testFetch { malProtocol: tf.mMalS, atxProtocol: tf.mAtxS, lyrDataProtocol: tf.mLyrS, - lyrOpnsProtocol: tf.mOpnS, hashProtocol: tf.mHashS, meshHashProtocol: tf.mMHashS, OpnProtocol: tf.mOpn2S, @@ -365,7 +361,6 @@ func TestFetch_PeerDroppedWhenMessageResultsInValidationReject(t *testing.T) { QueueSize: 1000, RequestTimeout: time.Second * time.Duration(3), MaxRetriesForRequest: 3, - ServeNewProtocol: true, } p2pconf := p2p.DefaultConfig() p2pconf.Listen = "/ip4/127.0.0.1/tcp/0" diff --git a/fetch/handler.go b/fetch/handler.go index e46b149180..41a7b96551 100644 --- a/fetch/handler.go +++ b/fetch/handler.go @@ -23,18 +23,15 @@ type handler struct { bs *datastore.BlobStore msh meshProvider beacon system.BeaconGetter - - serveNewOpn bool } -func newHandler(cdb *datastore.CachedDB, bs *datastore.BlobStore, m meshProvider, b system.BeaconGetter, newOpn bool, lg log.Log) *handler { +func newHandler(cdb *datastore.CachedDB, bs *datastore.BlobStore, m meshProvider, b system.BeaconGetter, lg log.Log) *handler { return &handler{ - logger: lg, - cdb: cdb, - bs: bs, - msh: m, - beacon: b, - serveNewOpn: newOpn, + logger: lg, + cdb: cdb, + bs: bs, + msh: m, + beacon: b, } } @@ -103,55 +100,7 @@ func (h *handler) handleLayerDataReq(ctx context.Context, req []byte) ([]byte, e return out, nil } -// handleLayerOpinionsReq returns the opinions on data in the specified layer, described in LayerOpinion. -func (h *handler) handleLayerOpinionsReq(ctx context.Context, req []byte) ([]byte, error) { - opnReqV1.Inc() - var ( - lid types.LayerID - lo LayerOpinion - out []byte - err error - ) - if err := codec.Decode(req, &lid); err != nil { - return nil, err - } - lo.PrevAggHash, err = layers.GetAggregatedHash(h.cdb, lid.Sub(1)) - if err != nil && !errors.Is(err, sql.ErrNotFound) { - h.logger.WithContext(ctx).With().Warning("serve: failed to get prev agg hash", lid, log.Err(err)) - return nil, err - } - - certs, err := certificates.Get(h.cdb, lid) - if err != nil && !errors.Is(err, sql.ErrNotFound) { - h.logger.WithContext(ctx).With().Warning("serve: failed to get certificate", lid, log.Err(err)) - return nil, err - } - if err == nil { - var validCert *types.Certificate - for _, cert := range certs { - if !cert.Valid { - continue - } - if validCert != nil { - validCert = nil - break - } - validCert = cert.Cert - } - lo.Cert = validCert - } - - out, err = codec.Encode(&lo) - if err != nil { - h.logger.WithContext(ctx).With().Fatal("serve: failed to encode layer opinions response", log.Err(err)) - } - return out, nil -} - func (h *handler) handleLayerOpinionsReq2(ctx context.Context, data []byte) ([]byte, error) { - if !h.serveNewOpn { - return nil, errors.New("new opn protocol not supported") - } var req OpinionRequest if err := codec.Decode(data, &req); err != nil { return nil, err @@ -162,7 +111,7 @@ func (h *handler) handleLayerOpinionsReq2(ctx context.Context, data []byte) ([]b var ( lid = req.Layer - lo LayerOpinion2 + lo LayerOpinion out []byte err error ) diff --git a/fetch/handler_test.go b/fetch/handler_test.go index 1d6f004e74..f007b01045 100644 --- a/fetch/handler_test.go +++ b/fetch/handler_test.go @@ -39,7 +39,7 @@ func createTestHandler(t testing.TB) *testHandler { mm := mocks.NewMockmeshProvider(ctrl) mb := smocks.NewMockBeaconGetter(ctrl) return &testHandler{ - handler: newHandler(cdb, datastore.NewBlobStore(cdb.Database), mm, mb, true, lg), + handler: newHandler(cdb, datastore.NewBlobStore(cdb.Database), mm, mb, lg), cdb: cdb, mm: mm, mb: mb, @@ -135,58 +135,6 @@ func TestHandleLayerOpinionsReq(t *testing.T) { }, } - for _, tc := range tt { - tc := tc - t.Run(tc.name, func(t *testing.T) { - t.Parallel() - - th := createTestHandler(t) - lid := types.LayerID(111) - certified, aggHash := createOpinions(t, th.cdb, lid, !tc.missingCert) - if tc.multipleCerts { - require.NoError(t, certificates.Add(th.cdb, lid, &types.Certificate{ - BlockID: types.RandomBlockID(), - })) - } - - lidBytes, err := codec.Encode(&lid) - require.NoError(t, err) - - out, err := th.handleLayerOpinionsReq(context.Background(), lidBytes) - require.NoError(t, err) - - var got LayerOpinion - err = codec.Decode(out, &got) - require.NoError(t, err) - require.Equal(t, aggHash, got.PrevAggHash) - if tc.missingCert || tc.multipleCerts { - require.Nil(t, got.Cert) - } else { - require.NotNil(t, got.Cert) - require.Equal(t, certified, got.Cert.BlockID) - } - }) - } -} - -func TestHandleLayerOpinionsReq2(t *testing.T) { - tt := []struct { - name string - missingCert, multipleCerts bool - }{ - { - name: "all good", - }, - { - name: "cert missing", - missingCert: true, - }, - { - name: "multiple certs", - multipleCerts: true, - }, - } - for _, tc := range tt { tc := tc t.Run(tc.name, func(t *testing.T) { @@ -210,7 +158,7 @@ func TestHandleLayerOpinionsReq2(t *testing.T) { out, err := th.handleLayerOpinionsReq2(context.Background(), reqBytes) require.NoError(t, err) - var got LayerOpinion2 + var got LayerOpinion err = codec.Decode(out, &got) require.NoError(t, err) require.Equal(t, aggHash, got.PrevAggHash) @@ -247,10 +195,6 @@ func TestHandleCertReq(t *testing.T) { var got types.Certificate require.NoError(t, codec.Decode(resp, &got)) require.Equal(t, *cert, got) - - th.serveNewOpn = false - _, err = th.handleLayerOpinionsReq2(context.Background(), reqData) - require.ErrorContains(t, err, "new opn protocol not supported") } func TestHandleMeshHashReq(t *testing.T) { diff --git a/fetch/mesh_data.go b/fetch/mesh_data.go index b78e255667..a9ec96e360 100644 --- a/fetch/mesh_data.go +++ b/fetch/mesh_data.go @@ -178,16 +178,7 @@ func (f *Fetch) GetLayerData(ctx context.Context, peers []p2p.Peer, lid types.La return poll(ctx, f.servers[lyrDataProtocol], peers, lidBytes, okCB, errCB) } -// GetLayerOpinions get opinions on data in the specified layer from peers. func (f *Fetch) GetLayerOpinions(ctx context.Context, peers []p2p.Peer, lid types.LayerID, okCB func([]byte, p2p.Peer), errCB func(error, p2p.Peer)) error { - lidBytes, err := codec.Encode(&lid) - if err != nil { - return err - } - return poll(ctx, f.servers[lyrOpnsProtocol], peers, lidBytes, okCB, errCB) -} - -func (f *Fetch) GetLayerOpinions2(ctx context.Context, peers []p2p.Peer, lid types.LayerID, okCB func([]byte, p2p.Peer), errCB func(error, p2p.Peer)) error { req := OpinionRequest{ Layer: lid, } diff --git a/fetch/mesh_data_test.go b/fetch/mesh_data_test.go index fa969c3635..f945eae9be 100644 --- a/fetch/mesh_data_test.go +++ b/fetch/mesh_data_test.go @@ -548,87 +548,6 @@ func TestFetch_GetLayerData(t *testing.T) { } } -func TestFetch_GetLayerOpinions(t *testing.T) { - peers := []p2p.Peer{"p0", "p1", "p3", "p4"} - errUnknown := errors.New("unknown") - tt := []struct { - name string - errs []error - v2 bool - }{ - { - name: "all peers returns", - errs: []error{nil, nil, nil, nil}, - }, - { - name: "all peers returns v2", - v2: true, - errs: []error{nil, nil, nil, nil}, - }, - { - name: "some peers errors", - errs: []error{nil, errUnknown, nil, errUnknown}, - }, - { - name: "some peers errors v2", - v2: true, - errs: []error{nil, errUnknown, nil, errUnknown}, - }, - } - - for _, tc := range tt { - tc := tc - t.Run(tc.name, func(t *testing.T) { - t.Parallel() - - require.Equal(t, len(peers), len(tc.errs)) - f := createFetch(t) - oks := make(chan struct{}, len(peers)) - errs := make(chan struct{}, len(peers)) - var wg sync.WaitGroup - wg.Add(len(peers)) - okFunc := func(data []byte, peer p2p.Peer) { - oks <- struct{}{} - wg.Done() - } - errFunc := func(err error, peer p2p.Peer) { - errs <- struct{}{} - wg.Done() - } - var expOk, expErr int - for i, p := range peers { - if tc.errs[i] == nil { - expOk++ - } else { - expErr++ - } - idx := i - ms := f.mOpnS - if tc.v2 { - ms = f.mOpn2S - } - ms.EXPECT().Request(gomock.Any(), p, gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn( - func(_ context.Context, _ p2p.Peer, _ []byte, okCB func([]byte), errCB func(error)) error { - if tc.errs[idx] == nil { - go okCB([]byte("data")) - } else { - go errCB(tc.errs[idx]) - } - return nil - }) - } - if tc.v2 { - require.NoError(t, f.GetLayerOpinions2(context.Background(), peers, types.LayerID(111), okFunc, errFunc)) - } else { - require.NoError(t, f.GetLayerOpinions(context.Background(), peers, types.LayerID(111), okFunc, errFunc)) - } - wg.Wait() - require.Len(t, oks, expOk) - require.Len(t, errs, expErr) - }) - } -} - func generateEpochData(t *testing.T) (*EpochData, []byte) { t.Helper() ed := &EpochData{ diff --git a/fetch/metrics.go b/fetch/metrics.go index 2698fe7ccd..621e82f75e 100644 --- a/fetch/metrics.go +++ b/fetch/metrics.go @@ -54,14 +54,12 @@ var ( "total requests for block certificate received", []string{}).WithLabelValues() - opnReq = metrics.NewCounter( + opnReqV2 = metrics.NewCounter( "opn_reqs", subsystem, "total layer opinion requests received", []string{"version"}, - ) - opnReqV1 = opnReq.WithLabelValues("v1") - opnReqV2 = opnReq.WithLabelValues("v2") + ).WithLabelValues("v2") ) // logCacheHit logs cache hit. diff --git a/fetch/mocks/mocks.go b/fetch/mocks/mocks.go index 611acce0a3..f65a0649e2 100644 --- a/fetch/mocks/mocks.go +++ b/fetch/mocks/mocks.go @@ -1,6 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: ./interface.go - +// +// Generated by this command: +// +// mockgen -typed -package=mocks -destination=./mocks/mocks.go -source=./interface.go +// // Package mocks is a generated GoMock package. package mocks @@ -46,7 +50,7 @@ func (m *Mockrequester) Request(arg0 context.Context, arg1 p2p.Peer, arg2 []byte } // Request indicates an expected call of Request. -func (mr *MockrequesterMockRecorder) Request(arg0, arg1, arg2, arg3, arg4 interface{}) *requesterRequestCall { +func (mr *MockrequesterMockRecorder) Request(arg0, arg1, arg2, arg3, arg4 any) *requesterRequestCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Request", reflect.TypeOf((*Mockrequester)(nil).Request), arg0, arg1, arg2, arg3, arg4) return &requesterRequestCall{Call: call} @@ -107,7 +111,7 @@ func (m *MockSyncValidator) HandleMessage(arg0 context.Context, arg1 types.Hash3 } // HandleMessage indicates an expected call of HandleMessage. -func (mr *MockSyncValidatorMockRecorder) HandleMessage(arg0, arg1, arg2, arg3 interface{}) *SyncValidatorHandleMessageCall { +func (mr *MockSyncValidatorMockRecorder) HandleMessage(arg0, arg1, arg2, arg3 any) *SyncValidatorHandleMessageCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HandleMessage", reflect.TypeOf((*MockSyncValidator)(nil).HandleMessage), arg0, arg1, arg2, arg3) return &SyncValidatorHandleMessageCall{Call: call} @@ -168,7 +172,7 @@ func (m *MockPoetValidator) ValidateAndStoreMsg(arg0 context.Context, arg1 types } // ValidateAndStoreMsg indicates an expected call of ValidateAndStoreMsg. -func (mr *MockPoetValidatorMockRecorder) ValidateAndStoreMsg(arg0, arg1, arg2, arg3 interface{}) *PoetValidatorValidateAndStoreMsgCall { +func (mr *MockPoetValidatorMockRecorder) ValidateAndStoreMsg(arg0, arg1, arg2, arg3 any) *PoetValidatorValidateAndStoreMsgCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidateAndStoreMsg", reflect.TypeOf((*MockPoetValidator)(nil).ValidateAndStoreMsg), arg0, arg1, arg2, arg3) return &PoetValidatorValidateAndStoreMsgCall{Call: call} @@ -328,7 +332,7 @@ func (m *Mockhost) Connected(arg0 p2p.Peer) bool { } // Connected indicates an expected call of Connected. -func (mr *MockhostMockRecorder) Connected(arg0 interface{}) *hostConnectedCall { +func (mr *MockhostMockRecorder) Connected(arg0 any) *hostConnectedCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Connected", reflect.TypeOf((*Mockhost)(nil).Connected), arg0) return &hostConnectedCall{Call: call} @@ -443,7 +447,7 @@ func (m *Mockhost) PeerProtocols(arg0 p2p.Peer) ([]protocol.ID, error) { } // PeerProtocols indicates an expected call of PeerProtocols. -func (mr *MockhostMockRecorder) PeerProtocols(arg0 interface{}) *hostPeerProtocolsCall { +func (mr *MockhostMockRecorder) PeerProtocols(arg0 any) *hostPeerProtocolsCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PeerProtocols", reflect.TypeOf((*Mockhost)(nil).PeerProtocols), arg0) return &hostPeerProtocolsCall{Call: call} diff --git a/fetch/wire_types.go b/fetch/wire_types.go index f2964276ff..2272d8c180 100644 --- a/fetch/wire_types.go +++ b/fetch/wire_types.go @@ -110,40 +110,12 @@ type LayerData struct { Ballots []types.BallotID `scale:"max=500"` // expected are 50 proposals per layer + safety margin } -// LayerOpinion is the response for opinion for a given layer. -type LayerOpinion struct { - PrevAggHash types.Hash32 - Cert *types.Certificate - - peer p2p.Peer -} - -// SetPeer ... -func (lo *LayerOpinion) SetPeer(p p2p.Peer) { - lo.peer = p -} - -// Peer ... -func (lo *LayerOpinion) Peer() p2p.Peer { - return lo.peer -} - -// MarshalLogObject implements logging encoder for LayerOpinion. -func (lo *LayerOpinion) MarshalLogObject(encoder log.ObjectEncoder) error { - encoder.AddString("peer", lo.peer.String()) - encoder.AddString("prev_hash", lo.PrevAggHash.String()) - if lo.Cert != nil { - encoder.AddString("cert_block_id", lo.Cert.BlockID.String()) - } - return nil -} - type OpinionRequest struct { Layer types.LayerID Block *types.BlockID } -type LayerOpinion2 struct { +type LayerOpinion struct { PrevAggHash types.Hash32 Certified *types.BlockID @@ -151,17 +123,17 @@ type LayerOpinion2 struct { } // SetPeer ... -func (lo *LayerOpinion2) SetPeer(p p2p.Peer) { +func (lo *LayerOpinion) SetPeer(p p2p.Peer) { lo.peer = p } // Peer ... -func (lo *LayerOpinion2) Peer() p2p.Peer { +func (lo *LayerOpinion) Peer() p2p.Peer { return lo.peer } // MarshalLogObject implements logging encoder for LayerOpinion. -func (lo *LayerOpinion2) MarshalLogObject(encoder log.ObjectEncoder) error { +func (lo *LayerOpinion) MarshalLogObject(encoder log.ObjectEncoder) error { encoder.AddString("peer", lo.peer.String()) encoder.AddString("prev hash", lo.PrevAggHash.String()) encoder.AddBool("has cert", lo.Certified != nil) diff --git a/fetch/wire_types_scale.go b/fetch/wire_types_scale.go index 1055b93ad5..86d2ed58f0 100644 --- a/fetch/wire_types_scale.go +++ b/fetch/wire_types_scale.go @@ -302,43 +302,6 @@ func (t *LayerData) DecodeScale(dec *scale.Decoder) (total int, err error) { return total, nil } -func (t *LayerOpinion) EncodeScale(enc *scale.Encoder) (total int, err error) { - { - n, err := scale.EncodeByteArray(enc, t.PrevAggHash[:]) - if err != nil { - return total, err - } - total += n - } - { - n, err := scale.EncodeOption(enc, t.Cert) - if err != nil { - return total, err - } - total += n - } - return total, nil -} - -func (t *LayerOpinion) DecodeScale(dec *scale.Decoder) (total int, err error) { - { - n, err := scale.DecodeByteArray(dec, t.PrevAggHash[:]) - if err != nil { - return total, err - } - total += n - } - { - field, n, err := scale.DecodeOption[types.Certificate](dec) - if err != nil { - return total, err - } - total += n - t.Cert = field - } - return total, nil -} - func (t *OpinionRequest) EncodeScale(enc *scale.Encoder) (total int, err error) { { n, err := scale.EncodeCompact32(enc, uint32(t.Layer)) @@ -377,7 +340,7 @@ func (t *OpinionRequest) DecodeScale(dec *scale.Decoder) (total int, err error) return total, nil } -func (t *LayerOpinion2) EncodeScale(enc *scale.Encoder) (total int, err error) { +func (t *LayerOpinion) EncodeScale(enc *scale.Encoder) (total int, err error) { { n, err := scale.EncodeByteArray(enc, t.PrevAggHash[:]) if err != nil { @@ -395,7 +358,7 @@ func (t *LayerOpinion2) EncodeScale(enc *scale.Encoder) (total int, err error) { return total, nil } -func (t *LayerOpinion2) DecodeScale(dec *scale.Decoder) (total int, err error) { +func (t *LayerOpinion) DecodeScale(dec *scale.Decoder) (total int, err error) { { n, err := scale.DecodeByteArray(dec, t.PrevAggHash[:]) if err != nil { diff --git a/genvm/core/mocks/handler.go b/genvm/core/mocks/handler.go index a38a903525..0ead71d8e0 100644 --- a/genvm/core/mocks/handler.go +++ b/genvm/core/mocks/handler.go @@ -1,6 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: github.com/spacemeshos/go-spacemesh/genvm/core (interfaces: Handler) - +// +// Generated by this command: +// +// mockgen -typed -package=mocks -destination=./mocks/handler.go github.com/spacemeshos/go-spacemesh/genvm/core Handler +// // Package mocks is a generated GoMock package. package mocks @@ -44,7 +48,7 @@ func (m *MockHandler) Args(arg0 byte) scale.Type { } // Args indicates an expected call of Args. -func (mr *MockHandlerMockRecorder) Args(arg0 interface{}) *HandlerArgsCall { +func (mr *MockHandlerMockRecorder) Args(arg0 any) *HandlerArgsCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Args", reflect.TypeOf((*MockHandler)(nil).Args), arg0) return &HandlerArgsCall{Call: call} @@ -82,7 +86,7 @@ func (m *MockHandler) Exec(arg0 core.Host, arg1 byte, arg2 scale.Encodable) erro } // Exec indicates an expected call of Exec. -func (mr *MockHandlerMockRecorder) Exec(arg0, arg1, arg2 interface{}) *HandlerExecCall { +func (mr *MockHandlerMockRecorder) Exec(arg0, arg1, arg2 any) *HandlerExecCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Exec", reflect.TypeOf((*MockHandler)(nil).Exec), arg0, arg1, arg2) return &HandlerExecCall{Call: call} @@ -121,7 +125,7 @@ func (m *MockHandler) Load(arg0 []byte) (core.Template, error) { } // Load indicates an expected call of Load. -func (mr *MockHandlerMockRecorder) Load(arg0 interface{}) *HandlerLoadCall { +func (mr *MockHandlerMockRecorder) Load(arg0 any) *HandlerLoadCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Load", reflect.TypeOf((*MockHandler)(nil).Load), arg0) return &HandlerLoadCall{Call: call} @@ -151,7 +155,7 @@ func (c *HandlerLoadCall) DoAndReturn(f func([]byte) (core.Template, error)) *Ha } // New mocks base method. -func (m *MockHandler) New(arg0 interface{}) (core.Template, error) { +func (m *MockHandler) New(arg0 any) (core.Template, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "New", arg0) ret0, _ := ret[0].(core.Template) @@ -160,7 +164,7 @@ func (m *MockHandler) New(arg0 interface{}) (core.Template, error) { } // New indicates an expected call of New. -func (mr *MockHandlerMockRecorder) New(arg0 interface{}) *HandlerNewCall { +func (mr *MockHandlerMockRecorder) New(arg0 any) *HandlerNewCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "New", reflect.TypeOf((*MockHandler)(nil).New), arg0) return &HandlerNewCall{Call: call} @@ -178,13 +182,13 @@ func (c *HandlerNewCall) Return(arg0 core.Template, arg1 error) *HandlerNewCall } // Do rewrite *gomock.Call.Do -func (c *HandlerNewCall) Do(f func(interface{}) (core.Template, error)) *HandlerNewCall { +func (c *HandlerNewCall) Do(f func(any) (core.Template, error)) *HandlerNewCall { c.Call = c.Call.Do(f) return c } // DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *HandlerNewCall) DoAndReturn(f func(interface{}) (core.Template, error)) *HandlerNewCall { +func (c *HandlerNewCall) DoAndReturn(f func(any) (core.Template, error)) *HandlerNewCall { c.Call = c.Call.DoAndReturn(f) return c } @@ -199,7 +203,7 @@ func (m *MockHandler) Parse(arg0 core.Host, arg1 byte, arg2 *scale.Decoder) (cor } // Parse indicates an expected call of Parse. -func (mr *MockHandlerMockRecorder) Parse(arg0, arg1, arg2 interface{}) *HandlerParseCall { +func (mr *MockHandlerMockRecorder) Parse(arg0, arg1, arg2 any) *HandlerParseCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Parse", reflect.TypeOf((*MockHandler)(nil).Parse), arg0, arg1, arg2) return &HandlerParseCall{Call: call} diff --git a/genvm/core/mocks/template.go b/genvm/core/mocks/template.go index 5fc890128f..35f6e4f46d 100644 --- a/genvm/core/mocks/template.go +++ b/genvm/core/mocks/template.go @@ -1,6 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: github.com/spacemeshos/go-spacemesh/genvm/core (interfaces: Template) - +// +// Generated by this command: +// +// mockgen -typed -package=mocks -destination=./mocks/template.go github.com/spacemeshos/go-spacemesh/genvm/core Template +// // Package mocks is a generated GoMock package. package mocks @@ -44,7 +48,7 @@ func (m *MockTemplate) BaseGas(arg0 byte) uint64 { } // BaseGas indicates an expected call of BaseGas. -func (mr *MockTemplateMockRecorder) BaseGas(arg0 interface{}) *TemplateBaseGasCall { +func (mr *MockTemplateMockRecorder) BaseGas(arg0 any) *TemplateBaseGasCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BaseGas", reflect.TypeOf((*MockTemplate)(nil).BaseGas), arg0) return &TemplateBaseGasCall{Call: call} @@ -83,7 +87,7 @@ func (m *MockTemplate) EncodeScale(arg0 *scale.Encoder) (int, error) { } // EncodeScale indicates an expected call of EncodeScale. -func (mr *MockTemplateMockRecorder) EncodeScale(arg0 interface{}) *TemplateEncodeScaleCall { +func (mr *MockTemplateMockRecorder) EncodeScale(arg0 any) *TemplateEncodeScaleCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EncodeScale", reflect.TypeOf((*MockTemplate)(nil).EncodeScale), arg0) return &TemplateEncodeScaleCall{Call: call} @@ -121,7 +125,7 @@ func (m *MockTemplate) ExecGas(arg0 byte) uint64 { } // ExecGas indicates an expected call of ExecGas. -func (mr *MockTemplateMockRecorder) ExecGas(arg0 interface{}) *TemplateExecGasCall { +func (mr *MockTemplateMockRecorder) ExecGas(arg0 any) *TemplateExecGasCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExecGas", reflect.TypeOf((*MockTemplate)(nil).ExecGas), arg0) return &TemplateExecGasCall{Call: call} @@ -189,7 +193,7 @@ func (c *TemplateLoadGasCall) DoAndReturn(f func() uint64) *TemplateLoadGasCall } // MaxSpend mocks base method. -func (m *MockTemplate) MaxSpend(arg0 byte, arg1 interface{}) (uint64, error) { +func (m *MockTemplate) MaxSpend(arg0 byte, arg1 any) (uint64, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "MaxSpend", arg0, arg1) ret0, _ := ret[0].(uint64) @@ -198,7 +202,7 @@ func (m *MockTemplate) MaxSpend(arg0 byte, arg1 interface{}) (uint64, error) { } // MaxSpend indicates an expected call of MaxSpend. -func (mr *MockTemplateMockRecorder) MaxSpend(arg0, arg1 interface{}) *TemplateMaxSpendCall { +func (mr *MockTemplateMockRecorder) MaxSpend(arg0, arg1 any) *TemplateMaxSpendCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "MaxSpend", reflect.TypeOf((*MockTemplate)(nil).MaxSpend), arg0, arg1) return &TemplateMaxSpendCall{Call: call} @@ -216,13 +220,13 @@ func (c *TemplateMaxSpendCall) Return(arg0 uint64, arg1 error) *TemplateMaxSpend } // Do rewrite *gomock.Call.Do -func (c *TemplateMaxSpendCall) Do(f func(byte, interface{}) (uint64, error)) *TemplateMaxSpendCall { +func (c *TemplateMaxSpendCall) Do(f func(byte, any) (uint64, error)) *TemplateMaxSpendCall { c.Call = c.Call.Do(f) return c } // DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *TemplateMaxSpendCall) DoAndReturn(f func(byte, interface{}) (uint64, error)) *TemplateMaxSpendCall { +func (c *TemplateMaxSpendCall) DoAndReturn(f func(byte, any) (uint64, error)) *TemplateMaxSpendCall { c.Call = c.Call.DoAndReturn(f) return c } @@ -236,7 +240,7 @@ func (m *MockTemplate) Verify(arg0 core.Host, arg1 []byte, arg2 *scale.Decoder) } // Verify indicates an expected call of Verify. -func (mr *MockTemplateMockRecorder) Verify(arg0, arg1, arg2 interface{}) *TemplateVerifyCall { +func (mr *MockTemplateMockRecorder) Verify(arg0, arg1, arg2 any) *TemplateVerifyCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Verify", reflect.TypeOf((*MockTemplate)(nil).Verify), arg0, arg1, arg2) return &TemplateVerifyCall{Call: call} diff --git a/genvm/core/mocks/updater.go b/genvm/core/mocks/updater.go index 81eadaadb2..ba04f7f189 100644 --- a/genvm/core/mocks/updater.go +++ b/genvm/core/mocks/updater.go @@ -1,6 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: github.com/spacemeshos/go-spacemesh/genvm/core (interfaces: AccountUpdater) - +// +// Generated by this command: +// +// mockgen -typed -package=mocks -destination=./mocks/updater.go github.com/spacemeshos/go-spacemesh/genvm/core AccountUpdater +// // Package mocks is a generated GoMock package. package mocks @@ -43,7 +47,7 @@ func (m *MockAccountUpdater) Update(arg0 types.Account) error { } // Update indicates an expected call of Update. -func (mr *MockAccountUpdaterMockRecorder) Update(arg0 interface{}) *AccountUpdaterUpdateCall { +func (mr *MockAccountUpdaterMockRecorder) Update(arg0 any) *AccountUpdaterUpdateCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockAccountUpdater)(nil).Update), arg0) return &AccountUpdaterUpdateCall{Call: call} diff --git a/go.mod b/go.mod index 9907a64cb0..ff98b6abc6 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,10 @@ module github.com/spacemeshos/go-spacemesh -go 1.21 +go 1.21.1 require ( cloud.google.com/go/storage v1.33.0 github.com/ALTree/bigfloat v0.2.0 - github.com/benbjohnson/clock v1.3.5 github.com/chaos-mesh/chaos-mesh/api v0.0.0-20230912033821-30d9600a7db0 github.com/cosmos/btcutil v1.0.5 github.com/go-llsqlite/crawshaw v0.0.0-20230910110433-7e901377eb6c @@ -16,11 +15,12 @@ require ( github.com/google/uuid v1.3.1 github.com/grafana/pyroscope-go v1.0.2 github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 - github.com/grpc-ecosystem/grpc-gateway/v2 v2.17.1 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 github.com/hashicorp/go-retryablehttp v0.7.4 github.com/hashicorp/golang-lru/v2 v2.0.6 github.com/ipfs/go-ds-leveldb v0.5.0 github.com/ipfs/go-log/v2 v2.5.1 + github.com/jonboulle/clockwork v0.2.2 github.com/libp2p/go-libp2p v0.31.0 github.com/libp2p/go-libp2p-kad-dht v0.25.1 github.com/libp2p/go-libp2p-pubsub v0.9.3 @@ -37,9 +37,9 @@ require ( github.com/spacemeshos/api/release/go v1.20.1 github.com/spacemeshos/economics v0.1.1 github.com/spacemeshos/fixed v0.1.1 - github.com/spacemeshos/go-scale v1.1.11 + github.com/spacemeshos/go-scale v1.1.12 github.com/spacemeshos/merkle-tree v0.2.3 - github.com/spacemeshos/poet v0.9.1 + github.com/spacemeshos/poet v0.9.5 github.com/spacemeshos/post v0.9.4 github.com/spf13/afero v1.9.5 github.com/spf13/cobra v1.7.0 @@ -49,16 +49,16 @@ require ( github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 github.com/zeebo/blake3 v0.2.3 go.uber.org/atomic v1.11.0 - go.uber.org/mock v0.2.0 - go.uber.org/zap v1.25.0 + go.uber.org/mock v0.3.0 + go.uber.org/zap v1.26.0 golang.org/x/exp v0.0.0-20230905200255-921286631fa9 golang.org/x/sync v0.3.0 google.golang.org/genproto/googleapis/rpc v0.0.0-20230911183012-2d3300fd4832 - google.golang.org/grpc v1.58.0 + google.golang.org/grpc v1.58.1 google.golang.org/protobuf v1.31.0 - k8s.io/api v0.28.1 - k8s.io/apimachinery v0.28.1 - k8s.io/client-go v0.28.1 + k8s.io/api v0.28.2 + k8s.io/apimachinery v0.28.2 + k8s.io/client-go v0.28.2 sigs.k8s.io/controller-runtime v0.16.1 ) @@ -68,6 +68,7 @@ require ( cloud.google.com/go/compute/metadata v0.2.3 // indirect cloud.google.com/go/iam v1.1.1 // indirect github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect + github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/c0mm4nd/go-ripemd v0.0.0-20200326052756-bd1759ad7d10 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect @@ -193,7 +194,7 @@ require ( golang.org/x/crypto v0.13.0 // indirect golang.org/x/mod v0.12.0 // indirect golang.org/x/net v0.15.0 // indirect - golang.org/x/oauth2 v0.11.0 // indirect + golang.org/x/oauth2 v0.12.0 // indirect golang.org/x/sys v0.12.0 // indirect golang.org/x/term v0.12.0 // indirect golang.org/x/text v0.13.0 // indirect diff --git a/go.sum b/go.sum index 05466bfdc9..ab90f961b9 100644 --- a/go.sum +++ b/go.sum @@ -305,8 +305,8 @@ github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.3 h1:o95KDiV/b1xdkumY5 github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0-rc.3/go.mod h1:hTxjzRcX49ogbTGVJ1sM5mz5s+SSgiGIyL3jjPxl32E= github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.17.1 h1:LSsiG61v9IzzxMkqEr6nrix4miJI62xlRjwT7BYD2SM= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.17.1/go.mod h1:Hbb13e3/WtqQ8U5hLGkek9gJvBLasHuPFI0UEGfnQ10= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 h1:RtRsiaGvWxcwd8y3BiRZxsylPT8hLWZ5SPcfI+3IDNk= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0/go.mod h1:TzP6duP4Py2pHLVPPQp42aoYI92+PCrVotyR5e8Vqlk= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -368,6 +368,8 @@ github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0 github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc= github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= +github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= +github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= @@ -616,12 +618,12 @@ github.com/spacemeshos/economics v0.1.1 h1:BPgMoTaeQ05ME6wEA1+MvXMp+wvXr51bIuN23 github.com/spacemeshos/economics v0.1.1/go.mod h1:76nTjugYRiQ5/eD/DQs2dXPPilp28URMswUKncfdanY= github.com/spacemeshos/fixed v0.1.1 h1:N1y4SUpq1EV+IdJrWJwUCt1oBFzeru/VKVcBsvPc2Fk= github.com/spacemeshos/fixed v0.1.1/go.mod h1:B/moObha9wGnwljZP+w/dYAwzv097aL9VV8Oyv2cM/E= -github.com/spacemeshos/go-scale v1.1.11 h1:esFyFSwSvZe+uian2oMUk0cmKWT8IxVt7jjGWkM1SPI= -github.com/spacemeshos/go-scale v1.1.11/go.mod h1:loK9wrj9IHxATTrVqIyR2o9SB+E9/SAsiDDXuUfvbA8= +github.com/spacemeshos/go-scale v1.1.12 h1:O66yfIBaXSCqbxJYlDP6QSI2s9Lz8rvZjPe3qZZABLo= +github.com/spacemeshos/go-scale v1.1.12/go.mod h1:loK9wrj9IHxATTrVqIyR2o9SB+E9/SAsiDDXuUfvbA8= github.com/spacemeshos/merkle-tree v0.2.3 h1:zGEgOR9nxAzJr0EWjD39QFngwFEOxfxMloEJZtAysas= github.com/spacemeshos/merkle-tree v0.2.3/go.mod h1:VomOcQ5pCBXz7goiWMP5hReyqOfDXGSKbrH2GB9Htww= -github.com/spacemeshos/poet v0.9.1 h1:10wiGjuuGCZq9mAuQjRvNCpE5Uv0KU6yW5eynUCIECU= -github.com/spacemeshos/poet v0.9.1/go.mod h1:ccxzHl5IRSenCSqonPI8M+5vPNwN+o3QU2X41bhbcao= +github.com/spacemeshos/poet v0.9.5 h1:eT2h42o70OTsV4XOiSjbdOKJbatWoILIBSms64hms7U= +github.com/spacemeshos/poet v0.9.5/go.mod h1:ARuJCQRfAEVkq7U6pVziYjAcT6WIgkpzhaUUiP2n1EQ= github.com/spacemeshos/post v0.9.4 h1:l/KGneUnLH5imy2Uml7G9kBnJuzl4ag0ku3U0OWaTxc= github.com/spacemeshos/post v0.9.4/go.mod h1:YjYLMcFFSpxrI86TW2rhyWCWRRFG+8LPiONgARNuaP4= github.com/spacemeshos/sha256-simd v0.1.0 h1:G7Mfu5RYdQiuE+wu4ZyJ7I0TI74uqLhFnKblEnSpjYI= @@ -710,8 +712,8 @@ go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= -go.uber.org/mock v0.2.0 h1:TaP3xedm7JaAgScZO7tlvlKrqT0p7I6OsdGB5YNSMDU= -go.uber.org/mock v0.2.0/go.mod h1:J0y0rp9L3xiff1+ZBfKxlC1fz2+aO16tw0tsDOixfuM= +go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo= +go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -720,8 +722,8 @@ go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9E go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= -go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c= -go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -837,8 +839,8 @@ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210413134643-5e61552d6c78/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.11.0 h1:vPL4xzxBM4niKCW6g9whtaWVXTJf1U5e4aZxxFx/gbU= -golang.org/x/oauth2 v0.11.0/go.mod h1:LdF7O/8bLR/qWK9DrpXmbHLTouvRHK0SgJl0GmDBchk= +golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4= +golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4= golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1113,8 +1115,8 @@ google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -google.golang.org/grpc v1.58.0 h1:32JY8YpPMSR45K+c3o6b8VL73V+rR8k+DeMIr4vRH8o= -google.golang.org/grpc v1.58.0/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= +google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= google.golang.org/grpc/examples v0.0.0-20210424002626-9572fd6faeae/go.mod h1:Ly7ZA/ARzg8fnPU9TyZIxoz33sEUuWX7txiqs8lPTgE= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -1167,14 +1169,14 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.28.1 h1:i+0O8k2NPBCPYaMB+uCkseEbawEt/eFaiRqUx8aB108= -k8s.io/api v0.28.1/go.mod h1:uBYwID+66wiL28Kn2tBjBYQdEU0Xk0z5qF8bIBqk/Dg= +k8s.io/api v0.28.2 h1:9mpl5mOb6vXZvqbQmankOfPIGiudghwCoLl1EYfUZbw= +k8s.io/api v0.28.2/go.mod h1:RVnJBsjU8tcMq7C3iaRSGMeaKt2TWEUXcpIt/90fjEg= k8s.io/apiextensions-apiserver v0.28.1 h1:l2ThkBRjrWpw4f24uq0Da2HaEgqJZ7pcgiEUTKSmQZw= k8s.io/apiextensions-apiserver v0.28.1/go.mod h1:sVvrI+P4vxh2YBBcm8n2ThjNyzU4BQGilCQ/JAY5kGs= -k8s.io/apimachinery v0.28.1 h1:EJD40og3GizBSV3mkIoXQBsws32okPOy+MkRyzh6nPY= -k8s.io/apimachinery v0.28.1/go.mod h1:X0xh/chESs2hP9koe+SdIAcXWcQ+RM5hy0ZynB+yEvw= -k8s.io/client-go v0.28.1 h1:pRhMzB8HyLfVwpngWKE8hDcXRqifh1ga2Z/PU9SXVK8= -k8s.io/client-go v0.28.1/go.mod h1:pEZA3FqOsVkCc07pFVzK076R+P/eXqsgx5zuuRWukNE= +k8s.io/apimachinery v0.28.2 h1:KCOJLrc6gu+wV1BYgwik4AF4vXOlVJPdiqn0yAWWwXQ= +k8s.io/apimachinery v0.28.2/go.mod h1:RdzF87y/ngqk9H4z3EL2Rppv5jj95vGS/HaFXrLDApU= +k8s.io/client-go v0.28.2 h1:DNoYI1vGq0slMBN/SWKMZMw0Rq+0EQW6/AK4v9+3VeY= +k8s.io/client-go v0.28.2/go.mod h1:sMkApowspLuc7omj1FOSUxSoqjr+d5Q0Yc0LOFnYFJY= k8s.io/component-base v0.28.1 h1:LA4AujMlK2mr0tZbQDZkjWbdhTV5bRyEyAFe0TJxlWg= k8s.io/component-base v0.28.1/go.mod h1:jI11OyhbX21Qtbav7JkhehyBsIRfnO8oEgoAR12ArIU= k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= diff --git a/hare/config/config.go b/hare/config/config.go index 11b03bdfe9..ebcd324b64 100644 --- a/hare/config/config.go +++ b/hare/config/config.go @@ -14,7 +14,6 @@ type Config struct { ExpectedLeaders int `mapstructure:"hare-exp-leaders"` // the expected number of leaders LimitIterations int `mapstructure:"hare-limit-iterations"` // limit on number of iterations LimitConcurrent int `mapstructure:"hare-limit-concurrent"` // limit number of concurrent CPs - StopAtxGrading uint32 `mapstructure:"stop-atx-grading"` Hdist uint32 diff --git a/hare/eligibility/mocks.go b/hare/eligibility/mocks.go index ef823ab841..80d1f505cb 100644 --- a/hare/eligibility/mocks.go +++ b/hare/eligibility/mocks.go @@ -1,6 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: ./interface.go - +// +// Generated by this command: +// +// mockgen -typed -package=eligibility -destination=./mocks.go -source=./interface.go +// // Package eligibility is a generated GoMock package. package eligibility @@ -43,7 +47,7 @@ func (m *MockactiveSetCache) Add(key types.EpochID, value *cachedActiveSet) bool } // Add indicates an expected call of Add. -func (mr *MockactiveSetCacheMockRecorder) Add(key, value interface{}) *activeSetCacheAddCall { +func (mr *MockactiveSetCacheMockRecorder) Add(key, value any) *activeSetCacheAddCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Add", reflect.TypeOf((*MockactiveSetCache)(nil).Add), key, value) return &activeSetCacheAddCall{Call: call} @@ -82,7 +86,7 @@ func (m *MockactiveSetCache) Get(key types.EpochID) (*cachedActiveSet, bool) { } // Get indicates an expected call of Get. -func (mr *MockactiveSetCacheMockRecorder) Get(key interface{}) *activeSetCacheGetCall { +func (mr *MockactiveSetCacheMockRecorder) Get(key any) *activeSetCacheGetCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockactiveSetCache)(nil).Get), key) return &activeSetCacheGetCall{Call: call} @@ -143,7 +147,7 @@ func (m *MockvrfVerifier) Verify(nodeID types.NodeID, msg []byte, sig types.VrfS } // Verify indicates an expected call of Verify. -func (mr *MockvrfVerifierMockRecorder) Verify(nodeID, msg, sig interface{}) *vrfVerifierVerifyCall { +func (mr *MockvrfVerifierMockRecorder) Verify(nodeID, msg, sig any) *vrfVerifierVerifyCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Verify", reflect.TypeOf((*MockvrfVerifier)(nil).Verify), nodeID, msg, sig) return &vrfVerifierVerifyCall{Call: call} diff --git a/hare/eligibility/oracle.go b/hare/eligibility/oracle.go index f1ca48918c..00333ec24c 100644 --- a/hare/eligibility/oracle.go +++ b/hare/eligibility/oracle.go @@ -19,6 +19,7 @@ import ( "github.com/spacemeshos/go-spacemesh/miner" "github.com/spacemeshos/go-spacemesh/signing" "github.com/spacemeshos/go-spacemesh/sql" + "github.com/spacemeshos/go-spacemesh/sql/activesets" "github.com/spacemeshos/go-spacemesh/sql/ballots" "github.com/spacemeshos/go-spacemesh/system" ) @@ -421,7 +422,7 @@ func (o *Oracle) computeActiveSet(ctx context.Context, targetEpoch types.EpochID return activeSet, nil } - activeSet, err := miner.ActiveSetFromEpochFirstCertifiedBlock(o.cdb, targetEpoch) + activeSet, err := miner.ActiveSetFromEpochFirstBlock(o.cdb, targetEpoch) if err != nil && !errors.Is(err, sql.ErrNotFound) { return nil, err } @@ -462,11 +463,24 @@ func (o *Oracle) activeSetFromRefBallots(epoch types.EpochID) ([]types.ATXID, er o.Log.With().Debug("beacon mismatch", log.Stringer("local", beacon), log.Object("ballot", ballot)) continue } - for _, id := range ballot.ActiveSet { + actives, err := activesets.Get(o.cdb, ballot.EpochData.ActiveSetHash) + if err != nil { + o.Log.With().Error("failed to get active set", + log.String("actives hash", ballot.EpochData.ActiveSetHash.ShortString()), + log.String("ballot ", ballot.ID().String()), + log.Err(err), + ) + continue + } + for _, id := range actives.Set { activeMap[id] = struct{}{} } } - o.Log.With().Warning("using tortoise active set", log.Uint32("epoch", epoch.Uint32()), log.Stringer("beacon", beacon)) + o.Log.With().Warning("using tortoise active set", + log.Int("actives size", len(activeMap)), + log.Uint32("epoch", epoch.Uint32()), + log.Stringer("beacon", beacon), + ) return maps.Keys(activeMap), nil } diff --git a/hare/eligibility/oracle_test.go b/hare/eligibility/oracle_test.go index 5794c16f2a..e4b5d74a02 100644 --- a/hare/eligibility/oracle_test.go +++ b/hare/eligibility/oracle_test.go @@ -23,10 +23,11 @@ import ( "github.com/spacemeshos/go-spacemesh/log/logtest" "github.com/spacemeshos/go-spacemesh/signing" "github.com/spacemeshos/go-spacemesh/sql" + "github.com/spacemeshos/go-spacemesh/sql/activesets" "github.com/spacemeshos/go-spacemesh/sql/atxs" "github.com/spacemeshos/go-spacemesh/sql/ballots" "github.com/spacemeshos/go-spacemesh/sql/blocks" - "github.com/spacemeshos/go-spacemesh/sql/certificates" + "github.com/spacemeshos/go-spacemesh/sql/layers" "github.com/spacemeshos/go-spacemesh/system/mocks" ) @@ -64,7 +65,7 @@ func defaultOracle(t testing.TB) *testOracle { return to } -func createBallots(tb testing.TB, cdb *datastore.CachedDB, lid types.LayerID, activeSet []types.ATXID, miners []types.NodeID) []*types.Ballot { +func createBallots(tb testing.TB, cdb *datastore.CachedDB, lid types.LayerID, activeSet types.ATXIDList, miners []types.NodeID) []*types.Ballot { tb.Helper() numBallots := ballotsPerLayer if len(activeSet) < numBallots { @@ -76,12 +77,15 @@ func createBallots(tb testing.TB, cdb *datastore.CachedDB, lid types.LayerID, ac b.Layer = lid b.AtxID = activeSet[i] b.RefBallot = types.EmptyBallotID - b.EpochData = &types.EpochData{} - b.ActiveSet = activeSet + b.EpochData = &types.EpochData{ActiveSetHash: activeSet.Hash()} b.Signature = types.RandomEdSignature() b.SmesherID = miners[i] require.NoError(tb, b.Initialize()) require.NoError(tb, ballots.Add(cdb, b)) + activesets.Add(cdb, b.EpochData.ActiveSetHash, &types.EpochActiveSet{ + Epoch: lid.GetEpoch(), + Set: activeSet, + }) result = append(result, b) } return result @@ -99,7 +103,7 @@ func createBlock(tb testing.TB, cdb *datastore.CachedDB, blts []*types.Ballot) { } block.Initialize() require.NoError(tb, blocks.Add(cdb, block)) - require.NoError(tb, certificates.Add(cdb, blts[0].Layer, &types.Certificate{BlockID: block.ID()})) + require.NoError(tb, layers.SetApplied(cdb, block.LayerIndex, block.ID())) } func createLayerData(tb testing.TB, cdb *datastore.CachedDB, lid types.LayerID, numMiners int) []types.NodeID { @@ -659,11 +663,10 @@ func TestActiveSetDD(t *testing.T) { t.Parallel() target := types.EpochID(4) - bgen := func(id types.BallotID, lid types.LayerID, node types.NodeID, beacon types.Beacon, atxs []types.ATXID, option ...func(*types.Ballot)) types.Ballot { + bgen := func(id types.BallotID, lid types.LayerID, node types.NodeID, beacon types.Beacon, atxs types.ATXIDList, option ...func(*types.Ballot)) types.Ballot { ballot := types.Ballot{} ballot.Layer = lid - ballot.EpochData = &types.EpochData{Beacon: beacon} - ballot.ActiveSet = atxs + ballot.EpochData = &types.EpochData{Beacon: beacon, ActiveSetHash: atxs.Hash()} ballot.SmesherID = node ballot.SetID(id) for _, opt := range option { @@ -693,12 +696,13 @@ func TestActiveSetDD(t *testing.T) { beacon types.Beacon // local beacon ballots []types.Ballot atxs []*types.VerifiedActivationTx + actives []types.ATXIDList expect any }{ { - "merged activesets", - types.Beacon{1}, - []types.Ballot{ + desc: "merged activesets", + beacon: types.Beacon{1}, + ballots: []types.Ballot{ bgen( types.BallotID{1}, target.FirstLayer(), @@ -714,17 +718,18 @@ func TestActiveSetDD(t *testing.T) { []types.ATXID{{2}, {3}}, ), }, - []*types.VerifiedActivationTx{ + atxs: []*types.VerifiedActivationTx{ agen(types.ATXID{1}, types.NodeID{1}), agen(types.ATXID{2}, types.NodeID{2}), agen(types.ATXID{3}, types.NodeID{3}), }, - []types.ATXID{{1}, {2}, {3}}, + actives: []types.ATXIDList{{{1}, {2}}, {{2}, {3}}}, + expect: []types.ATXID{{1}, {2}, {3}}, }, { - "filter by beacon", - types.Beacon{1}, - []types.Ballot{ + desc: "filter by beacon", + beacon: types.Beacon{1}, + ballots: []types.Ballot{ bgen( types.BallotID{1}, target.FirstLayer(), @@ -740,16 +745,17 @@ func TestActiveSetDD(t *testing.T) { []types.ATXID{{2}, {3}}, ), }, - []*types.VerifiedActivationTx{ + atxs: []*types.VerifiedActivationTx{ agen(types.ATXID{1}, types.NodeID{1}), agen(types.ATXID{2}, types.NodeID{2}), }, - []types.ATXID{{1}, {2}}, + actives: []types.ATXIDList{{{1}, {2}}, {{2}, {3}}}, + expect: []types.ATXID{{1}, {2}}, }, { - "no local beacon", - types.EmptyBeacon, - []types.Ballot{ + desc: "no local beacon", + beacon: types.EmptyBeacon, + ballots: []types.Ballot{ bgen( types.BallotID{1}, target.FirstLayer(), @@ -765,13 +771,14 @@ func TestActiveSetDD(t *testing.T) { []types.ATXID{{2}, {3}}, ), }, - []*types.VerifiedActivationTx{}, - "not found", + atxs: []*types.VerifiedActivationTx{}, + actives: []types.ATXIDList{{{1}, {2}}, {{2}, {3}}}, + expect: "not found", }, { - "unknown atxs", - types.Beacon{1}, - []types.Ballot{ + desc: "unknown atxs", + beacon: types.Beacon{1}, + ballots: []types.Ballot{ bgen( types.BallotID{1}, target.FirstLayer(), @@ -787,13 +794,14 @@ func TestActiveSetDD(t *testing.T) { []types.ATXID{{2}, {3}}, ), }, - []*types.VerifiedActivationTx{}, - "get ATX", + atxs: []*types.VerifiedActivationTx{}, + actives: []types.ATXIDList{{{1}, {2}}, {{2}, {3}}}, + expect: "get ATX", }, { - "ballot no epoch data", - types.Beacon{1}, - []types.Ballot{ + desc: "ballot no epoch data", + beacon: types.Beacon{1}, + ballots: []types.Ballot{ bgen( types.BallotID{1}, target.FirstLayer(), @@ -812,16 +820,17 @@ func TestActiveSetDD(t *testing.T) { []types.ATXID{{2}, {3}}, ), }, - []*types.VerifiedActivationTx{ + atxs: []*types.VerifiedActivationTx{ agen(types.ATXID{2}, types.NodeID{2}), agen(types.ATXID{3}, types.NodeID{3}), }, - []types.ATXID{{2}, {3}}, + actives: []types.ATXIDList{{{2}, {3}}}, + expect: []types.ATXID{{2}, {3}}, }, { - "wrong target epoch", - types.Beacon{1}, - []types.Ballot{ + desc: "wrong target epoch", + beacon: types.Beacon{1}, + ballots: []types.Ballot{ bgen( types.BallotID{1}, target.FirstLayer(), @@ -830,18 +839,22 @@ func TestActiveSetDD(t *testing.T) { []types.ATXID{{1}}, ), }, - []*types.VerifiedActivationTx{ + atxs: []*types.VerifiedActivationTx{ agen(types.ATXID{1}, types.NodeID{1}, func(verified *types.VerifiedActivationTx) { verified.PublishEpoch = target }), }, - "no epoch atx found", + actives: []types.ATXIDList{{{1}}}, + expect: "no epoch atx found", }, } { tc := tc t.Run(tc.desc, func(t *testing.T) { t.Parallel() oracle := defaultOracle(t) + for _, actives := range tc.actives { + require.NoError(t, activesets.Add(oracle.cdb, actives.Hash(), &types.EpochActiveSet{Set: actives})) + } for _, ballot := range tc.ballots { require.NoError(t, ballots.Add(oracle.cdb, &ballot)) } diff --git a/hare/hare.go b/hare/hare.go index a7d75b1b55..d5c0a012c9 100644 --- a/hare/hare.go +++ b/hare/hare.go @@ -16,7 +16,6 @@ import ( "github.com/spacemeshos/go-spacemesh/hare/config" "github.com/spacemeshos/go-spacemesh/log" "github.com/spacemeshos/go-spacemesh/malfeasance" - "github.com/spacemeshos/go-spacemesh/miner" "github.com/spacemeshos/go-spacemesh/p2p/pubsub" "github.com/spacemeshos/go-spacemesh/signing" "github.com/spacemeshos/go-spacemesh/sql" @@ -393,7 +392,7 @@ func (h *Hare) onTick(ctx context.Context, lid types.LayerID) (bool, error) { report: h.outputChan, wc: h.wcChan, } - props := goodProposals(ctx, h.Log, h.msh, h.nodeID, lid, types.LayerID(h.config.StopAtxGrading), beacon, h.layerClock.LayerToTime(lid.GetEpoch().FirstLayer()), h.config.WakeupDelta) + props := goodProposals(ctx, h.Log, h.msh, h.nodeID, lid, beacon) preNumProposals.Add(float64(len(props))) set := NewSet(props) cp := h.factory(ctx, h.config, lid, set, h.rolacle, et, h.sign, h.publisher, comm, clock) @@ -456,10 +455,8 @@ func goodProposals( logger log.Log, msh mesh, nodeID types.NodeID, - lid, stopGrading types.LayerID, + lid types.LayerID, epochBeacon types.Beacon, - epochStart time.Time, - networkDelay time.Duration, ) []types.ProposalID { props, err := msh.Proposals(lid) if err != nil { @@ -473,7 +470,6 @@ func goodProposals( var ( beacon types.Beacon - activeSet []types.ATXID result []types.ProposalID ownHdr *types.ActivationTxHeader ownTickHeight = uint64(math.MaxUint64) @@ -492,7 +488,6 @@ func goodProposals( for _, p := range props { atxs[p.AtxID]++ } - cache := map[types.ATXID]miner.AtxGrade{} for _, p := range props { if p.IsMalicious() { logger.With().Warning("not voting on proposal from malicious identity", @@ -527,7 +522,6 @@ func goodProposals( } if p.EpochData != nil { beacon = p.EpochData.Beacon - activeSet = p.ActiveSet } else if p.RefBallot == types.EmptyBallotID { logger.With().Error("proposal missing ref ballot", log.Context(ctx), @@ -553,37 +547,7 @@ func goodProposals( return []types.ProposalID{} } else { beacon = refBallot.EpochData.Beacon - activeSet = refBallot.ActiveSet } - - if len(activeSet) == 0 { - logger.With().Error("proposal missing active set", - log.Context(ctx), - p.ID(), - lid, - ) - return []types.ProposalID{} - } - if lid < stopGrading { - if evil, err := gradeActiveSet(cache, activeSet, msh, epochStart, networkDelay); err != nil { - logger.With().Error("failed to grade active set", - log.Context(ctx), - lid, - p.ID(), - log.Err(err), - ) - return []types.ProposalID{} - } else if evil != types.EmptyATXID { - logger.With().Warning("proposal has grade 0 active set", - log.Context(ctx), - lid, - p.ID(), - log.Stringer("evil atx", evil), - ) - continue - } - } - if beacon == epochBeacon { result = append(result, p.ID()) } else { @@ -598,29 +562,6 @@ func goodProposals( return result } -func gradeActiveSet(cache map[types.ATXID]miner.AtxGrade, activeSet []types.ATXID, msh mesh, epochStart time.Time, networkDelay time.Duration) (types.ATXID, error) { - for _, id := range activeSet { - var grade miner.AtxGrade - if g, ok := cache[id]; ok { - grade = g - } else { - hdr, err := msh.GetAtxHeader(id) - if err != nil { - return types.EmptyATXID, fmt.Errorf("get header %v: %w", id, err) - } - grade, err = miner.GradeAtx(msh, hdr.NodeID, hdr.Received, epochStart, networkDelay) - if err != nil { - return types.EmptyATXID, fmt.Errorf("grade %v: %w", id, err) - } - cache[id] = grade - } - if grade == miner.Evil { - return id, nil - } - } - return types.EmptyATXID, nil -} - var ( errTooOld = errors.New("layer has already been evacuated from buffer") errNoResult = errors.New("no result for the requested layer") diff --git a/hare/hare_test.go b/hare/hare_test.go index 2bf2b49d52..3a56618c22 100644 --- a/hare/hare_test.go +++ b/hare/hare_test.go @@ -88,11 +88,9 @@ func randomProposal(lyrID types.LayerID, beacon types.Beacon) *types.Proposal { Layer: lyrID, AtxID: types.RandomATXID(), EpochData: &types.EpochData{ - ActiveSetHash: types.RandomHash(), - Beacon: beacon, + Beacon: beacon, }, }, - ActiveSet: types.RandomActiveSet(10), }, }, } @@ -570,11 +568,6 @@ func TestHare_goodProposals(t *testing.T) { pList[i].EpochData = nil pList[i].RefBallot = refBallot.ID() mockMesh.EXPECT().Ballot(pList[1].RefBallot).Return(refBallot, nil) - for _, id := range refBallot.ActiveSet { - nodeID := types.RandomNodeID() - mockMesh.EXPECT().GetAtxHeader(id).Return(&types.ActivationTxHeader{BaseTickHeight: 11, TickCount: 1, NodeID: nodeID}, nil).AnyTimes() - mockMesh.EXPECT().GetMalfeasanceProof(nodeID).AnyTimes() - } } } for i, p := range pList { @@ -585,13 +578,6 @@ func TestHare_goodProposals(t *testing.T) { } else { mockMesh.EXPECT().GetAtxHeader(p.AtxID).Return(&types.ActivationTxHeader{BaseTickHeight: tc.baseHeights[i], TickCount: 1}, nil) } - if p.EpochData != nil { - for _, id := range p.ActiveSet { - nodeID := types.RandomNodeID() - mockMesh.EXPECT().GetAtxHeader(id).Return(&types.ActivationTxHeader{BaseTickHeight: 11, TickCount: 1, NodeID: nodeID}, nil).AnyTimes() - mockMesh.EXPECT().GetMalfeasanceProof(nodeID).AnyTimes() - } - } } nodeID := types.NodeID{1, 2, 3} mockMesh.EXPECT().GetEpochAtx(lyrID.GetEpoch()-1, nodeID).Return(&types.ActivationTxHeader{BaseTickHeight: nodeBaseHeight, TickCount: 1}, nil) @@ -601,90 +587,12 @@ func TestHare_goodProposals(t *testing.T) { for _, i := range tc.expected { expected = append(expected, pList[i].ID()) } - got := goodProposals(context.Background(), logtest.New(t), mockMesh, nodeID, lyrID, types.LayerID(0), nodeBeacon, time.Now(), time.Second) + got := goodProposals(context.Background(), logtest.New(t), mockMesh, nodeID, lyrID, nodeBeacon) require.ElementsMatch(t, expected, got) }) } } -func TestHare_goodProposals_gradedAtxs(t *testing.T) { - beacon := types.RandomBeacon() - tickHeight := uint64(11) - lyrID := types.GetEffectiveGenesis().Add(1) - epochStart := time.Now() - mockMesh := newMockMesh(t) - activeSet := types.RandomActiveSet(10) - pList := []*types.Proposal{ - randomProposal(lyrID, beacon), - randomProposal(lyrID, beacon), - randomProposal(lyrID, beacon), - randomProposal(lyrID, beacon), - randomProposal(lyrID, beacon), - randomProposal(lyrID, beacon), - randomProposal(lyrID, beacon), - } - for _, p := range pList { - mockMesh.EXPECT().GetAtxHeader(p.AtxID).Return(&types.ActivationTxHeader{BaseTickHeight: 11, TickCount: 1, NodeID: p.SmesherID}, nil) - } - - delay := time.Second - goodTime := epochStart.Add(-4*delay - time.Nanosecond) - acceptableTime := epochStart.Add(-3*delay - time.Nanosecond) - evilTime := epochStart.Add(-3 * delay) - - for i := 0; i < 4; i++ { - good := &types.ActivationTxHeader{BaseTickHeight: tickHeight, TickCount: 1, Received: goodTime, NodeID: types.NodeID{byte(i + 1)}} - mockMesh.EXPECT().GetAtxHeader(activeSet[i]).Return(good, nil).AnyTimes() - mockMesh.EXPECT().GetMalfeasanceProof(good.NodeID).Return(nil, nil).AnyTimes() - } - - earlyAtxLateMalicious := &types.ActivationTxHeader{BaseTickHeight: tickHeight, TickCount: 1, Received: goodTime, NodeID: types.NodeID{5}} - mockMesh.EXPECT().GetAtxHeader(activeSet[4]).Return(earlyAtxLateMalicious, nil).AnyTimes() - proof1 := &types.MalfeasanceProof{} - proof1.SetReceived(epochStart) - mockMesh.EXPECT().GetMalfeasanceProof(earlyAtxLateMalicious.NodeID).Return(proof1, nil).AnyTimes() - - earlyAtxMalicious := &types.ActivationTxHeader{BaseTickHeight: tickHeight, TickCount: 1, Received: goodTime, NodeID: types.NodeID{6}} - mockMesh.EXPECT().GetAtxHeader(activeSet[5]).Return(earlyAtxMalicious, nil).AnyTimes() - proof2 := &types.MalfeasanceProof{} - proof2.SetReceived(epochStart.Add(-delay)) - mockMesh.EXPECT().GetMalfeasanceProof(earlyAtxMalicious.NodeID).Return(proof2, nil).AnyTimes() - - acceptable := &types.ActivationTxHeader{BaseTickHeight: tickHeight, TickCount: 1, Received: acceptableTime, NodeID: types.NodeID{7}} - mockMesh.EXPECT().GetAtxHeader(activeSet[6]).Return(acceptable, nil).AnyTimes() - mockMesh.EXPECT().GetMalfeasanceProof(acceptable.NodeID).Return(nil, nil).AnyTimes() - - acceptableMalicious := &types.ActivationTxHeader{BaseTickHeight: tickHeight, TickCount: 1, Received: acceptableTime, NodeID: types.NodeID{8}} - mockMesh.EXPECT().GetAtxHeader(activeSet[7]).Return(acceptableMalicious, nil).AnyTimes() - proof3 := &types.MalfeasanceProof{} - proof3.SetReceived(epochStart.Add(-delay)) - mockMesh.EXPECT().GetMalfeasanceProof(acceptableMalicious.NodeID).Return(proof3, nil).AnyTimes() - - malicious := &types.ActivationTxHeader{BaseTickHeight: tickHeight, TickCount: 1, Received: goodTime, NodeID: types.NodeID{9}} - mockMesh.EXPECT().GetAtxHeader(activeSet[8]).Return(malicious, nil).AnyTimes() - proof4 := &types.MalfeasanceProof{} - proof4.SetReceived(epochStart.Add(-delay - time.Nanosecond)) - mockMesh.EXPECT().GetMalfeasanceProof(malicious.NodeID).Return(proof4, nil).AnyTimes() - - evil := &types.ActivationTxHeader{BaseTickHeight: tickHeight, TickCount: 1, Received: evilTime, NodeID: types.NodeID{10}} - mockMesh.EXPECT().GetAtxHeader(activeSet[9]).Return(evil, nil).AnyTimes() - mockMesh.EXPECT().GetMalfeasanceProof(evil.NodeID).Return(nil, nil).AnyTimes() - - pList[0].ActiveSet = activeSet[:4] - pList[1].ActiveSet = activeSet[:5] - pList[2].ActiveSet = activeSet[:6] - pList[3].ActiveSet = activeSet[:7] - pList[4].ActiveSet = activeSet[:8] - pList[5].ActiveSet = activeSet[:9] - pList[6].ActiveSet = activeSet - - nodeID := types.NodeID{1, 2, 3} - mockMesh.EXPECT().GetEpochAtx(lyrID.GetEpoch()-1, nodeID).Return(&types.ActivationTxHeader{BaseTickHeight: tickHeight, TickCount: 1}, nil) - mockMesh.EXPECT().Proposals(lyrID).Return(pList, nil) - got := goodProposals(context.Background(), logtest.New(t), mockMesh, nodeID, lyrID, lyrID+1, beacon, epochStart, delay) - require.ElementsMatch(t, types.ToProposalIDs(pList[:5]), got) -} - func TestHare_outputBuffer(t *testing.T) { h := createTestHare(t, newMockMesh(t), config.DefaultConfig(), newMockClock(), noopPubSub(t), t.Name()) var lyr types.LayerID diff --git a/hare/mocks/mocks.go b/hare/mocks/mocks.go index 6d3f8ce386..04b4b4706d 100644 --- a/hare/mocks/mocks.go +++ b/hare/mocks/mocks.go @@ -1,6 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: ./interfaces.go - +// +// Generated by this command: +// +// mockgen -typed -package=mocks -destination=./mocks/mocks.go -source=./interfaces.go +// // Package mocks is a generated GoMock package. package mocks @@ -43,7 +47,7 @@ func (m *MocklayerPatrol) SetHareInCharge(arg0 types.LayerID) { } // SetHareInCharge indicates an expected call of SetHareInCharge. -func (mr *MocklayerPatrolMockRecorder) SetHareInCharge(arg0 interface{}) *layerPatrolSetHareInChargeCall { +func (mr *MocklayerPatrolMockRecorder) SetHareInCharge(arg0 any) *layerPatrolSetHareInChargeCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetHareInCharge", reflect.TypeOf((*MocklayerPatrol)(nil).SetHareInCharge), arg0) return &layerPatrolSetHareInChargeCall{Call: call} @@ -105,7 +109,7 @@ func (m *MockRolacle) CalcEligibility(arg0 context.Context, arg1 types.LayerID, } // CalcEligibility indicates an expected call of CalcEligibility. -func (mr *MockRolacleMockRecorder) CalcEligibility(arg0, arg1, arg2, arg3, arg4, arg5 interface{}) *RolacleCalcEligibilityCall { +func (mr *MockRolacleMockRecorder) CalcEligibility(arg0, arg1, arg2, arg3, arg4, arg5 any) *RolacleCalcEligibilityCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CalcEligibility", reflect.TypeOf((*MockRolacle)(nil).CalcEligibility), arg0, arg1, arg2, arg3, arg4, arg5) return &RolacleCalcEligibilityCall{Call: call} @@ -144,7 +148,7 @@ func (m *MockRolacle) IsIdentityActiveOnConsensusView(arg0 context.Context, arg1 } // IsIdentityActiveOnConsensusView indicates an expected call of IsIdentityActiveOnConsensusView. -func (mr *MockRolacleMockRecorder) IsIdentityActiveOnConsensusView(arg0, arg1, arg2 interface{}) *RolacleIsIdentityActiveOnConsensusViewCall { +func (mr *MockRolacleMockRecorder) IsIdentityActiveOnConsensusView(arg0, arg1, arg2 any) *RolacleIsIdentityActiveOnConsensusViewCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsIdentityActiveOnConsensusView", reflect.TypeOf((*MockRolacle)(nil).IsIdentityActiveOnConsensusView), arg0, arg1, arg2) return &RolacleIsIdentityActiveOnConsensusViewCall{Call: call} @@ -183,7 +187,7 @@ func (m *MockRolacle) Proof(arg0 context.Context, arg1 types.LayerID, arg2 uint3 } // Proof indicates an expected call of Proof. -func (mr *MockRolacleMockRecorder) Proof(arg0, arg1, arg2 interface{}) *RolacleProofCall { +func (mr *MockRolacleMockRecorder) Proof(arg0, arg1, arg2 any) *RolacleProofCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Proof", reflect.TypeOf((*MockRolacle)(nil).Proof), arg0, arg1, arg2) return &RolacleProofCall{Call: call} @@ -222,7 +226,7 @@ func (m *MockRolacle) Validate(arg0 context.Context, arg1 types.LayerID, arg2 ui } // Validate indicates an expected call of Validate. -func (mr *MockRolacleMockRecorder) Validate(arg0, arg1, arg2, arg3, arg4, arg5, arg6 interface{}) *RolacleValidateCall { +func (mr *MockRolacleMockRecorder) Validate(arg0, arg1, arg2, arg3, arg4, arg5, arg6 any) *RolacleValidateCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Validate", reflect.TypeOf((*MockRolacle)(nil).Validate), arg0, arg1, arg2, arg3, arg4, arg5, arg6) return &RolacleValidateCall{Call: call} @@ -284,7 +288,7 @@ func (m *MockstateQuerier) IsIdentityActiveOnConsensusView(arg0 context.Context, } // IsIdentityActiveOnConsensusView indicates an expected call of IsIdentityActiveOnConsensusView. -func (mr *MockstateQuerierMockRecorder) IsIdentityActiveOnConsensusView(arg0, arg1, arg2 interface{}) *stateQuerierIsIdentityActiveOnConsensusViewCall { +func (mr *MockstateQuerierMockRecorder) IsIdentityActiveOnConsensusView(arg0, arg1, arg2 any) *stateQuerierIsIdentityActiveOnConsensusViewCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsIdentityActiveOnConsensusView", reflect.TypeOf((*MockstateQuerier)(nil).IsIdentityActiveOnConsensusView), arg0, arg1, arg2) return &stateQuerierIsIdentityActiveOnConsensusViewCall{Call: call} @@ -346,7 +350,7 @@ func (m *Mockmesh) Ballot(arg0 types.BallotID) (*types.Ballot, error) { } // Ballot indicates an expected call of Ballot. -func (mr *MockmeshMockRecorder) Ballot(arg0 interface{}) *meshBallotCall { +func (mr *MockmeshMockRecorder) Ballot(arg0 any) *meshBallotCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Ballot", reflect.TypeOf((*Mockmesh)(nil).Ballot), arg0) return &meshBallotCall{Call: call} @@ -423,7 +427,7 @@ func (m *Mockmesh) GetAtxHeader(arg0 types.ATXID) (*types.ActivationTxHeader, er } // GetAtxHeader indicates an expected call of GetAtxHeader. -func (mr *MockmeshMockRecorder) GetAtxHeader(arg0 interface{}) *meshGetAtxHeaderCall { +func (mr *MockmeshMockRecorder) GetAtxHeader(arg0 any) *meshGetAtxHeaderCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAtxHeader", reflect.TypeOf((*Mockmesh)(nil).GetAtxHeader), arg0) return &meshGetAtxHeaderCall{Call: call} @@ -462,7 +466,7 @@ func (m *Mockmesh) GetEpochAtx(arg0 types.EpochID, arg1 types.NodeID) (*types.Ac } // GetEpochAtx indicates an expected call of GetEpochAtx. -func (mr *MockmeshMockRecorder) GetEpochAtx(arg0, arg1 interface{}) *meshGetEpochAtxCall { +func (mr *MockmeshMockRecorder) GetEpochAtx(arg0, arg1 any) *meshGetEpochAtxCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEpochAtx", reflect.TypeOf((*Mockmesh)(nil).GetEpochAtx), arg0, arg1) return &meshGetEpochAtxCall{Call: call} @@ -501,7 +505,7 @@ func (m *Mockmesh) GetMalfeasanceProof(arg0 types.NodeID) (*types.MalfeasancePro } // GetMalfeasanceProof indicates an expected call of GetMalfeasanceProof. -func (mr *MockmeshMockRecorder) GetMalfeasanceProof(arg0 interface{}) *meshGetMalfeasanceProofCall { +func (mr *MockmeshMockRecorder) GetMalfeasanceProof(arg0 any) *meshGetMalfeasanceProofCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMalfeasanceProof", reflect.TypeOf((*Mockmesh)(nil).GetMalfeasanceProof), arg0) return &meshGetMalfeasanceProofCall{Call: call} @@ -540,7 +544,7 @@ func (m *Mockmesh) Proposals(arg0 types.LayerID) ([]*types.Proposal, error) { } // Proposals indicates an expected call of Proposals. -func (mr *MockmeshMockRecorder) Proposals(arg0 interface{}) *meshProposalsCall { +func (mr *MockmeshMockRecorder) Proposals(arg0 any) *meshProposalsCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Proposals", reflect.TypeOf((*Mockmesh)(nil).Proposals), arg0) return &meshProposalsCall{Call: call} @@ -601,7 +605,7 @@ func (m *MockweakCoin) Set(arg0 types.LayerID, arg1 bool) error { } // Set indicates an expected call of Set. -func (mr *MockweakCoinMockRecorder) Set(arg0, arg1 interface{}) *weakCoinSetCall { +func (mr *MockweakCoinMockRecorder) Set(arg0, arg1 any) *weakCoinSetCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Set", reflect.TypeOf((*MockweakCoin)(nil).Set), arg0, arg1) return &weakCoinSetCall{Call: call} diff --git a/hare3/hare.go b/hare3/hare.go index 25da02e4d8..2895cfa615 100644 --- a/hare3/hare.go +++ b/hare3/hare.go @@ -8,7 +8,7 @@ import ( "sync" "time" - "github.com/benbjohnson/clock" + "github.com/jonboulle/clockwork" "go.uber.org/zap" "go.uber.org/zap/zapcore" "golang.org/x/sync/errgroup" @@ -100,7 +100,7 @@ type WeakCoinOutput struct { type Opt func(*Hare) -func WithWallclock(clock clock.Clock) Opt { +func WithWallclock(clock clockwork.Clock) Opt { return func(hr *Hare) { hr.wallclock = clock } @@ -153,7 +153,7 @@ func New( config: DefaultConfig(), log: zap.NewNop(), - wallclock: clock.New(), + wallclock: clockwork.NewRealClock(), nodeclock: nodeclock, pubsub: pubsub, @@ -188,7 +188,7 @@ type Hare struct { // options config Config log *zap.Logger - wallclock clock.Clock + wallclock clockwork.Clock // dependencies nodeclock nodeclock @@ -370,7 +370,7 @@ func (h *Hare) run(layer types.LayerID, beacon types.Beacon, proto *protocol) er h.log.Debug("active in preround", zap.Uint32("lid", layer.Uint32())) // initial set is not needed if node is not active in preround select { - case <-h.wallclock.After(h.wallclock.Until(walltime)): + case <-h.wallclock.After(walltime.Sub(h.wallclock.Now())): case <-h.ctx.Done(): return h.ctx.Err() } @@ -381,24 +381,24 @@ func (h *Hare) run(layer types.LayerID, beacon types.Beacon, proto *protocol) er if err := h.onOutput(layer, current, proto.Next(vrf != nil), vrf); err != nil { return err } - walltime = walltime.Add(h.config.RoundDuration) result := false for { + walltime = walltime.Add(h.config.RoundDuration) + current := proto.IterRound + var vrf *types.HareEligibility + if current.IsMessageRound() { + start := time.Now() + vrf = h.oracle.active(h.signer.NodeID(), layer, current) + activeLatency.Observe(time.Since(start).Seconds()) + } + h.tracer.OnActive(vrf) select { - case <-h.wallclock.After(h.wallclock.Until(walltime)): + case <-h.wallclock.After(walltime.Sub(h.wallclock.Now())): h.log.Debug("execute round", zap.Uint32("lid", layer.Uint32()), zap.Uint8("iter", proto.Iter), zap.Stringer("round", proto.Round), + zap.Bool("active", vrf != nil), ) - current := proto.IterRound - var vrf *types.HareEligibility - if current.IsMessageRound() { - start := time.Now() - vrf = h.oracle.active(h.signer.NodeID(), layer, current) - activeLatency.Observe(time.Since(start).Seconds()) - } - h.tracer.OnActive(vrf) - out := proto.Next(vrf != nil) if out.result != nil { result = true @@ -416,7 +416,6 @@ func (h *Hare) run(layer types.LayerID, beacon types.Beacon, proto *protocol) er return fmt.Errorf("hare failed to reach consensus in %d iterations", h.config.IterationsLimit) } - walltime = walltime.Add(h.config.RoundDuration) case <-h.ctx.Done(): return nil } @@ -428,23 +427,17 @@ func (h *Hare) onOutput(layer types.LayerID, ir IterRound, out output, vrf *type out.message.Layer = layer out.message.Eligibility = *vrf out.message.Sender = h.signer.NodeID() + out.message.Signature = h.signer.Sign(signing.HARE, out.message.ToMetadata().ToBytes()) + if err := h.pubsub.Publish(h.ctx, h.config.ProtocolName, out.message.ToBytes()); err != nil { + h.log.Error("failed to publish", zap.Inline(out.message), zap.Error(err)) + } } h.log.Debug("round output", zap.Uint32("lid", layer.Uint32()), zap.Uint8("iter", ir.Iter), zap.Stringer("round", ir.Round), zap.Inline(&out), - zap.Bool("active", vrf != nil), ) - if out.message != nil { - h.eg.Go(func() error { - out.message.Signature = h.signer.Sign(signing.HARE, out.message.ToMetadata().ToBytes()) - if err := h.pubsub.Publish(h.ctx, h.config.ProtocolName, out.message.ToBytes()); err != nil { - h.log.Error("failed to publish", zap.Inline(out.message), zap.Error(err)) - } - h.tracer.OnMessageSent(out.message) - return nil - }) - } + h.tracer.OnMessageSent(out.message) if out.coin != nil { select { case <-h.ctx.Done(): diff --git a/hare3/hare_test.go b/hare3/hare_test.go index f36051ec61..e16000c8e8 100644 --- a/hare3/hare_test.go +++ b/hare3/hare_test.go @@ -9,7 +9,7 @@ import ( "testing" "time" - "github.com/benbjohnson/clock" + "github.com/jonboulle/clockwork" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "go.uber.org/zap/zapcore" @@ -109,7 +109,7 @@ type node struct { t *tester i int - clock *clock.Mock + clock clockwork.FakeClock nclock *testNodeClock signer *signing.EdSigner vrfsigner *signing.VRFSigner @@ -126,8 +126,7 @@ type node struct { } func (n *node) withClock() *node { - n.clock = clock.NewMock() - n.clock.Set(n.t.start) + n.clock = clockwork.NewFakeClockAt(n.t.start) return n } @@ -266,8 +265,6 @@ type lockstepCluster struct { } timestamp time.Time - start chan struct{} - complete chan struct{} } func (cl *lockstepCluster) addNode(n *node) { @@ -314,19 +311,13 @@ func (cl *lockstepCluster) addEquivocators(n int) *lockstepCluster { } func (cl *lockstepCluster) nogossip() { - cl.start = make(chan struct{}, len(cl.nodes)) - cl.complete = make(chan struct{}, len(cl.nodes)) for _, n := range cl.nodes { require.NoError(cl.t, beacons.Add(n.db, cl.t.genesis.GetEpoch()+1, cl.t.beacon)) - n.mpublisher.EXPECT().Publish(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(ctx context.Context, _ string, msg []byte) error { - cl.timedReceive(cl.start) - cl.timedSend(cl.complete) - return nil - }).AnyTimes() + n.mpublisher.EXPECT().Publish(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() } } -func (cl *lockstepCluster) activeSet() []types.ATXID { +func (cl *lockstepCluster) activeSet() types.ATXIDList { var ids []types.ATXID unique := map[types.ATXID]struct{}{} for _, n := range cl.nodes { @@ -351,9 +342,9 @@ func (cl *lockstepCluster) genProposals(lid types.LayerID) { } proposal := &types.Proposal{} proposal.Layer = lid - proposal.ActiveSet = active proposal.EpochData = &types.EpochData{ - Beacon: cl.t.beacon, + Beacon: cl.t.beacon, + ActiveSetHash: active.Hash(), } proposal.AtxID = n.atx.ID() proposal.SmesherID = n.signer.NodeID() @@ -381,8 +372,6 @@ func (cl *lockstepCluster) genProposals(lid types.LayerID) { } func (cl *lockstepCluster) setup() { - cl.start = make(chan struct{}, len(cl.nodes)) - cl.complete = make(chan struct{}, len(cl.nodes)) active := cl.activeSet() for _, n := range cl.nodes { require.NoError(cl.t, beacons.Add(n.db, cl.t.genesis.GetEpoch()+1, cl.t.beacon)) @@ -394,11 +383,9 @@ func (cl *lockstepCluster) setup() { } n.oracle.UpdateActiveSet(cl.t.genesis.GetEpoch()+1, active) n.mpublisher.EXPECT().Publish(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(ctx context.Context, _ string, msg []byte) error { - cl.timedReceive(cl.start) for _, other := range cl.nodes { other.hare.Handler(ctx, "self", msg) } - cl.timedSend(cl.complete) return nil }).AnyTimes() } @@ -410,54 +397,32 @@ func (cl *lockstepCluster) movePreround(layer types.LayerID) { Add(cl.t.cfg.PreroundDelay) for _, n := range cl.nodes { n.nclock.StartLayer(layer) - n.clock.Set(cl.timestamp) + n.clock.Advance(cl.timestamp.Sub(n.clock.Now())) } - send := 0 for _, n := range cl.nodes { - if n.tracer.waitEligibility() != nil { - send++ - } - } - for i := 0; i < send; i++ { - cl.timedSend(cl.start) + n.tracer.waitEligibility() } - for i := 0; i < send; i++ { - cl.timedReceive(cl.complete) + for _, n := range cl.nodes { + n.tracer.waitSent() } } func (cl *lockstepCluster) moveRound() { cl.timestamp = cl.timestamp.Add(cl.t.cfg.RoundDuration) - send := 0 for _, n := range cl.nodes { - n.clock.Set(cl.timestamp) + n.clock.Advance(cl.timestamp.Sub(n.clock.Now())) } for _, n := range cl.nodes { - if n.tracer.waitEligibility() != nil { - send++ - } - } - for i := 0; i < send; i++ { - cl.timedSend(cl.start) - } - for i := 0; i < send; i++ { - cl.timedReceive(cl.complete) + n.tracer.waitEligibility() } -} - -func (cl *lockstepCluster) timedSend(ch chan struct{}) { - select { - case ch <- struct{}{}: - case <-time.After(time.Second): - require.FailNow(cl.t, "send timed out") + for _, n := range cl.nodes { + n.tracer.waitSent() } } -func (cl *lockstepCluster) timedReceive(ch chan struct{}) { - select { - case <-ch: - case <-time.After(time.Second): - require.FailNow(cl.t, "receive timed out") +func (cl *lockstepCluster) waitStopped() { + for _, n := range cl.nodes { + n.tracer.waitStopped() } } @@ -465,7 +430,8 @@ func newTestTracer(tb testing.TB) *testTracer { return &testTracer{ TB: tb, stopped: make(chan types.LayerID, 100), - eligibility: make(chan *types.HareEligibility, 100), + eligibility: make(chan *types.HareEligibility), + sent: make(chan *Message), } } @@ -473,6 +439,7 @@ type testTracer struct { testing.TB stopped chan types.LayerID eligibility chan *types.HareEligibility + sent chan *Message } func (t *testTracer) waitStopped() types.LayerID { @@ -497,6 +464,17 @@ func (t *testTracer) waitEligibility() *types.HareEligibility { return nil } +func (t *testTracer) waitSent() *Message { + wait := time.Second + select { + case <-time.After(wait): + require.FailNow(t, "no message", "wait %v", wait) + case m := <-t.sent: + return m + } + return nil +} + func (*testTracer) OnStart(types.LayerID) {} func (t *testTracer) OnStop(lid types.LayerID) { @@ -507,13 +485,22 @@ func (t *testTracer) OnStop(lid types.LayerID) { } func (t *testTracer) OnActive(el *types.HareEligibility) { + wait := time.Second select { + case <-time.After(wait): + require.FailNow(t, "eligibility can't be sent", "wait %v", wait) case t.eligibility <- el: - default: } } -func (*testTracer) OnMessageSent(*Message) {} +func (t *testTracer) OnMessageSent(m *Message) { + wait := time.Second + select { + case <-time.After(wait): + require.FailNow(t, "message can't be sent", "wait %v", wait) + case t.sent <- m: + } +} func (*testTracer) OnMessageReceived(*Message) {} @@ -541,8 +528,8 @@ func testHare(t *testing.T, active, inactive, equivocators int, opts ...clusterO cluster.moveRound() } var consistent []types.ProposalID + cluster.waitStopped() for _, n := range cluster.nodes { - n.tracer.waitStopped() select { case coin := <-n.hare.Coins(): require.Equal(t, coin.Layer, layer) @@ -597,6 +584,7 @@ func TestIterationLimit(t *testing.T) { for i := 0; i < int(tst.cfg.IterationsLimit)*int(notify); i++ { cluster.moveRound() } + cluster.waitStopped() require.Empty(t, cluster.nodes[0].hare.Running()) require.False(t, cluster.nodes[0].patrol.IsHareInCharge(layer)) } @@ -627,10 +615,13 @@ func TestHandler(t *testing.T) { n.mpublisher.EXPECT().Publish(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() layer := tst.genesis + 1 n.nclock.StartLayer(layer) - n.clock.Set(tst.start. + n.clock.Advance((tst.start. Add(tst.layerDuration * time.Duration(layer)). - Add(tst.cfg.PreroundDelay)) + Add(tst.cfg.PreroundDelay)).Sub(n.clock.Now())) elig := n.tracer.waitEligibility() + n.tracer.waitSent() + n.tracer.waitEligibility() + t.Run("malformed", func(t *testing.T) { require.ErrorIs(t, n.hare.Handler(context.Background(), "", []byte("malformed")), pubsub.ErrValidationReject) diff --git a/log/log_mock.go b/log/log_mock.go index aa6c6a6312..ff5565cbd9 100644 --- a/log/log_mock.go +++ b/log/log_mock.go @@ -1,6 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: ./log.go - +// +// Generated by this command: +// +// mockgen -typed -package=log -destination=./log_mock.go -source=./log.go +// // Package log is a generated GoMock package. package log @@ -37,7 +41,7 @@ func (m *MockLogger) EXPECT() *MockLoggerMockRecorder { // Debug mocks base method. func (m *MockLogger) Debug(format string, args ...any) { m.ctrl.T.Helper() - varargs := []interface{}{format} + varargs := []any{format} for _, a := range args { varargs = append(varargs, a) } @@ -45,9 +49,9 @@ func (m *MockLogger) Debug(format string, args ...any) { } // Debug indicates an expected call of Debug. -func (mr *MockLoggerMockRecorder) Debug(format interface{}, args ...interface{}) *LoggerDebugCall { +func (mr *MockLoggerMockRecorder) Debug(format any, args ...any) *LoggerDebugCall { mr.mock.ctrl.T.Helper() - varargs := append([]interface{}{format}, args...) + varargs := append([]any{format}, args...) call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Debug", reflect.TypeOf((*MockLogger)(nil).Debug), varargs...) return &LoggerDebugCall{Call: call} } @@ -78,7 +82,7 @@ func (c *LoggerDebugCall) DoAndReturn(f func(string, ...any)) *LoggerDebugCall { // Error mocks base method. func (m *MockLogger) Error(format string, args ...any) { m.ctrl.T.Helper() - varargs := []interface{}{format} + varargs := []any{format} for _, a := range args { varargs = append(varargs, a) } @@ -86,9 +90,9 @@ func (m *MockLogger) Error(format string, args ...any) { } // Error indicates an expected call of Error. -func (mr *MockLoggerMockRecorder) Error(format interface{}, args ...interface{}) *LoggerErrorCall { +func (mr *MockLoggerMockRecorder) Error(format any, args ...any) *LoggerErrorCall { mr.mock.ctrl.T.Helper() - varargs := append([]interface{}{format}, args...) + varargs := append([]any{format}, args...) call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Error", reflect.TypeOf((*MockLogger)(nil).Error), varargs...) return &LoggerErrorCall{Call: call} } @@ -119,7 +123,7 @@ func (c *LoggerErrorCall) DoAndReturn(f func(string, ...any)) *LoggerErrorCall { // Info mocks base method. func (m *MockLogger) Info(format string, args ...any) { m.ctrl.T.Helper() - varargs := []interface{}{format} + varargs := []any{format} for _, a := range args { varargs = append(varargs, a) } @@ -127,9 +131,9 @@ func (m *MockLogger) Info(format string, args ...any) { } // Info indicates an expected call of Info. -func (mr *MockLoggerMockRecorder) Info(format interface{}, args ...interface{}) *LoggerInfoCall { +func (mr *MockLoggerMockRecorder) Info(format any, args ...any) *LoggerInfoCall { mr.mock.ctrl.T.Helper() - varargs := append([]interface{}{format}, args...) + varargs := append([]any{format}, args...) call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Info", reflect.TypeOf((*MockLogger)(nil).Info), varargs...) return &LoggerInfoCall{Call: call} } @@ -160,7 +164,7 @@ func (c *LoggerInfoCall) DoAndReturn(f func(string, ...any)) *LoggerInfoCall { // Panic mocks base method. func (m *MockLogger) Panic(format string, args ...any) { m.ctrl.T.Helper() - varargs := []interface{}{format} + varargs := []any{format} for _, a := range args { varargs = append(varargs, a) } @@ -168,9 +172,9 @@ func (m *MockLogger) Panic(format string, args ...any) { } // Panic indicates an expected call of Panic. -func (mr *MockLoggerMockRecorder) Panic(format interface{}, args ...interface{}) *LoggerPanicCall { +func (mr *MockLoggerMockRecorder) Panic(format any, args ...any) *LoggerPanicCall { mr.mock.ctrl.T.Helper() - varargs := append([]interface{}{format}, args...) + varargs := append([]any{format}, args...) call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Panic", reflect.TypeOf((*MockLogger)(nil).Panic), varargs...) return &LoggerPanicCall{Call: call} } @@ -201,7 +205,7 @@ func (c *LoggerPanicCall) DoAndReturn(f func(string, ...any)) *LoggerPanicCall { // Warning mocks base method. func (m *MockLogger) Warning(format string, args ...any) { m.ctrl.T.Helper() - varargs := []interface{}{format} + varargs := []any{format} for _, a := range args { varargs = append(varargs, a) } @@ -209,9 +213,9 @@ func (m *MockLogger) Warning(format string, args ...any) { } // Warning indicates an expected call of Warning. -func (mr *MockLoggerMockRecorder) Warning(format interface{}, args ...interface{}) *LoggerWarningCall { +func (mr *MockLoggerMockRecorder) Warning(format any, args ...any) *LoggerWarningCall { mr.mock.ctrl.T.Helper() - varargs := append([]interface{}{format}, args...) + varargs := append([]any{format}, args...) call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Warning", reflect.TypeOf((*MockLogger)(nil).Warning), varargs...) return &LoggerWarningCall{Call: call} } @@ -286,7 +290,7 @@ func (m *MockLogger) WithContext(arg0 context.Context) Log { } // WithContext indicates an expected call of WithContext. -func (mr *MockLoggerMockRecorder) WithContext(arg0 interface{}) *LoggerWithContextCall { +func (mr *MockLoggerMockRecorder) WithContext(arg0 any) *LoggerWithContextCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WithContext", reflect.TypeOf((*MockLogger)(nil).WithContext), arg0) return &LoggerWithContextCall{Call: call} @@ -324,7 +328,7 @@ func (m *MockLogger) WithName(arg0 string) Log { } // WithName indicates an expected call of WithName. -func (mr *MockLoggerMockRecorder) WithName(arg0 interface{}) *LoggerWithNameCall { +func (mr *MockLoggerMockRecorder) WithName(arg0 any) *LoggerWithNameCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WithName", reflect.TypeOf((*MockLogger)(nil).WithName), arg0) return &LoggerWithNameCall{Call: call} diff --git a/malfeasance/mocks.go b/malfeasance/mocks.go index 466348c11d..266af624c7 100644 --- a/malfeasance/mocks.go +++ b/malfeasance/mocks.go @@ -1,6 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: ./interface.go - +// +// Generated by this command: +// +// mockgen -typed -package=malfeasance -destination=./mocks.go -source=./interface.go +// // Package malfeasance is a generated GoMock package. package malfeasance @@ -43,7 +47,7 @@ func (m *MockconsensusProtocol) HandleEligibility(arg0 context.Context, arg1 *ty } // HandleEligibility indicates an expected call of HandleEligibility. -func (mr *MockconsensusProtocolMockRecorder) HandleEligibility(arg0, arg1 interface{}) *consensusProtocolHandleEligibilityCall { +func (mr *MockconsensusProtocolMockRecorder) HandleEligibility(arg0, arg1 any) *consensusProtocolHandleEligibilityCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HandleEligibility", reflect.TypeOf((*MockconsensusProtocol)(nil).HandleEligibility), arg0, arg1) return &consensusProtocolHandleEligibilityCall{Call: call} @@ -104,7 +108,7 @@ func (m *MockSigVerifier) Verify(arg0 signing.Domain, arg1 types.NodeID, arg2 [] } // Verify indicates an expected call of Verify. -func (mr *MockSigVerifierMockRecorder) Verify(arg0, arg1, arg2, arg3 interface{}) *SigVerifierVerifyCall { +func (mr *MockSigVerifierMockRecorder) Verify(arg0, arg1, arg2, arg3 any) *SigVerifierVerifyCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Verify", reflect.TypeOf((*MockSigVerifier)(nil).Verify), arg0, arg1, arg2, arg3) return &SigVerifierVerifyCall{Call: call} @@ -163,7 +167,7 @@ func (m *Mocktortoise) OnMalfeasance(arg0 types.NodeID) { } // OnMalfeasance indicates an expected call of OnMalfeasance. -func (mr *MocktortoiseMockRecorder) OnMalfeasance(arg0 interface{}) *tortoiseOnMalfeasanceCall { +func (mr *MocktortoiseMockRecorder) OnMalfeasance(arg0 any) *tortoiseOnMalfeasanceCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OnMalfeasance", reflect.TypeOf((*Mocktortoise)(nil).OnMalfeasance), arg0) return &tortoiseOnMalfeasanceCall{Call: call} diff --git a/mesh/mocks/mocks.go b/mesh/mocks/mocks.go index 79bb070477..44fd6e6d44 100644 --- a/mesh/mocks/mocks.go +++ b/mesh/mocks/mocks.go @@ -1,6 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: ./interface.go - +// +// Generated by this command: +// +// mockgen -typed -package=mocks -destination=./mocks/mocks.go -source=./interface.go +// // Package mocks is a generated GoMock package. package mocks @@ -45,7 +49,7 @@ func (m *MockconservativeState) LinkTXsWithBlock(arg0 types.LayerID, arg1 types. } // LinkTXsWithBlock indicates an expected call of LinkTXsWithBlock. -func (mr *MockconservativeStateMockRecorder) LinkTXsWithBlock(arg0, arg1, arg2 interface{}) *conservativeStateLinkTXsWithBlockCall { +func (mr *MockconservativeStateMockRecorder) LinkTXsWithBlock(arg0, arg1, arg2 any) *conservativeStateLinkTXsWithBlockCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LinkTXsWithBlock", reflect.TypeOf((*MockconservativeState)(nil).LinkTXsWithBlock), arg0, arg1, arg2) return &conservativeStateLinkTXsWithBlockCall{Call: call} @@ -83,7 +87,7 @@ func (m *MockconservativeState) LinkTXsWithProposal(arg0 types.LayerID, arg1 typ } // LinkTXsWithProposal indicates an expected call of LinkTXsWithProposal. -func (mr *MockconservativeStateMockRecorder) LinkTXsWithProposal(arg0, arg1, arg2 interface{}) *conservativeStateLinkTXsWithProposalCall { +func (mr *MockconservativeStateMockRecorder) LinkTXsWithProposal(arg0, arg1, arg2 any) *conservativeStateLinkTXsWithProposalCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LinkTXsWithProposal", reflect.TypeOf((*MockconservativeState)(nil).LinkTXsWithProposal), arg0, arg1, arg2) return &conservativeStateLinkTXsWithProposalCall{Call: call} @@ -121,7 +125,7 @@ func (m *MockconservativeState) RevertCache(arg0 types.LayerID) error { } // RevertCache indicates an expected call of RevertCache. -func (mr *MockconservativeStateMockRecorder) RevertCache(arg0 interface{}) *conservativeStateRevertCacheCall { +func (mr *MockconservativeStateMockRecorder) RevertCache(arg0 any) *conservativeStateRevertCacheCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RevertCache", reflect.TypeOf((*MockconservativeState)(nil).RevertCache), arg0) return &conservativeStateRevertCacheCall{Call: call} @@ -159,7 +163,7 @@ func (m *MockconservativeState) UpdateCache(arg0 context.Context, arg1 types.Lay } // UpdateCache indicates an expected call of UpdateCache. -func (mr *MockconservativeStateMockRecorder) UpdateCache(arg0, arg1, arg2, arg3, arg4 interface{}) *conservativeStateUpdateCacheCall { +func (mr *MockconservativeStateMockRecorder) UpdateCache(arg0, arg1, arg2, arg3, arg4 any) *conservativeStateUpdateCacheCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateCache", reflect.TypeOf((*MockconservativeState)(nil).UpdateCache), arg0, arg1, arg2, arg3, arg4) return &conservativeStateUpdateCacheCall{Call: call} @@ -222,7 +226,7 @@ func (m *MockvmState) Apply(arg0 vm.ApplyContext, arg1 []types.Transaction, arg2 } // Apply indicates an expected call of Apply. -func (mr *MockvmStateMockRecorder) Apply(arg0, arg1, arg2 interface{}) *vmStateApplyCall { +func (mr *MockvmStateMockRecorder) Apply(arg0, arg1, arg2 any) *vmStateApplyCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Apply", reflect.TypeOf((*MockvmState)(nil).Apply), arg0, arg1, arg2) return &vmStateApplyCall{Call: call} @@ -299,7 +303,7 @@ func (m *MockvmState) Revert(arg0 types.LayerID) error { } // Revert indicates an expected call of Revert. -func (mr *MockvmStateMockRecorder) Revert(arg0 interface{}) *vmStateRevertCall { +func (mr *MockvmStateMockRecorder) Revert(arg0 any) *vmStateRevertCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Revert", reflect.TypeOf((*MockvmState)(nil).Revert), arg0) return &vmStateRevertCall{Call: call} diff --git a/miner/mocks.go b/miner/mocks.go index 77f4f4d1af..b3d55c6672 100644 --- a/miner/mocks.go +++ b/miner/mocks.go @@ -1,6 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: ./interface.go - +// +// Generated by this command: +// +// mockgen -typed -package=miner -destination=./mocks.go -source=./interface.go +// // Package miner is a generated GoMock package. package miner @@ -47,7 +51,7 @@ func (m *MockproposalOracle) ProposalEligibility(arg0 types.LayerID, arg1 types. } // ProposalEligibility indicates an expected call of ProposalEligibility. -func (mr *MockproposalOracleMockRecorder) ProposalEligibility(arg0, arg1, arg2 interface{}) *proposalOracleProposalEligibilityCall { +func (mr *MockproposalOracleMockRecorder) ProposalEligibility(arg0, arg1, arg2 any) *proposalOracleProposalEligibilityCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProposalEligibility", reflect.TypeOf((*MockproposalOracle)(nil).ProposalEligibility), arg0, arg1, arg2) return &proposalOracleProposalEligibilityCall{Call: call} @@ -108,7 +112,7 @@ func (m *MockconservativeState) SelectProposalTXs(arg0 types.LayerID, arg1 int) } // SelectProposalTXs indicates an expected call of SelectProposalTXs. -func (mr *MockconservativeStateMockRecorder) SelectProposalTXs(arg0, arg1 interface{}) *conservativeStateSelectProposalTXsCall { +func (mr *MockconservativeStateMockRecorder) SelectProposalTXs(arg0, arg1 any) *conservativeStateSelectProposalTXsCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SelectProposalTXs", reflect.TypeOf((*MockconservativeState)(nil).SelectProposalTXs), arg0, arg1) return &conservativeStateSelectProposalTXsCall{Call: call} @@ -163,7 +167,7 @@ func (m *MockvotesEncoder) EXPECT() *MockvotesEncoderMockRecorder { // EncodeVotes mocks base method. func (m *MockvotesEncoder) EncodeVotes(arg0 context.Context, arg1 ...tortoise.EncodeVotesOpts) (*types.Opinion, error) { m.ctrl.T.Helper() - varargs := []interface{}{arg0} + varargs := []any{arg0} for _, a := range arg1 { varargs = append(varargs, a) } @@ -174,9 +178,9 @@ func (m *MockvotesEncoder) EncodeVotes(arg0 context.Context, arg1 ...tortoise.En } // EncodeVotes indicates an expected call of EncodeVotes. -func (mr *MockvotesEncoderMockRecorder) EncodeVotes(arg0 interface{}, arg1 ...interface{}) *votesEncoderEncodeVotesCall { +func (mr *MockvotesEncoderMockRecorder) EncodeVotes(arg0 any, arg1 ...any) *votesEncoderEncodeVotesCall { mr.mock.ctrl.T.Helper() - varargs := append([]interface{}{arg0}, arg1...) + varargs := append([]any{arg0}, arg1...) call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EncodeVotes", reflect.TypeOf((*MockvotesEncoder)(nil).EncodeVotes), varargs...) return &votesEncoderEncodeVotesCall{Call: call} } @@ -249,7 +253,7 @@ func (m *MockvotesEncoder) TallyVotes(arg0 context.Context, arg1 types.LayerID) } // TallyVotes indicates an expected call of TallyVotes. -func (mr *MockvotesEncoderMockRecorder) TallyVotes(arg0, arg1 interface{}) *votesEncoderTallyVotesCall { +func (mr *MockvotesEncoderMockRecorder) TallyVotes(arg0, arg1 any) *votesEncoderTallyVotesCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TallyVotes", reflect.TypeOf((*MockvotesEncoder)(nil).TallyVotes), arg0, arg1) return &votesEncoderTallyVotesCall{Call: call} @@ -311,7 +315,7 @@ func (m *MocknonceFetcher) VRFNonce(arg0 types.NodeID, arg1 types.EpochID) (type } // VRFNonce indicates an expected call of VRFNonce. -func (mr *MocknonceFetcherMockRecorder) VRFNonce(arg0, arg1 interface{}) *nonceFetcherVRFNonceCall { +func (mr *MocknonceFetcherMockRecorder) VRFNonce(arg0, arg1 any) *nonceFetcherVRFNonceCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "VRFNonce", reflect.TypeOf((*MocknonceFetcher)(nil).VRFNonce), arg0, arg1) return &nonceFetcherVRFNonceCall{Call: call} @@ -373,7 +377,7 @@ func (m *Mockmesh) GetMalfeasanceProof(nodeID types.NodeID) (*types.MalfeasanceP } // GetMalfeasanceProof indicates an expected call of GetMalfeasanceProof. -func (mr *MockmeshMockRecorder) GetMalfeasanceProof(nodeID interface{}) *meshGetMalfeasanceProofCall { +func (mr *MockmeshMockRecorder) GetMalfeasanceProof(nodeID any) *meshGetMalfeasanceProofCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMalfeasanceProof", reflect.TypeOf((*Mockmesh)(nil).GetMalfeasanceProof), nodeID) return &meshGetMalfeasanceProofCall{Call: call} @@ -434,7 +438,7 @@ func (m *MocklayerClock) AwaitLayer(layerID types.LayerID) <-chan struct{} { } // AwaitLayer indicates an expected call of AwaitLayer. -func (mr *MocklayerClockMockRecorder) AwaitLayer(layerID interface{}) *layerClockAwaitLayerCall { +func (mr *MocklayerClockMockRecorder) AwaitLayer(layerID any) *layerClockAwaitLayerCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AwaitLayer", reflect.TypeOf((*MocklayerClock)(nil).AwaitLayer), layerID) return &layerClockAwaitLayerCall{Call: call} @@ -510,7 +514,7 @@ func (m *MocklayerClock) LayerToTime(arg0 types.LayerID) time.Time { } // LayerToTime indicates an expected call of LayerToTime. -func (mr *MocklayerClockMockRecorder) LayerToTime(arg0 interface{}) *layerClockLayerToTimeCall { +func (mr *MocklayerClockMockRecorder) LayerToTime(arg0 any) *layerClockLayerToTimeCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LayerToTime", reflect.TypeOf((*MocklayerClock)(nil).LayerToTime), arg0) return &layerClockLayerToTimeCall{Call: call} diff --git a/miner/oracle.go b/miner/oracle.go index 79c528d4dd..685aae859c 100644 --- a/miner/oracle.go +++ b/miner/oracle.go @@ -14,6 +14,7 @@ import ( "github.com/spacemeshos/go-spacemesh/proposals" "github.com/spacemeshos/go-spacemesh/signing" "github.com/spacemeshos/go-spacemesh/sql" + "github.com/spacemeshos/go-spacemesh/sql/activesets" "github.com/spacemeshos/go-spacemesh/sql/ballots" "github.com/spacemeshos/go-spacemesh/system" ) @@ -63,10 +64,6 @@ func (o *Oracle) ProposalEligibility(lid types.LayerID, beacon types.Beacon, non o.mu.Lock() defer o.mu.Unlock() - if legacy := types.GetLegacyLayer(); legacy != 0 && lid.Uint32() == legacy+1 { - o.cache = &EpochEligibility{} - } - epoch := lid.GetEpoch() if lid <= types.GetEffectiveGenesis() { o.log.With().Panic("eligibility should not be queried during genesis", lid, epoch) @@ -220,7 +217,11 @@ func (o *Oracle) calcEligibilityProofs(lid types.LayerID, epoch types.EpochID, b if ref == nil { minerWeight, totalWeight, ownAtx, activeSet, err = o.activeSet(epoch) } else { - activeSet = ref.ActiveSet + if epochActives, err := activesets.Get(o.cdb, ref.EpochData.ActiveSetHash); err != nil { + return nil, err + } else { + activeSet = epochActives.Set + } o.log.With().Info("use active set from ref ballot", ref.ID(), log.Int("num atx", len(activeSet)), @@ -244,7 +245,7 @@ func (o *Oracle) calcEligibilityProofs(lid types.LayerID, epoch types.EpochID, b ) var numEligibleSlots uint32 if ref == nil { - numEligibleSlots, err = proposals.GetLegacyNumEligible(lid, minerWeight, o.cfg.minActiveSetWeight, totalWeight, o.cfg.layerSize, o.cfg.layersPerEpoch) + numEligibleSlots, err = proposals.GetNumEligibleSlots(minerWeight, o.cfg.minActiveSetWeight, totalWeight, o.cfg.layerSize, o.cfg.layersPerEpoch) if err != nil { return nil, fmt.Errorf("oracle get num slots: %w", err) } diff --git a/miner/oracle_test.go b/miner/oracle_test.go index 0ebdb6345d..c945ddb944 100644 --- a/miner/oracle_test.go +++ b/miner/oracle_test.go @@ -16,6 +16,7 @@ import ( "github.com/spacemeshos/go-spacemesh/proposals" "github.com/spacemeshos/go-spacemesh/signing" "github.com/spacemeshos/go-spacemesh/sql" + "github.com/spacemeshos/go-spacemesh/sql/activesets" "github.com/spacemeshos/go-spacemesh/sql/atxs" "github.com/spacemeshos/go-spacemesh/sql/ballots" "github.com/spacemeshos/go-spacemesh/sql/blocks" @@ -102,7 +103,6 @@ func genBallotWithEligibility( EligibilityCount: ee.Slots, }, }, - ActiveSet: ee.ActiveSet, EligibilityProofs: ee.Proofs[lid], } ballot.Signature = signer.Sign(signing.BALLOT, ballot.SignedBytes()) @@ -216,6 +216,7 @@ func testMinerOracleAndProposalValidator(t *testing.T, layerSize, layersPerEpoch require.True(t, ok) ee, err := o.ProposalEligibility(layer, info.beacon, nonce) require.NoError(t, err) + activesets.Add(o.cdb, ee.ActiveSet.Hash(), &types.EpochActiveSet{Epoch: ee.Epoch, Set: ee.ActiveSet}) for _, proof := range ee.Proofs[layer] { b := genBallotWithEligibility(t, o.edSigner, info.beacon, layer, ee) @@ -223,7 +224,7 @@ func testMinerOracleAndProposalValidator(t *testing.T, layerSize, layersPerEpoch o.mClock.EXPECT().CurrentLayer().Return(layer) mbc.EXPECT().ReportBeaconFromBallot(layer.GetEpoch(), b, info.beacon, gomock.Any()).Times(1) nonceFetcher.EXPECT().VRFNonce(b.SmesherID, layer.GetEpoch()).Return(nonce, nil).Times(1) - eligible, err := validator.CheckEligibility(context.Background(), b) + eligible, err := validator.CheckEligibility(context.Background(), b, ee.ActiveSet) require.NoError(t, err, "at layer %d, with layersPerEpoch %d", layer, layersPerEpoch) require.True(t, eligible, "should be eligible at layer %d, but isn't", layer) counterValuesSeen[proof.J]++ @@ -380,11 +381,16 @@ func createBallots(tb testing.TB, cdb *datastore.CachedDB, lid types.LayerID, nu b.Layer = lid b.AtxID = types.RandomATXID() b.RefBallot = types.EmptyBallotID - b.EpochData = &types.EpochData{} - b.ActiveSet = common - b.ActiveSet = append(b.ActiveSet, b.AtxID) + b.EpochData = &types.EpochData{ + ActiveSetHash: types.RandomHash(), + } b.Signature = types.RandomEdSignature() b.SmesherID = types.RandomNodeID() + actives := append(common, b.AtxID) + require.NoError(tb, activesets.Add(cdb, b.EpochData.ActiveSetHash, &types.EpochActiveSet{ + Epoch: lid.GetEpoch(), + Set: actives, + })) require.NoError(tb, b.Initialize()) require.NoError(tb, ballots.Add(cdb, b)) result = append(result, b) @@ -480,10 +486,14 @@ func TestRefBallot(t *testing.T) { ballot.Layer = layer ballot.AtxID = atx.ID() ballot.SmesherID = o.edSigner.NodeID() - ballot.EpochData = &types.EpochData{EligibilityCount: 1} - ballot.ActiveSet = []types.ATXID{ballot.AtxID} + actives := types.ATXIDList{ballot.AtxID} + ballot.EpochData = &types.EpochData{EligibilityCount: 1, ActiveSetHash: actives.Hash()} ballot.SetID(types.BallotID{1}) require.NoError(t, ballots.Add(o.cdb, &ballot)) + activesets.Add(o.cdb, ballot.EpochData.ActiveSetHash, &types.EpochActiveSet{ + Epoch: layer.GetEpoch(), + Set: actives, + }) genATXForTargetEpochs(t, o.cdb, layer.GetEpoch(), layer.GetEpoch()+1, o.edSigner, layersPerEpoch, time.Now().Add(-1*time.Hour)) ee, err := o.calcEligibilityProofs(layer, layer.GetEpoch(), types.Beacon{}, types.VRFPostIndex(101)) @@ -491,5 +501,5 @@ func TestRefBallot(t *testing.T) { require.NotEmpty(t, ee) require.Equal(t, 1, int(ee.Slots)) require.Equal(t, atx.ID(), ee.Atx) - require.ElementsMatch(t, ballot.ActiveSet, ee.ActiveSet) + require.ElementsMatch(t, actives, ee.ActiveSet) } diff --git a/miner/proposal_builder.go b/miner/proposal_builder.go index 2c597f151b..e69e0db742 100644 --- a/miner/proposal_builder.go +++ b/miner/proposal_builder.go @@ -66,7 +66,6 @@ type config struct { layersPerEpoch uint32 hdist uint32 minActiveSetWeight uint64 - emitEmptyActiveSet types.LayerID nodeID types.NodeID networkDelay time.Duration @@ -79,7 +78,6 @@ func (c *config) MarshalLogObject(encoder log.ObjectEncoder) error { encoder.AddUint32("epoch size", c.layersPerEpoch) encoder.AddUint32("hdist", c.hdist) encoder.AddUint64("min active weight", c.minActiveSetWeight) - encoder.AddUint32("emit empty set", c.emitEmptyActiveSet.Uint32()) encoder.AddDuration("network delay", c.networkDelay) encoder.AddInt("good atx percent", c.goodAtxPct) return nil @@ -152,12 +150,6 @@ func WithMinGoodAtxPct(pct int) Opt { } } -func WithEmitEmptyActiveSet(lid types.LayerID) Opt { - return func(pb *ProposalBuilder) { - pb.cfg.emitEmptyActiveSet = lid - } -} - func withOracle(o proposalOracle) Opt { return func(pb *ProposalBuilder) { pb.proposalOracle = o @@ -302,9 +294,6 @@ func (pb *ProposalBuilder) createProposal( MeshHash: pb.decideMeshHash(ctx, layerID), }, } - if p.EpochData != nil && layerID < pb.cfg.emitEmptyActiveSet { - p.ActiveSet = epochEligibility.ActiveSet - } p.Ballot.Signature = pb.signer.Sign(signing.BALLOT, p.Ballot.SignedBytes()) p.SmesherID = pb.signer.NodeID() p.Signature = pb.signer.Sign(signing.PROPOSAL, p.SignedBytes()) diff --git a/miner/util.go b/miner/util.go index 71d7513e38..764c09a921 100644 --- a/miner/util.go +++ b/miner/util.go @@ -7,20 +7,12 @@ import ( "github.com/spacemeshos/go-spacemesh/common/types" "github.com/spacemeshos/go-spacemesh/sql" + "github.com/spacemeshos/go-spacemesh/sql/activesets" "github.com/spacemeshos/go-spacemesh/sql/ballots" "github.com/spacemeshos/go-spacemesh/sql/blocks" - "github.com/spacemeshos/go-spacemesh/sql/certificates" "github.com/spacemeshos/go-spacemesh/sql/layers" ) -func ActiveSetFromEpochFirstCertifiedBlock(db sql.Executor, epoch types.EpochID) ([]types.ATXID, error) { - bid, err := certificates.FirstInEpoch(db, epoch) - if err != nil { - return nil, err - } - return activeSetFromBlock(db, bid) -} - func ActiveSetFromEpochFirstBlock(db sql.Executor, epoch types.EpochID) ([]types.ATXID, error) { bid, err := layers.FirstAppliedInEpoch(db, epoch) if err != nil { @@ -42,7 +34,11 @@ func activeSetFromBlock(db sql.Executor, bid types.BlockID) ([]types.ATXID, erro if err != nil { return nil, fmt.Errorf("actives get ballot: %w", err) } - for _, id := range ballot.ActiveSet { + actives, err := activesets.Get(db, ballot.EpochData.ActiveSetHash) + if err != nil { + return nil, fmt.Errorf("actives get active hash for ballot %s: %w", ballot.ID().String(), err) + } + for _, id := range actives.Set { activeMap[id] = struct{}{} } } diff --git a/miner/util_test.go b/miner/util_test.go index e12862fbc1..ff268a652c 100644 --- a/miner/util_test.go +++ b/miner/util_test.go @@ -12,32 +12,19 @@ import ( "github.com/spacemeshos/go-spacemesh/signing" "github.com/spacemeshos/go-spacemesh/sql" "github.com/spacemeshos/go-spacemesh/sql/blocks" - "github.com/spacemeshos/go-spacemesh/sql/certificates" "github.com/spacemeshos/go-spacemesh/sql/layers" ) func TestActiveSetFromEpochFirstBlock(t *testing.T) { for _, tc := range []struct { - desc string - miner, hare bool - err error + desc string + err error }{ { - desc: "actives for miner", - miner: true, + desc: "actives", }, { - desc: "no actives for miner", - miner: true, - err: sql.ErrNotFound, - }, - { - desc: "actives for hare", - hare: true, - }, - { - desc: "no actives for hare", - hare: true, + desc: "no actives", err: sql.ErrNotFound, }, } { @@ -45,7 +32,7 @@ func TestActiveSetFromEpochFirstBlock(t *testing.T) { epoch := types.EpochID(3) cdb := datastore.NewCachedDB(sql.InMemory(), logtest.New(t)) - got, err := ActiveSetFromEpochFirstCertifiedBlock(cdb, epoch) + got, err := ActiveSetFromEpochFirstBlock(cdb, epoch) require.ErrorIs(t, err, sql.ErrNotFound) require.Nil(t, got) @@ -66,12 +53,7 @@ func TestActiveSetFromEpochFirstBlock(t *testing.T) { block.Initialize() require.NoError(t, blocks.Add(cdb, block)) if tc.err == nil { - if tc.miner { - require.NoError(t, layers.SetApplied(cdb, lid, block.ID())) - } - if tc.hare { - require.NoError(t, certificates.Add(cdb, lid, &types.Certificate{BlockID: block.ID()})) - } + require.NoError(t, layers.SetApplied(cdb, lid, block.ID())) } if i == 0 { expected = all @@ -83,11 +65,7 @@ func TestActiveSetFromEpochFirstBlock(t *testing.T) { } } - if tc.miner { - got, err = ActiveSetFromEpochFirstBlock(cdb, epoch) - } else if tc.hare { - got, err = ActiveSetFromEpochFirstCertifiedBlock(cdb, epoch) - } + got, err = ActiveSetFromEpochFirstBlock(cdb, epoch) if tc.err != nil { require.ErrorIs(t, err, tc.err) } else { diff --git a/node/node.go b/node/node.go index 5396ed3016..c1ad105ea7 100644 --- a/node/node.go +++ b/node/node.go @@ -22,7 +22,6 @@ import ( "github.com/grpc-ecosystem/go-grpc-middleware/logging/zap/ctxzap" grpctags "github.com/grpc-ecosystem/go-grpc-middleware/tags" "github.com/mitchellh/mapstructure" - poetconfig "github.com/spacemeshos/poet/config" "github.com/spacemeshos/poet/server" "github.com/spacemeshos/post/verifying" "github.com/spf13/afero" @@ -64,8 +63,10 @@ import ( "github.com/spacemeshos/go-spacemesh/p2p" "github.com/spacemeshos/go-spacemesh/p2p/pubsub" "github.com/spacemeshos/go-spacemesh/proposals" + "github.com/spacemeshos/go-spacemesh/prune" "github.com/spacemeshos/go-spacemesh/signing" "github.com/spacemeshos/go-spacemesh/sql" + "github.com/spacemeshos/go-spacemesh/sql/ballots/util" "github.com/spacemeshos/go-spacemesh/sql/layers" dbmetrics "github.com/spacemeshos/go-spacemesh/sql/metrics" "github.com/spacemeshos/go-spacemesh/syncer" @@ -142,9 +143,6 @@ func GetCommand() *cobra.Command { run := func(ctx context.Context) error { types.SetLayersPerEpoch(app.Config.LayersPerEpoch) - types.SetLegacyLayers(app.Config.LegacyLayer) - // starting on 2023-09-14 20:00:00 +0000 UTC (~1 week into 4th epoch) - types.SetOpUpgradeLayer(18000) // ensure all data folders exist if err := os.MkdirAll(app.Config.DataDir(), 0o700); err != nil { return fmt.Errorf("ensure folders exist: %w", err) @@ -564,7 +562,7 @@ func (app *App) initServices(ctx context.Context) error { } app.postVerifier = activation.NewOffloadingPostVerifier(postVerifiers, nipostValidatorLogger) - validator := activation.NewValidator(poetDb, app.Config.POST, nipostValidatorLogger, app.postVerifier) + validator := activation.NewValidator(poetDb, app.Config.POST, app.Config.SMESHING.Opts.Scrypt, nipostValidatorLogger, app.postVerifier) app.validator = validator cfg := vm.DefaultConfig() @@ -623,6 +621,7 @@ func (app *App) initServices(ctx context.Context) error { app.log.With().Info("tortoise will trace execution") trtlopts = append(trtlopts, tortoise.WithTracer()) } + start := time.Now() trtl, err := tortoise.Recover( app.cachedDB, app.clock.CurrentLayer(), beaconProtocol, trtlopts..., @@ -630,6 +629,7 @@ func (app *App) initServices(ctx context.Context) error { if err != nil { return fmt.Errorf("can't recover tortoise state: %w", err) } + app.log.With().Info("tortoise initialized", log.Duration("duration", time.Since(start))) app.eg.Go(func() error { for rst := range beaconProtocol.Results() { events.EmitBeacon(rst.Epoch, rst.Beacon) @@ -640,11 +640,17 @@ func (app *App) initServices(ctx context.Context) error { }) executor := mesh.NewExecutor(app.cachedDB, state, app.conState, app.addLogger(ExecutorLogger, lg)) - msh, err := mesh.NewMesh(app.cachedDB, app.clock, trtl, executor, app.conState, app.addLogger(MeshLogger, lg)) + mlog := app.addLogger(MeshLogger, lg) + msh, err := mesh.NewMesh(app.cachedDB, app.clock, trtl, executor, app.conState, mlog) if err != nil { return fmt.Errorf("failed to create mesh: %w", err) } + app.eg.Go(func() error { + prune.Prune(ctx, mlog.Zap(), app.db, app.clock, app.Config.Tortoise.Hdist, app.Config.DatabasePruneInterval) + return nil + }) + fetcherWrapped := &layerFetcher{} atxHandler := activation.NewHandler( app.cachedDB, @@ -677,7 +683,6 @@ func (app *App) initServices(ctx context.Context) error { MaxExceptions: trtlCfg.MaxExceptions, Hdist: trtlCfg.Hdist, MinimalActiveSetWeight: trtlCfg.MinimalActiveSetWeight, - AllowEmptyActiveSet: trtlCfg.EmitEmptyActiveSet, }), ) @@ -750,7 +755,6 @@ func (app *App) initServices(ctx context.Context) error { hareCfg := app.Config.HARE hareCfg.Hdist = app.Config.Tortoise.Hdist - hareCfg.StopAtxGrading = types.GetLegacyLayer() app.hare = hare.New( app.cachedDB, hareCfg, @@ -808,7 +812,6 @@ func (app *App) initServices(ctx context.Context) error { miner.WithLayerSize(layerSize), miner.WithLayerPerEpoch(layersPerEpoch), miner.WithMinimalActiveSetWeight(app.Config.Tortoise.MinimalActiveSetWeight), - miner.WithEmitEmptyActiveSet(app.Config.Tortoise.EmitEmptyActiveSet), miner.WithHdist(app.Config.Tortoise.Hdist), miner.WithNetworkDelay(app.Config.HARE.WakeupDelta), miner.WithMinGoodAtxPct(minerGoodAtxPct), @@ -965,7 +968,7 @@ func (app *App) launchStandalone(ctx context.Context) error { if err := app.beaconProtocol.UpdateBeacon(epoch, value); err != nil { return fmt.Errorf("update standalone beacon: %w", err) } - cfg := poetconfig.DefaultConfig() + cfg := server.DefaultConfig() cfg.PoetDir = filepath.Join(app.Config.DataDir(), "poet") parsed, err := url.Parse(app.Config.PoETServers[0]) @@ -973,15 +976,11 @@ func (app *App) launchStandalone(ctx context.Context) error { return err } cfg.RawRESTListener = parsed.Host - cfg.Service.Genesis.UnmarshalFlag(app.Config.Genesis.GenesisTime) - cfg.Service.EpochDuration = app.Config.LayerDuration * time.Duration(app.Config.LayersPerEpoch) - cfg.Service.CycleGap = app.Config.POET.CycleGap - cfg.Service.PhaseShift = app.Config.POET.PhaseShift - - cfg, err = poetconfig.SetupConfig(cfg) - if err != nil { - return fmt.Errorf("setup poet config: %w", err) - } + cfg.Genesis.UnmarshalFlag(app.Config.Genesis.GenesisTime) + cfg.Round.EpochDuration = app.Config.LayerDuration * time.Duration(app.Config.LayersPerEpoch) + cfg.Round.CycleGap = app.Config.POET.CycleGap + cfg.Round.PhaseShift = app.Config.POET.PhaseShift + server.SetupConfig(cfg) srv, err := server.New(ctx, *cfg) if err != nil { @@ -1327,13 +1326,15 @@ func (app *App) LoadOrCreateEdSigner() (*signing.EdSigner, error) { return edSgn, nil } -func (app *App) setupDBs(ctx context.Context, lg log.Log, dbPath string) error { +func (app *App) setupDBs(ctx context.Context, lg log.Log) error { + dbPath := app.Config.DataDir() if err := os.MkdirAll(dbPath, os.ModePerm); err != nil { return fmt.Errorf("failed to create %s: %w", dbPath, err) } sqlDB, err := sql.Open("file:"+filepath.Join(dbPath, dbFile), sql.WithConnections(app.Config.DatabaseConnections), sql.WithLatencyMetering(app.Config.DatabaseLatencyMetering), + sql.WithV5Migration(util.ExtractActiveSet), ) if err != nil { return fmt.Errorf("open sqlite db %w", err) @@ -1412,7 +1413,6 @@ func (app *App) startSynchronous(ctx context.Context) (err error) { } if app.Config.ProfilerURL != "" { - app.profilerService, err = pyroscope.Start(pyroscope.Config{ ApplicationName: app.Config.ProfilerName, // app.Config.ProfilerURL should be the pyroscope server address @@ -1461,7 +1461,7 @@ func (app *App) startSynchronous(ctx context.Context) (err error) { return fmt.Errorf("failed to initialize p2p host: %w", err) } - if err := app.setupDBs(ctx, lg, app.Config.DataDir()); err != nil { + if err := app.setupDBs(ctx, lg); err != nil { return err } if err := app.initServices(ctx); err != nil { diff --git a/p2p/README.md b/p2p/README.md index 02897cf7ad..9244bb378e 100644 --- a/p2p/README.md +++ b/p2p/README.md @@ -40,7 +40,6 @@ for them if needed. "min-peers": 30, "low-peers": 60, "high-peers": 100, - "p2p-disable-legacy-discovery": true, "direct": [ "/ip4/0.0.0.0/tcp/6000/p2p/12D3KooWRkBh6QayKLb1pDRJGMHE94Lix4ZBVh2BJJeX6mghk8VH" ], @@ -58,7 +57,7 @@ for them if needed. ### Configuration for private node -Set min-peers to the number of peers in the config and disable-dht. +Set min-peers to the number of peers in the config. low-peers and high-peers should not be lower than min-peers. ```json @@ -68,8 +67,6 @@ low-peers and high-peers should not be lower than min-peers. "min-peers": 1, "low-peers": 10, "high-peers": 20, - "p2p-disable-legacy-discovery": true, - "disable-dht": true, "bootnodes": [], "direct": [ "/ip4/0.0.0.0/tcp/7513/p2p/12D3KooWRfy4Sj4rDHDuBaYw3Mg5d2puwiCyqBCWMziFquaGQ5g8" diff --git a/p2p/dhtdiscovery/discovery.go b/p2p/dhtdiscovery/discovery.go index 4cc27850c8..40333dafff 100644 --- a/p2p/dhtdiscovery/discovery.go +++ b/p2p/dhtdiscovery/discovery.go @@ -84,12 +84,6 @@ func WithDir(path string) Opt { } } -func DisableDHT() Opt { - return func(d *Discovery) { - d.disableDht = true - } -} - func New(h host.Host, opts ...Opt) (*Discovery, error) { ctx, cancel := context.WithCancel(context.Background()) d := Discovery{ @@ -110,20 +104,17 @@ func New(h host.Host, opts ...Opt) (*Discovery, error) { if len(d.bootnodes) == 0 { d.logger.Warn("no bootnodes in the config") } - if !d.disableDht { - err := d.newDht(ctx, h, d.public, d.server, d.dir) - if err != nil { - return nil, err - } + err := d.newDht(ctx, h, d.public, d.server, d.dir) + if err != nil { + return nil, err } return &d, nil } type Discovery struct { - public bool - server bool - disableDht bool - dir string + public bool + server bool + dir string logger *zap.Logger eg errgroup.Group @@ -189,13 +180,11 @@ func (d *Discovery) Start() { func (d *Discovery) Stop() { d.cancel() d.eg.Wait() - if !d.disableDht { - if err := d.dht.Close(); err != nil { - d.logger.Error("error closing dht", zap.Error(err)) - } - if err := d.datastore.Close(); err != nil { - d.logger.Error("error closing level datastore", zap.Error(err)) - } + if err := d.dht.Close(); err != nil { + d.logger.Error("error closing dht", zap.Error(err)) + } + if err := d.datastore.Close(); err != nil { + d.logger.Error("error closing level datastore", zap.Error(err)) } } diff --git a/p2p/host.go b/p2p/host.go index 28d748237a..c105be6b03 100644 --- a/p2p/host.go +++ b/p2p/host.go @@ -83,7 +83,6 @@ type Config struct { DisableNatPort bool `mapstructure:"disable-natport"` DisableConnectionManager bool `mapstructure:"disable-connection-manager"` DisableResourceManager bool `mapstructure:"disable-resource-manager"` - DisableDHT bool `mapstructure:"disable-dht"` Flood bool `mapstructure:"flood"` Listen string `mapstructure:"listen"` Bootnodes []string `mapstructure:"bootnodes"` @@ -100,7 +99,6 @@ type Config struct { Bootnode bool `mapstructure:"p2p-bootnode"` ForceReachability string `mapstructure:"p2p-reachability"` EnableHolepunching bool `mapstructure:"p2p-holepunching"` - DisableLegacyDiscovery bool `mapstructure:"p2p-disable-legacy-discovery"` PrivateNetwork bool `mapstructure:"p2p-private-network"` RelayServer RelayServer `mapstructure:"relay-server"` IP4Blocklist []string `mapstructure:"ip4-blocklist"` diff --git a/p2p/pubsub/mocks/publisher.go b/p2p/pubsub/mocks/publisher.go index 32a4646f61..03e6d60d4b 100644 --- a/p2p/pubsub/mocks/publisher.go +++ b/p2p/pubsub/mocks/publisher.go @@ -1,6 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: ./pubsub.go - +// +// Generated by this command: +// +// mockgen -typed -package=mocks -destination=./mocks/publisher.go -source=./pubsub.go +// // Package mocks is a generated GoMock package. package mocks @@ -44,7 +48,7 @@ func (m *MockPublisher) Publish(arg0 context.Context, arg1 string, arg2 []byte) } // Publish indicates an expected call of Publish. -func (mr *MockPublisherMockRecorder) Publish(arg0, arg1, arg2 interface{}) *PublisherPublishCall { +func (mr *MockPublisherMockRecorder) Publish(arg0, arg1, arg2 any) *PublisherPublishCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Publish", reflect.TypeOf((*MockPublisher)(nil).Publish), arg0, arg1, arg2) return &PublisherPublishCall{Call: call} @@ -99,7 +103,7 @@ func (m *MockSubscriber) EXPECT() *MockSubscriberMockRecorder { // Register mocks base method. func (m *MockSubscriber) Register(arg0 string, arg1 pubsub.GossipHandler, arg2 ...pubsub.ValidatorOpt) { m.ctrl.T.Helper() - varargs := []interface{}{arg0, arg1} + varargs := []any{arg0, arg1} for _, a := range arg2 { varargs = append(varargs, a) } @@ -107,9 +111,9 @@ func (m *MockSubscriber) Register(arg0 string, arg1 pubsub.GossipHandler, arg2 . } // Register indicates an expected call of Register. -func (mr *MockSubscriberMockRecorder) Register(arg0, arg1 interface{}, arg2 ...interface{}) *SubscriberRegisterCall { +func (mr *MockSubscriberMockRecorder) Register(arg0, arg1 any, arg2 ...any) *SubscriberRegisterCall { mr.mock.ctrl.T.Helper() - varargs := append([]interface{}{arg0, arg1}, arg2...) + varargs := append([]any{arg0, arg1}, arg2...) call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Register", reflect.TypeOf((*MockSubscriber)(nil).Register), varargs...) return &SubscriberRegisterCall{Call: call} } @@ -169,7 +173,7 @@ func (m *MockPublishSubsciber) Publish(arg0 context.Context, arg1 string, arg2 [ } // Publish indicates an expected call of Publish. -func (mr *MockPublishSubsciberMockRecorder) Publish(arg0, arg1, arg2 interface{}) *PublishSubsciberPublishCall { +func (mr *MockPublishSubsciberMockRecorder) Publish(arg0, arg1, arg2 any) *PublishSubsciberPublishCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Publish", reflect.TypeOf((*MockPublishSubsciber)(nil).Publish), arg0, arg1, arg2) return &PublishSubsciberPublishCall{Call: call} @@ -201,7 +205,7 @@ func (c *PublishSubsciberPublishCall) DoAndReturn(f func(context.Context, string // Register mocks base method. func (m *MockPublishSubsciber) Register(arg0 string, arg1 pubsub.GossipHandler, arg2 ...pubsub.ValidatorOpt) { m.ctrl.T.Helper() - varargs := []interface{}{arg0, arg1} + varargs := []any{arg0, arg1} for _, a := range arg2 { varargs = append(varargs, a) } @@ -209,9 +213,9 @@ func (m *MockPublishSubsciber) Register(arg0 string, arg1 pubsub.GossipHandler, } // Register indicates an expected call of Register. -func (mr *MockPublishSubsciberMockRecorder) Register(arg0, arg1 interface{}, arg2 ...interface{}) *PublishSubsciberRegisterCall { +func (mr *MockPublishSubsciberMockRecorder) Register(arg0, arg1 any, arg2 ...any) *PublishSubsciberRegisterCall { mr.mock.ctrl.T.Helper() - varargs := append([]interface{}{arg0, arg1}, arg2...) + varargs := append([]any{arg0, arg1}, arg2...) call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Register", reflect.TypeOf((*MockPublishSubsciber)(nil).Register), varargs...) return &PublishSubsciberRegisterCall{Call: call} } diff --git a/p2p/server/mocks/mocks.go b/p2p/server/mocks/mocks.go index b9cc09c091..50557f6320 100644 --- a/p2p/server/mocks/mocks.go +++ b/p2p/server/mocks/mocks.go @@ -1,6 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: ./server.go - +// +// Generated by this command: +// +// mockgen -typed -package=mocks -destination=./mocks/mocks.go -source=./server.go +// // Package mocks is a generated GoMock package. package mocks @@ -78,7 +82,7 @@ func (c *HostNetworkCall) DoAndReturn(f func() network.Network) *HostNetworkCall // NewStream mocks base method. func (m *MockHost) NewStream(arg0 context.Context, arg1 peer.ID, arg2 ...protocol.ID) (network.Stream, error) { m.ctrl.T.Helper() - varargs := []interface{}{arg0, arg1} + varargs := []any{arg0, arg1} for _, a := range arg2 { varargs = append(varargs, a) } @@ -89,9 +93,9 @@ func (m *MockHost) NewStream(arg0 context.Context, arg1 peer.ID, arg2 ...protoco } // NewStream indicates an expected call of NewStream. -func (mr *MockHostMockRecorder) NewStream(arg0, arg1 interface{}, arg2 ...interface{}) *HostNewStreamCall { +func (mr *MockHostMockRecorder) NewStream(arg0, arg1 any, arg2 ...any) *HostNewStreamCall { mr.mock.ctrl.T.Helper() - varargs := append([]interface{}{arg0, arg1}, arg2...) + varargs := append([]any{arg0, arg1}, arg2...) call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewStream", reflect.TypeOf((*MockHost)(nil).NewStream), varargs...) return &HostNewStreamCall{Call: call} } @@ -126,7 +130,7 @@ func (m *MockHost) SetStreamHandler(arg0 protocol.ID, arg1 network.StreamHandler } // SetStreamHandler indicates an expected call of SetStreamHandler. -func (mr *MockHostMockRecorder) SetStreamHandler(arg0, arg1 interface{}) *HostSetStreamHandlerCall { +func (mr *MockHostMockRecorder) SetStreamHandler(arg0, arg1 any) *HostSetStreamHandlerCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetStreamHandler", reflect.TypeOf((*MockHost)(nil).SetStreamHandler), arg0, arg1) return &HostSetStreamHandlerCall{Call: call} diff --git a/p2p/upgrade.go b/p2p/upgrade.go index 15a35961ae..d917c952a7 100644 --- a/p2p/upgrade.go +++ b/p2p/upgrade.go @@ -132,9 +132,6 @@ func Upgrade(h host.Host, opts ...Opt) (*Host, error) { if cfg.PrivateNetwork { dopts = append(dopts, discovery.Private()) } - if cfg.DisableDHT { - dopts = append(dopts, discovery.DisableDHT()) - } if cfg.Bootnode { dopts = append(dopts, discovery.Server()) } else { diff --git a/proposals/eligibility_validator.go b/proposals/eligibility_validator.go index 71ce637450..ca95088ad0 100644 --- a/proposals/eligibility_validator.go +++ b/proposals/eligibility_validator.go @@ -70,7 +70,7 @@ func NewEligibilityValidator( } // CheckEligibility checks that a ballot is eligible in the layer that it specifies. -func (v *Validator) CheckEligibility(ctx context.Context, ballot *types.Ballot) (bool, error) { +func (v *Validator) CheckEligibility(ctx context.Context, ballot *types.Ballot, actives []types.ATXID) (bool, error) { if len(ballot.EligibilityProofs) == 0 { return false, fmt.Errorf("empty eligibility list is invalid (ballot %s)", ballot.ID()) } @@ -92,7 +92,7 @@ func (v *Validator) CheckEligibility(ctx context.Context, ballot *types.Ballot) var data *types.EpochData if ballot.EpochData != nil && ballot.Layer.GetEpoch() == v.clock.CurrentLayer().GetEpoch() { var err error - data, err = v.validateReference(ballot, owned) + data, err = v.validateReference(ballot, actives, owned) if err != nil { return false, err } @@ -136,22 +136,22 @@ func (v *Validator) CheckEligibility(ctx context.Context, ballot *types.Ballot) } // validateReference executed for reference ballots in latest epoch. -func (v *Validator) validateReference(ballot *types.Ballot, owned *types.ActivationTxHeader) (*types.EpochData, error) { +func (v *Validator) validateReference(ballot *types.Ballot, actives []types.ATXID, owned *types.ActivationTxHeader) (*types.EpochData, error) { if ballot.EpochData.Beacon == types.EmptyBeacon { return nil, fmt.Errorf("%w: ref ballot %v", errMissingBeacon, ballot.ID()) } - if len(ballot.ActiveSet) == 0 { + if len(actives) == 0 { return nil, fmt.Errorf("%w: ref ballot %v", errEmptyActiveSet, ballot.ID()) } var totalWeight uint64 - for _, atxID := range ballot.ActiveSet { + for _, atxID := range actives { atx, err := v.cdb.GetAtxHeader(atxID) if err != nil { return nil, fmt.Errorf("atx in active set is missing %v: %w", atxID, err) } totalWeight += atx.GetWeight() } - numEligibleSlots, err := GetLegacyNumEligible(ballot.Layer, owned.GetWeight(), v.minActiveSetWeight, totalWeight, v.avgLayerSize, v.layersPerEpoch) + numEligibleSlots, err := GetNumEligibleSlots(owned.GetWeight(), v.minActiveSetWeight, totalWeight, v.avgLayerSize, v.layersPerEpoch) if err != nil { return nil, err } diff --git a/proposals/eligibility_validator_test.go b/proposals/eligibility_validator_test.go index ecdc6ec4c6..ce4a866e6a 100644 --- a/proposals/eligibility_validator_test.go +++ b/proposals/eligibility_validator_test.go @@ -64,14 +64,15 @@ func gatxNilNonce(id types.ATXID, epoch types.EpochID, smesher types.NodeID, uni return *verified } -func gdata(slots uint32, beacon types.Beacon) *types.EpochData { +func gdata(slots uint32, beacon types.Beacon, hash types.Hash32) *types.EpochData { return &types.EpochData{ Beacon: beacon, EligibilityCount: slots, + ActiveSetHash: hash, } } -func gactiveset(atxs ...types.ATXID) []types.ATXID { +func gactiveset(atxs ...types.ATXID) types.ATXIDList { return atxs } @@ -89,7 +90,7 @@ func geligibilityWithSig(j uint32, sig string) []types.VotingEligibility { return []types.VotingEligibility{el} } -func gballot(id types.BallotID, atxid types.ATXID, activeset []types.ATXID, smesher types.NodeID, layer types.LayerID, +func gballot(id types.BallotID, atxid types.ATXID, smesher types.NodeID, layer types.LayerID, edata *types.EpochData, eligibilities []types.VotingEligibility, ) types.Ballot { ballot := types.Ballot{} @@ -97,7 +98,6 @@ func gballot(id types.BallotID, atxid types.ATXID, activeset []types.ATXID, smes ballot.EpochData = edata ballot.AtxID = atxid ballot.EligibilityProofs = eligibilities - ballot.ActiveSet = activeset ballot.SmesherID = smesher ballot.SetID(id) return ballot @@ -128,6 +128,7 @@ func TestEligibilityValidator(t *testing.T) { current types.LayerID minWeight uint64 atxs []types.VerifiedActivationTx + actives types.ATXIDList ballots []types.Ballot vrfFailed bool executed types.Ballot @@ -141,9 +142,10 @@ func TestEligibilityValidator(t *testing.T) { gatx(types.ATXID{1}, publish, types.NodeID{1}, 10, 10), gatx(types.ATXID{2}, publish, types.NodeID{2}, 10, 10), }, + actives: gactiveset(types.ATXID{1}, types.ATXID{2}), executed: gballot( - types.BallotID{1}, types.ATXID{1}, gactiveset(types.ATXID{1}, types.ATXID{2}), - types.NodeID{1}, epoch.FirstLayer(), gdata(15, types.Beacon{1}), + types.BallotID{1}, types.ATXID{1}, + types.NodeID{1}, epoch.FirstLayer(), gdata(15, types.Beacon{1}, gactiveset(types.ATXID{1}, types.ATXID{2}).Hash()), geligibilities(1, 2), ), }, @@ -155,9 +157,10 @@ func TestEligibilityValidator(t *testing.T) { gatx(types.ATXID{1}, publish, types.NodeID{1}, 10, 10), gatx(types.ATXID{2}, publish, types.NodeID{2}, 10, 10), }, + actives: gactiveset(types.ATXID{1}, types.ATXID{2}), executed: gballot( - types.BallotID{1}, types.ATXID{1}, gactiveset(types.ATXID{1}, types.ATXID{2}), - types.NodeID{1}, epoch.FirstLayer(), gdata(3, types.Beacon{1}), + types.BallotID{1}, types.ATXID{1}, + types.NodeID{1}, epoch.FirstLayer(), gdata(3, types.Beacon{1}, gactiveset(types.ATXID{1}, types.ATXID{2}).Hash()), geligibilities(1, 2), ), }, @@ -167,9 +170,10 @@ func TestEligibilityValidator(t *testing.T) { atxs: []types.VerifiedActivationTx{ gatxZeroHeight(types.ATXID{1}, publish, types.NodeID{1}, 10, 10), }, + actives: gactiveset(types.ATXID{1}), executed: gballot( - types.BallotID{1}, types.ATXID{1}, gactiveset(types.ATXID{1}), - types.NodeID{1}, epoch.FirstLayer(), gdata(15, types.Beacon{1}), + types.BallotID{1}, types.ATXID{1}, + types.NodeID{1}, epoch.FirstLayer(), gdata(15, types.Beacon{1}, gactiveset(types.ATXID{1}).Hash()), geligibilities(1, 2), ), fail: true, @@ -182,16 +186,16 @@ func TestEligibilityValidator(t *testing.T) { gatx(types.ATXID{1}, publish-1, types.NodeID{1}, 10, 10), }, executed: gballot( - types.BallotID{1}, types.ATXID{1}, nil, - types.NodeID{1}, publish.FirstLayer(), gdata(15, types.Beacon{1}), + types.BallotID{1}, types.ATXID{1}, + types.NodeID{1}, publish.FirstLayer(), gdata(15, types.Beacon{1}, types.Hash32{}), geligibilities(1, 2), ), }, { desc: "no eligibilities", executed: gballot( - types.BallotID{1}, types.ATXID{1}, nil, - types.NodeID{1}, publish.FirstLayer(), gdata(15, types.Beacon{1}), + types.BallotID{1}, types.ATXID{1}, + types.NodeID{1}, publish.FirstLayer(), gdata(15, types.Beacon{1}, types.Hash32{}), nil, ), fail: true, @@ -200,8 +204,8 @@ func TestEligibilityValidator(t *testing.T) { { desc: "no atx", executed: gballot( - types.BallotID{1}, types.ATXID{1}, nil, - types.NodeID{1}, publish.FirstLayer(), gdata(15, types.Beacon{1}), + types.BallotID{1}, types.ATXID{1}, + types.NodeID{1}, publish.FirstLayer(), gdata(15, types.Beacon{1}, types.Hash32{}), geligibilities(1, 2), ), fail: true, @@ -214,7 +218,7 @@ func TestEligibilityValidator(t *testing.T) { gatx(types.ATXID{1}, publish-1, types.NodeID{1}, 10, 10), }, executed: gballot( - types.BallotID{1}, types.ATXID{1}, nil, + types.BallotID{1}, types.ATXID{1}, types.NodeID{1}, publish.FirstLayer(), nil, geligibilities(1, 2), ), @@ -228,7 +232,7 @@ func TestEligibilityValidator(t *testing.T) { gatx(types.ATXID{1}, epoch-1, types.NodeID{1}, 10, 10), }, executed: gballot( - types.BallotID{1}, types.ATXID{1}, nil, + types.BallotID{1}, types.ATXID{1}, types.NodeID{1}, epoch.FirstLayer(), nil, geligibilities(1, 2), ), @@ -241,9 +245,10 @@ func TestEligibilityValidator(t *testing.T) { atxs: []types.VerifiedActivationTx{ gatx(types.ATXID{1}, epoch-1, types.NodeID{1}, 10, 10), }, + actives: types.ATXIDList{}, executed: gballot( - types.BallotID{1}, types.ATXID{1}, nil, - types.NodeID{1}, epoch.FirstLayer(), gdata(10, types.Beacon{1}), + types.BallotID{1}, types.ATXID{1}, + types.NodeID{1}, epoch.FirstLayer(), gdata(10, types.Beacon{1}, types.ATXIDList{}.Hash()), geligibilities(1, 2), ), fail: true, @@ -256,8 +261,8 @@ func TestEligibilityValidator(t *testing.T) { gatx(types.ATXID{1}, epoch-1, types.NodeID{1}, 10, 10), }, executed: gballot( - types.BallotID{1}, types.ATXID{1}, nil, - types.NodeID{1}, epoch.FirstLayer(), gdata(10, types.EmptyBeacon), + types.BallotID{1}, types.ATXID{1}, + types.NodeID{1}, epoch.FirstLayer(), gdata(10, types.EmptyBeacon, types.Hash32{}), geligibilities(1, 2), ), fail: true, @@ -269,9 +274,10 @@ func TestEligibilityValidator(t *testing.T) { atxs: []types.VerifiedActivationTx{ gatx(types.ATXID{1}, epoch-1, types.NodeID{1}, 10, 10), }, + actives: gactiveset(types.ATXID{1}, types.ATXID{2}), executed: gballot( - types.BallotID{1}, types.ATXID{1}, gactiveset(types.ATXID{1}, types.ATXID{2}), - types.NodeID{1}, epoch.FirstLayer(), gdata(10, types.Beacon{1}), + types.BallotID{1}, types.ATXID{1}, + types.NodeID{1}, epoch.FirstLayer(), gdata(10, types.Beacon{1}, gactiveset(types.ATXID{1}, types.ATXID{2}).Hash()), geligibilities(1, 2), ), fail: true, @@ -283,9 +289,10 @@ func TestEligibilityValidator(t *testing.T) { atxs: []types.VerifiedActivationTx{ gatx(types.ATXID{1}, epoch-1, types.NodeID{1}, 10, 0), }, + actives: gactiveset(types.ATXID{1}), executed: gballot( - types.BallotID{1}, types.ATXID{1}, gactiveset(types.ATXID{1}), - types.NodeID{1}, epoch.FirstLayer(), gdata(10, types.Beacon{1}), + types.BallotID{1}, types.ATXID{1}, + types.NodeID{1}, epoch.FirstLayer(), gdata(10, types.Beacon{1}, gactiveset(types.ATXID{1}).Hash()), geligibilities(1, 2), ), fail: true, @@ -297,9 +304,10 @@ func TestEligibilityValidator(t *testing.T) { atxs: []types.VerifiedActivationTx{ gatx(types.ATXID{1}, epoch-1, types.NodeID{1}, 10, 0), }, + actives: gactiveset(types.ATXID{1}), executed: gballot( - types.BallotID{1}, types.ATXID{1}, gactiveset(types.ATXID{1}), - types.NodeID{1}, (epoch + 1).FirstLayer(), gdata(10, types.Beacon{1}), + types.BallotID{1}, types.ATXID{1}, + types.NodeID{1}, (epoch + 1).FirstLayer(), gdata(10, types.Beacon{1}, gactiveset(types.ATXID{1}).Hash()), geligibilities(1, 2), ), fail: true, @@ -311,9 +319,10 @@ func TestEligibilityValidator(t *testing.T) { atxs: []types.VerifiedActivationTx{ gatx(types.ATXID{1}, epoch-1, types.NodeID{2}, 10, 0), }, + actives: gactiveset(types.ATXID{1}), executed: gballot( - types.BallotID{1}, types.ATXID{1}, gactiveset(types.ATXID{1}), - types.NodeID{1}, epoch.FirstLayer(), gdata(10, types.Beacon{1}), + types.BallotID{1}, types.ATXID{1}, + types.NodeID{1}, epoch.FirstLayer(), gdata(10, types.Beacon{1}, gactiveset(types.ATXID{1}).Hash()), geligibilities(1, 2), ), fail: true, @@ -325,9 +334,10 @@ func TestEligibilityValidator(t *testing.T) { atxs: []types.VerifiedActivationTx{ gatxNilNonce(types.ATXID{1}, epoch-1, types.NodeID{1}, 10), }, + actives: gactiveset(types.ATXID{1}), executed: gballot( - types.BallotID{1}, types.ATXID{1}, gactiveset(types.ATXID{1}), - types.NodeID{1}, epoch.FirstLayer(), gdata(10, types.Beacon{1}), + types.BallotID{1}, types.ATXID{1}, + types.NodeID{1}, epoch.FirstLayer(), gdata(10, types.Beacon{1}, gactiveset(types.ATXID{1}).Hash()), geligibilities(1, 2), ), fail: true, @@ -342,10 +352,9 @@ func TestEligibilityValidator(t *testing.T) { ballots: []types.Ballot{ gballot( types.BallotID{1}, types.ATXID{1}, - nil, types.NodeID{1, 1, 1}, epoch.FirstLayer(), - gdata(10, types.Beacon{1}), + gdata(10, types.Beacon{1}, types.Hash32{}), nil, ), }, @@ -398,10 +407,9 @@ func TestEligibilityValidator(t *testing.T) { ballots: []types.Ballot{ gballot( types.BallotID{1}, types.ATXID{2}, - nil, types.NodeID{1, 1, 1}, epoch.FirstLayer(), - gdata(10, types.Beacon{1}), + gdata(10, types.Beacon{1}, types.Hash32{}), nil, ), }, @@ -424,10 +432,9 @@ func TestEligibilityValidator(t *testing.T) { ballots: []types.Ballot{ gballot( types.BallotID{1}, types.ATXID{1}, - nil, types.NodeID{2, 2, 2}, epoch.FirstLayer(), - gdata(10, types.Beacon{1}), + gdata(10, types.Beacon{1}, types.Hash32{}), nil, ), }, @@ -450,10 +457,9 @@ func TestEligibilityValidator(t *testing.T) { ballots: []types.Ballot{ gballot( types.BallotID{1}, types.ATXID{1}, - nil, types.NodeID{1, 1, 1}, (epoch + 1).FirstLayer(), - gdata(10, types.Beacon{1}), + gdata(10, types.Beacon{1}, types.Hash32{}), nil, ), }, @@ -474,9 +480,10 @@ func TestEligibilityValidator(t *testing.T) { gatx(types.ATXID{1}, publish, types.NodeID{1}, 10, 10), gatx(types.ATXID{2}, publish, types.NodeID{2}, 10, 10), }, + actives: gactiveset(types.ATXID{1}, types.ATXID{2}), executed: gballot( - types.BallotID{1}, types.ATXID{1}, gactiveset(types.ATXID{1}, types.ATXID{2}), - types.NodeID{1}, epoch.FirstLayer(), gdata(15, types.Beacon{1}), + types.BallotID{1}, types.ATXID{1}, + types.NodeID{1}, epoch.FirstLayer(), gdata(15, types.Beacon{1}, gactiveset(types.ATXID{1}, types.ATXID{2}).Hash()), geligibilities(2, 1, 3), ), fail: true, @@ -489,9 +496,10 @@ func TestEligibilityValidator(t *testing.T) { gatx(types.ATXID{1}, publish, types.NodeID{1}, 10, 10), gatx(types.ATXID{2}, publish, types.NodeID{2}, 10, 10), }, + actives: gactiveset(types.ATXID{1}, types.ATXID{2}), executed: gballot( - types.BallotID{1}, types.ATXID{1}, gactiveset(types.ATXID{1}, types.ATXID{2}), - types.NodeID{1}, epoch.FirstLayer(), gdata(15, types.Beacon{1}), + types.BallotID{1}, types.ATXID{1}, + types.NodeID{1}, epoch.FirstLayer(), gdata(15, types.Beacon{1}, gactiveset(types.ATXID{1}, types.ATXID{2}).Hash()), geligibilities(15), ), fail: true, @@ -504,9 +512,10 @@ func TestEligibilityValidator(t *testing.T) { gatx(types.ATXID{1}, publish, types.NodeID{1}, 10, 10), gatx(types.ATXID{2}, publish, types.NodeID{2}, 10, 10), }, + actives: gactiveset(types.ATXID{1}, types.ATXID{2}), executed: gballot( - types.BallotID{1}, types.ATXID{1}, gactiveset(types.ATXID{1}, types.ATXID{2}), - types.NodeID{1}, epoch.FirstLayer(), gdata(15, types.Beacon{1}), + types.BallotID{1}, types.ATXID{1}, + types.NodeID{1}, epoch.FirstLayer(), gdata(15, types.Beacon{1}, gactiveset(types.ATXID{1}, types.ATXID{2}).Hash()), geligibilities(14), ), vrfFailed: true, @@ -520,9 +529,10 @@ func TestEligibilityValidator(t *testing.T) { gatx(types.ATXID{1}, publish, types.NodeID{1}, 10, 10), gatx(types.ATXID{2}, publish, types.NodeID{2}, 10, 10), }, + actives: gactiveset(types.ATXID{1}, types.ATXID{2}), executed: gballot( - types.BallotID{1}, types.ATXID{1}, gactiveset(types.ATXID{1}, types.ATXID{2}), - types.NodeID{1}, epoch.FirstLayer(), gdata(15, types.Beacon{1}), + types.BallotID{1}, types.ATXID{1}, + types.NodeID{1}, epoch.FirstLayer(), gdata(15, types.Beacon{1}, gactiveset(types.ATXID{1}, types.ATXID{2}).Hash()), geligibilityWithSig(1, "adjust layer"), ), fail: true, @@ -564,7 +574,7 @@ func TestEligibilityValidator(t *testing.T) { if !tc.fail { ms.mbc.EXPECT().ReportBeaconFromBallot(tc.executed.Layer.GetEpoch(), &tc.executed, gomock.Any(), gomock.Any()) } - rst, err := tv.CheckEligibility(context.Background(), &tc.executed) + rst, err := tv.CheckEligibility(context.Background(), &tc.executed, tc.actives) assert.Equal(t, !tc.fail, rst) if len(tc.err) == 0 { assert.Empty(t, err) diff --git a/proposals/handler.go b/proposals/handler.go index bbd7184099..0ef1ccc371 100644 --- a/proposals/handler.go +++ b/proposals/handler.go @@ -66,7 +66,6 @@ type Config struct { MaxExceptions int Hdist uint32 MinimalActiveSetWeight uint64 - AllowEmptyActiveSet types.LayerID } // defaultConfig for BlockHandler. @@ -262,17 +261,15 @@ func (h *Handler) handleProposal(ctx context.Context, expHash types.Hash32, peer preGenesis.Inc() return fmt.Errorf("proposal before effective genesis: layer %v", p.Layer) } + if p.Layer <= h.mesh.ProcessedLayer() { + // old proposals have no use for the node + tooLate.Inc() + return fmt.Errorf("proposal too late: layer %v", p.Layer) + } latency := receivedTime.Sub(h.clock.LayerToTime(p.Layer)) metrics.ReportMessageLatency(pubsub.ProposalProtocol, pubsub.ProposalProtocol, latency) - set := p.ActiveSet - // on sync path activeset is downloaded together with proposal - // but starting at layer AllowEmptyActiveSet proposals are signed without activeset - if p.Layer >= h.cfg.AllowEmptyActiveSet { - p.ActiveSet = nil - } - if !h.edVerifier.Verify(signing.PROPOSAL, p.SmesherID, p.SignedBytes(), p.Signature) { badSigProposal.Inc() return fmt.Errorf("failed to verify proposal signature") @@ -283,8 +280,6 @@ func (h *Handler) handleProposal(ctx context.Context, expHash types.Hash32, peer } // set the proposal ID when received - // It mustn't contain the active set if layer >= AllowEmptyActiveSet - // (p.Initialize uses SignedBytes again). if err := p.Initialize(); err != nil { failedInit.Inc() return errInitialize @@ -292,7 +287,6 @@ func (h *Handler) handleProposal(ctx context.Context, expHash types.Hash32, peer if expHash != (types.Hash32{}) && p.ID().AsHash32() != expHash { return fmt.Errorf("%w: proposal want %s, got %s", errWrongHash, expHash.ShortString(), p.ID().AsHash32().ShortString()) } - p.ActiveSet = set if p.AtxID == types.EmptyATXID || p.AtxID == h.cfg.GoldenATXID { badData.Inc() @@ -311,7 +305,9 @@ func (h *Handler) handleProposal(ctx context.Context, expHash types.Hash32, peer } proposalDuration.WithLabelValues(dbLookup).Observe(float64(time.Since(t1))) - logger.With().Info("new proposal", log.Int("num_txs", len(p.TxIDs))) + logger.With().Info("new proposal", + log.String("exp hash", expHash.ShortString()), + log.Int("num_txs", len(p.TxIDs))) t2 := time.Now() h.fetcher.RegisterPeerHashes(peer, collectHashes(p)) proposalDuration.WithLabelValues(peerHashes).Observe(float64(time.Since(t2))) @@ -385,6 +381,7 @@ func (h *Handler) processBallot(ctx context.Context, logger log.Log, b *types.Ba if err != nil { return nil, err } + b.ActiveSet = nil t1 := time.Now() proof, err := h.mesh.AddBallot(ctx, b) @@ -408,7 +405,8 @@ func (h *Handler) processBallot(ctx context.Context, logger log.Log, b *types.Ba func (h *Handler) checkBallotSyntacticValidity(ctx context.Context, logger log.Log, b *types.Ballot) (*tortoise.DecodedBallot, error) { t0 := time.Now() - if err := h.checkBallotDataIntegrity(ctx, b); err != nil { + actives, err := h.checkBallotDataIntegrity(ctx, b) + if err != nil { badData.Inc() return nil, err } @@ -443,7 +441,7 @@ func (h *Handler) checkBallotSyntacticValidity(ctx context.Context, logger log.L ballotDuration.WithLabelValues(votes).Observe(float64(time.Since(t3))) t4 := time.Now() - if eligible, err := h.validator.CheckEligibility(ctx, b); err != nil || !eligible { + if eligible, err := h.validator.CheckEligibility(ctx, b, actives); err != nil || !eligible { notEligible.Inc() var reason string if err != nil { @@ -457,45 +455,43 @@ func (h *Handler) checkBallotSyntacticValidity(ctx context.Context, logger log.L return decoded, nil } -func (h *Handler) checkBallotDataIntegrity(ctx context.Context, b *types.Ballot) error { +func (h *Handler) checkBallotDataIntegrity(ctx context.Context, b *types.Ballot) ([]types.ATXID, error) { + var actives []types.ATXID if b.RefBallot == types.EmptyBallotID { // this is the smesher's first Ballot in this epoch, should contain EpochData if b.EpochData == nil { - return errMissingEpochData + return nil, errMissingEpochData } if b.EpochData.Beacon == types.EmptyBeacon { - return errMissingBeacon - } - if len(b.ActiveSet) == 0 && b.Layer < h.cfg.AllowEmptyActiveSet { - return fmt.Errorf("%w: empty active set ballot %s", pubsub.ErrValidationReject, b.ID().String()) + return nil, errMissingBeacon } + // TODO: remove after the network no longer populate ActiveSet in ballot. if len(b.ActiveSet) != 0 { - if err := h.handleSet(ctx, b.EpochData.ActiveSetHash, types.EpochActiveSet{ + set := types.EpochActiveSet{ Epoch: b.Layer.GetEpoch(), Set: b.ActiveSet, - }); err != nil { - return err } + if err := h.handleSet(ctx, b.EpochData.ActiveSetHash, set); err != nil { + return nil, err + } + actives = set.Set } else { if err := h.fetcher.GetActiveSet(ctx, b.EpochData.ActiveSetHash); err != nil { - return err + return nil, err } set, err := activesets.Get(h.cdb, b.EpochData.ActiveSetHash) if err != nil { - return err + return nil, err } if len(set.Set) == 0 { - return fmt.Errorf("%w: empty active set ballot %s", pubsub.ErrValidationReject, b.ID().String()) + return nil, fmt.Errorf("%w: empty active set ballot %s", pubsub.ErrValidationReject, b.ID().String()) } - // NOTE(dshulyak) sidecar is still stored in reference ballot, so that - // nodes that won't update on time will be able to download it - // with sync - b.ActiveSet = set.Set + actives = set.Set } } else if b.EpochData != nil { - return errUnexpectedEpochData + return nil, errUnexpectedEpochData } - return nil + return actives, nil } func (h *Handler) checkVotesConsistency(ctx context.Context, b *types.Ballot) error { diff --git a/proposals/handler_test.go b/proposals/handler_test.go index 3919513f2f..f491b6e87f 100644 --- a/proposals/handler_test.go +++ b/proposals/handler_test.go @@ -60,6 +60,7 @@ func (ms *mockSet) decodeAnyBallots() *mockSet { func (ms *mockSet) setCurrentLayer(layer types.LayerID) *mockSet { ms.mclock.EXPECT().CurrentLayer().Return(layer).AnyTimes() + ms.mm.EXPECT().ProcessedLayer().Return(layer - 1).AnyTimes() ms.mclock.EXPECT().LayerToTime(gomock.Any()).Return(time.Now().Add(-5 * time.Second)).AnyTimes() return ms } @@ -162,10 +163,9 @@ func withLayer(lid types.LayerID) createBallotOpt { } } -func withAnyRefData() createBallotOpt { +func withRefData(activeSet types.ATXIDList) createBallotOpt { return func(b *types.Ballot) { b.RefBallot = types.EmptyBallotID - activeSet := types.ATXIDList{types.RandomATXID(), types.RandomATXID()} sort.Slice(activeSet, func(i, j int) bool { return bytes.Compare(activeSet[i].Bytes(), activeSet[j].Bytes()) < 0 }) @@ -173,7 +173,6 @@ func withAnyRefData() createBallotOpt { ActiveSetHash: activeSet.Hash(), Beacon: types.RandomBeacon(), } - b.ActiveSet = activeSet } } @@ -188,6 +187,7 @@ func withTransactions(ids ...types.TransactionID) createProposalOpt { func createProposal(t *testing.T, opts ...any) *types.Proposal { t.Helper() b := types.RandomBallot() + b.Layer = 10000 p := &types.Proposal{ InnerProposal: types.InnerProposal{ Ballot: *b, @@ -254,16 +254,14 @@ func signAndInit(tb testing.TB, b *types.Ballot) *types.Ballot { return b } -func createRefBallot(t *testing.T) *types.Ballot { +func createRefBallot(t *testing.T, actives types.ATXIDList) *types.Ballot { t.Helper() b := types.RandomBallot() b.RefBallot = types.EmptyBallotID - activeSet := types.ATXIDList{types.ATXID{1, 2, 3}, types.ATXID{2, 3, 4}} b.EpochData = &types.EpochData{ - ActiveSetHash: activeSet.Hash(), + ActiveSetHash: actives.Hash(), Beacon: types.RandomBeacon(), } - b.ActiveSet = activeSet return b } @@ -345,7 +343,7 @@ func TestBallot_GoldenATXID(t *testing.T) { func TestBallot_RefBallotMissingEpochData(t *testing.T) { th := createTestHandlerNoopDecoder(t) - b := createRefBallot(t) + b := createRefBallot(t, types.ATXIDList{{1}, {2}}) b.EpochData = nil signAndInit(t, b) createAtx(t, th.cdb.Database, b.Layer.GetEpoch()-1, b.AtxID, b.SmesherID) @@ -357,7 +355,9 @@ func TestBallot_RefBallotMissingEpochData(t *testing.T) { func TestBallot_RefBallotMissingBeacon(t *testing.T) { th := createTestHandlerNoopDecoder(t) - b := createRefBallot(t) + activeSet := types.ATXIDList{{1}, {2}} + b := createRefBallot(t, activeSet) + require.NoError(t, activesets.Add(th.cdb, activeSet.Hash(), &types.EpochActiveSet{Set: activeSet})) b.EpochData.Beacon = types.EmptyBeacon signAndInit(t, b) createAtx(t, th.cdb.Database, b.Layer.GetEpoch()-1, b.AtxID, b.SmesherID) @@ -369,8 +369,8 @@ func TestBallot_RefBallotMissingBeacon(t *testing.T) { func TestBallot_RefBallotEmptyActiveSet(t *testing.T) { th := createTestHandlerNoopDecoder(t) - b := createRefBallot(t) - b.ActiveSet = nil + activeSet := types.ATXIDList{{1}, {2}} + b := createRefBallot(t, activeSet) signAndInit(t, b) data := codec.MustEncode(b) createAtx(t, th.cdb.Database, b.Layer.GetEpoch()-1, b.AtxID, b.SmesherID) @@ -380,10 +380,12 @@ func TestBallot_RefBallotEmptyActiveSet(t *testing.T) { require.ErrorIs(t, th.HandleSyncedBallot(context.Background(), b.ID().AsHash32(), peer, data), sql.ErrNotFound) } +// TODO: remove after the network no longer populate ActiveSet in ballot. func TestBallot_RefBallotDuplicateInActiveSet(t *testing.T) { th := createTestHandlerNoopDecoder(t) - b := createRefBallot(t) - b.ActiveSet = append(b.ActiveSet, b.ActiveSet[0]) + activeSet := types.ATXIDList{{1}, {2}, {1}} + b := createRefBallot(t, activeSet) + b.ActiveSet = activeSet signAndInit(t, b) createAtx(t, th.cdb.Database, b.Layer.GetEpoch()-1, b.AtxID, b.SmesherID) data := codec.MustEncode(b) @@ -392,13 +394,12 @@ func TestBallot_RefBallotDuplicateInActiveSet(t *testing.T) { require.ErrorContains(t, th.HandleSyncedBallot(context.Background(), b.ID().AsHash32(), peer, data), "not sorted") } +// TODO: remove after the network no longer populate ActiveSet in ballot. func TestBallot_RefBallotActiveSetNotSorted(t *testing.T) { th := createTestHandlerNoopDecoder(t) - b := createRefBallot(t) - b.ActiveSet = types.RandomActiveSet(11) - sort.Slice(b.ActiveSet, func(i, j int) bool { - return bytes.Compare(b.ActiveSet[i].Bytes(), b.ActiveSet[j].Bytes()) > 0 - }) + activeSet := types.ATXIDList(types.RandomActiveSet(11)) + b := createRefBallot(t, activeSet) + b.ActiveSet = activeSet signAndInit(t, b) createAtx(t, th.cdb.Database, b.Layer.GetEpoch()-1, b.AtxID, b.SmesherID) data := codec.MustEncode(b) @@ -407,18 +408,6 @@ func TestBallot_RefBallotActiveSetNotSorted(t *testing.T) { require.ErrorContains(t, th.HandleSyncedBallot(context.Background(), b.ID().AsHash32(), peer, data), "not sorted") } -func TestBallot_RefBallotBadActiveSetHash(t *testing.T) { - th := createTestHandlerNoopDecoder(t) - b := createRefBallot(t) - b.EpochData.ActiveSetHash = types.Hash32{} - signAndInit(t, b) - createAtx(t, th.cdb.Database, b.Layer.GetEpoch()-1, b.AtxID, b.SmesherID) - data := codec.MustEncode(b) - peer := p2p.Peer("buddy") - th.mf.EXPECT().RegisterPeerHashes(peer, collectHashes(*b)) - require.ErrorContains(t, th.HandleSyncedBallot(context.Background(), b.ID().AsHash32(), peer, data), "wrong hash") -} - func TestBallot_NotRefBallotButHasEpochData(t *testing.T) { th := createTestHandlerNoopDecoder(t) b := types.RandomBallot() @@ -505,8 +494,8 @@ func TestBallot_BallotDoubleVotedOutsideHdist(t *testing.T) { th.mf.EXPECT().GetBallots(gomock.Any(), []types.BallotID{b.Votes.Base, b.RefBallot}).Return(nil).Times(1) th.md.EXPECT().GetMissingActiveSet(gomock.Any(), types.ATXIDList{b.AtxID}).Return(types.ATXIDList{b.AtxID}) th.mf.EXPECT().GetAtxs(gomock.Any(), types.ATXIDList{b.AtxID}).Return(nil).Times(1) - th.mv.EXPECT().CheckEligibility(gomock.Any(), gomock.Any()).DoAndReturn( - func(_ context.Context, ballot *types.Ballot) (bool, error) { + th.mv.EXPECT().CheckEligibility(gomock.Any(), gomock.Any(), nil).DoAndReturn( + func(_ context.Context, ballot *types.Ballot, _ []types.ATXID) (bool, error) { require.Equal(t, b.ID(), ballot.ID()) return true, nil }) @@ -664,8 +653,8 @@ func TestBallot_ErrorCheckingEligible(t *testing.T) { th.mf.EXPECT().GetBallots(gomock.Any(), []types.BallotID{b.Votes.Base, b.RefBallot}).Return(nil).Times(1) th.md.EXPECT().GetMissingActiveSet(gomock.Any(), types.ATXIDList{b.AtxID}).Return(types.ATXIDList{b.AtxID}) th.mf.EXPECT().GetAtxs(gomock.Any(), types.ATXIDList{b.AtxID}).Return(nil).Times(1) - th.mv.EXPECT().CheckEligibility(gomock.Any(), gomock.Any()).DoAndReturn( - func(ctx context.Context, ballot *types.Ballot) (bool, error) { + th.mv.EXPECT().CheckEligibility(gomock.Any(), gomock.Any(), nil).DoAndReturn( + func(ctx context.Context, ballot *types.Ballot, _ []types.ATXID) (bool, error) { require.Equal(t, b.ID(), ballot.ID()) return false, errors.New("unknown") }) @@ -693,8 +682,8 @@ func TestBallot_NotEligible(t *testing.T) { th.mf.EXPECT().GetBallots(gomock.Any(), []types.BallotID{b.Votes.Base, b.RefBallot}).Return(nil).Times(1) th.md.EXPECT().GetMissingActiveSet(gomock.Any(), types.ATXIDList{b.AtxID}).Return(types.ATXIDList{b.AtxID}) th.mf.EXPECT().GetAtxs(gomock.Any(), types.ATXIDList{b.AtxID}).Return(nil).Times(1) - th.mv.EXPECT().CheckEligibility(gomock.Any(), gomock.Any()).DoAndReturn( - func(ctx context.Context, ballot *types.Ballot) (bool, error) { + th.mv.EXPECT().CheckEligibility(gomock.Any(), gomock.Any(), nil).DoAndReturn( + func(ctx context.Context, ballot *types.Ballot, _ []types.ATXID) (bool, error) { require.Equal(t, b.ID(), ballot.ID()) return false, nil }) @@ -723,8 +712,8 @@ func TestBallot_Success(t *testing.T) { th.mf.EXPECT().GetBallots(gomock.Any(), []types.BallotID{b.Votes.Base, b.RefBallot}).Return(nil).Times(1) th.md.EXPECT().GetMissingActiveSet(gomock.Any(), types.ATXIDList{b.AtxID}).Return(types.ATXIDList{b.AtxID}) th.mf.EXPECT().GetAtxs(gomock.Any(), types.ATXIDList{b.AtxID}).Return(nil).Times(1) - th.mv.EXPECT().CheckEligibility(gomock.Any(), gomock.Any()).DoAndReturn( - func(_ context.Context, ballot *types.Ballot) (bool, error) { + th.mv.EXPECT().CheckEligibility(gomock.Any(), gomock.Any(), nil).DoAndReturn( + func(_ context.Context, ballot *types.Ballot, _ []types.ATXID) (bool, error) { require.Equal(t, b.ID(), ballot.ID()) return true, nil }) @@ -757,8 +746,8 @@ func TestBallot_MaliciousProofIgnoredInSyncFlow(t *testing.T) { th.mf.EXPECT().GetBallots(gomock.Any(), []types.BallotID{b.Votes.Base, b.RefBallot}).Return(nil).Times(1) th.md.EXPECT().GetMissingActiveSet(gomock.Any(), types.ATXIDList{b.AtxID}).Return(types.ATXIDList{b.AtxID}) th.mf.EXPECT().GetAtxs(gomock.Any(), types.ATXIDList{b.AtxID}).Return(nil).Times(1) - th.mv.EXPECT().CheckEligibility(gomock.Any(), gomock.Any()).DoAndReturn( - func(_ context.Context, ballot *types.Ballot) (bool, error) { + th.mv.EXPECT().CheckEligibility(gomock.Any(), gomock.Any(), nil).DoAndReturn( + func(_ context.Context, ballot *types.Ballot, _ []types.ATXID) (bool, error) { require.Equal(t, b.ID(), ballot.ID()) return true, nil }) @@ -776,10 +765,11 @@ func TestBallot_RefBallot(t *testing.T) { types.NewExistingBlock(types.BlockID{1}, types.InnerBlock{LayerIndex: lid.Sub(1)}), types.NewExistingBlock(types.BlockID{2}, types.InnerBlock{LayerIndex: lid.Sub(2)}), } + activeSet := types.ATXIDList{{1}, {2}, {3}} b := createBallot(t, withLayer(lid), withSupportBlocks(supported...), - withAnyRefData(), + withRefData(activeSet), ) createAtx(t, th.cdb.Database, b.Layer.GetEpoch()-1, b.AtxID, b.SmesherID) for _, blk := range supported { @@ -790,21 +780,19 @@ func TestBallot_RefBallot(t *testing.T) { th.mf.EXPECT().GetBallots(gomock.Any(), []types.BallotID{b.Votes.Base}).Return(nil).Times(1) th.md.EXPECT().GetMissingActiveSet(b.Layer.GetEpoch(), []types.ATXID{b.AtxID}).Return([]types.ATXID{b.AtxID}) th.mf.EXPECT().GetAtxs(gomock.Any(), []types.ATXID{b.AtxID}) - th.mf.EXPECT().GetActiveSet(gomock.Any(), b.EpochData.ActiveSetHash).DoAndReturn(func(_ context.Context, hash types.Hash32) error { + th.mf.EXPECT().GetActiveSet(gomock.Any(), activeSet.Hash()).DoAndReturn(func(_ context.Context, hash types.Hash32) error { return activesets.Add(th.cdb, hash, &types.EpochActiveSet{ Epoch: b.Layer.GetEpoch(), - Set: b.ActiveSet, + Set: activeSet, }) }) - th.mv.EXPECT().CheckEligibility(gomock.Any(), gomock.Any()).DoAndReturn( - func(_ context.Context, ballot *types.Ballot) (bool, error) { + th.mv.EXPECT().CheckEligibility(gomock.Any(), gomock.Any(), activeSet).DoAndReturn( + func(_ context.Context, ballot *types.Ballot, _ []types.ATXID) (bool, error) { require.Equal(t, b.ID(), ballot.ID()) return true, nil }) th.mm.EXPECT().AddBallot(context.Background(), b).Return(nil, nil) - received := *b - received.ActiveSet = nil - require.NoError(t, th.HandleSyncedBallot(context.Background(), b.ID().AsHash32(), peer, codec.MustEncode(&received))) + require.NoError(t, th.HandleSyncedBallot(context.Background(), b.ID().AsHash32(), peer, codec.MustEncode(b))) } func TestBallot_DecodeBeforeVotesConsistency(t *testing.T) { @@ -845,7 +833,7 @@ func TestBallot_DecodedStoreFailure(t *testing.T) { th.mf.EXPECT().GetBallots(gomock.Any(), []types.BallotID{b.Votes.Base, b.RefBallot}).Return(nil).Times(1) th.md.EXPECT().GetMissingActiveSet(gomock.Any(), types.ATXIDList{b.AtxID}).Return(types.ATXIDList{b.AtxID}) th.mf.EXPECT().GetAtxs(gomock.Any(), types.ATXIDList{b.AtxID}).Return(nil).Times(1) - th.mv.EXPECT().CheckEligibility(gomock.Any(), gomock.Any()).Return(true, nil).Times(1) + th.mv.EXPECT().CheckEligibility(gomock.Any(), gomock.Any(), nil).Return(true, nil).Times(1) decoded := &tortoise.DecodedBallot{BallotTortoiseData: b.ToTortoiseData()} th.md.EXPECT().DecodeBallot(decoded.BallotTortoiseData).Return(decoded, nil) @@ -876,6 +864,20 @@ func TestProposal_BeforeEffectiveGenesis(t *testing.T) { checkProposal(t, th.cdb, p, false) } +func TestProposal_TooOld(t *testing.T) { + th := createTestHandlerNoopDecoder(t) + lid := types.LayerID(11) + th.mockSet.setCurrentLayer(lid) + p := createProposal(t) + p.Layer = lid - 1 + data := encodeProposal(t, p) + got := th.HandleSyncedProposal(context.Background(), p.ID().AsHash32(), p2p.NoPeer, data) + require.ErrorContains(t, got, "proposal too late") + + require.Error(t, th.HandleProposal(context.Background(), "", data)) + checkProposal(t, th.cdb, p, false) +} + func TestProposal_BadSignature(t *testing.T) { th := createTestHandlerNoopDecoder(t) p := createProposal(t) @@ -896,6 +898,7 @@ func TestProposal_InconsistentSmeshers(t *testing.T) { TxIDs: []types.TransactionID{types.RandomTransactionID(), types.RandomTransactionID()}, }, } + p.Layer = th.clock.CurrentLayer() signer1, err := signing.NewEdSigner() require.NoError(t, err) signer2, err := signing.NewEdSigner() @@ -936,7 +939,7 @@ func TestProposal_KnownProposal(t *testing.T) { func TestProposal_DuplicateTXs(t *testing.T) { th := createTestHandlerNoopDecoder(t) - lid := types.LayerID(100) + lid := th.clock.CurrentLayer() supported := []*types.Block{ types.NewExistingBlock(types.BlockID{1}, types.InnerBlock{LayerIndex: lid.Sub(1)}), types.NewExistingBlock(types.BlockID{2}, types.InnerBlock{LayerIndex: lid.Sub(2)}), @@ -955,8 +958,8 @@ func TestProposal_DuplicateTXs(t *testing.T) { th.mf.EXPECT().GetBallots(gomock.Any(), []types.BallotID{p.Votes.Base, p.RefBallot}).Return(nil).Times(1) th.md.EXPECT().GetMissingActiveSet(gomock.Any(), types.ATXIDList{p.AtxID}).Return(types.ATXIDList{p.AtxID}) th.mf.EXPECT().GetAtxs(gomock.Any(), types.ATXIDList{p.AtxID}).Return(nil).Times(1) - th.mv.EXPECT().CheckEligibility(gomock.Any(), gomock.Any()).DoAndReturn( - func(ctx context.Context, ballot *types.Ballot) (bool, error) { + th.mv.EXPECT().CheckEligibility(gomock.Any(), gomock.Any(), nil).DoAndReturn( + func(ctx context.Context, ballot *types.Ballot, _ []types.ATXID) (bool, error) { require.Equal(t, p.Ballot.ID(), ballot.ID()) return true, nil }) @@ -973,7 +976,7 @@ func TestProposal_DuplicateTXs(t *testing.T) { func TestProposal_TXsNotAvailable(t *testing.T) { th := createTestHandlerNoopDecoder(t) - lid := types.LayerID(100) + lid := th.clock.CurrentLayer() supported := []*types.Block{ types.NewExistingBlock(types.BlockID{1}, types.InnerBlock{LayerIndex: lid.Sub(1)}), types.NewExistingBlock(types.BlockID{2}, types.InnerBlock{LayerIndex: lid.Sub(2)}), @@ -990,8 +993,8 @@ func TestProposal_TXsNotAvailable(t *testing.T) { th.mf.EXPECT().GetBallots(gomock.Any(), []types.BallotID{p.Votes.Base, p.RefBallot}).Return(nil).Times(1) th.md.EXPECT().GetMissingActiveSet(gomock.Any(), types.ATXIDList{p.AtxID}).Return(types.ATXIDList{p.AtxID}) th.mf.EXPECT().GetAtxs(gomock.Any(), types.ATXIDList{p.AtxID}).Return(nil).Times(1) - th.mv.EXPECT().CheckEligibility(gomock.Any(), gomock.Any()).DoAndReturn( - func(ctx context.Context, ballot *types.Ballot) (bool, error) { + th.mv.EXPECT().CheckEligibility(gomock.Any(), gomock.Any(), nil).DoAndReturn( + func(ctx context.Context, ballot *types.Ballot, _ []types.ATXID) (bool, error) { require.Equal(t, p.Ballot.ID(), ballot.ID()) return true, nil }) @@ -1011,7 +1014,7 @@ func TestProposal_TXsNotAvailable(t *testing.T) { func TestProposal_FailedToAddProposalTXs(t *testing.T) { th := createTestHandlerNoopDecoder(t) - lid := types.LayerID(100) + lid := th.clock.CurrentLayer() supported := []*types.Block{ types.NewExistingBlock(types.BlockID{1}, types.InnerBlock{LayerIndex: lid.Sub(1)}), types.NewExistingBlock(types.BlockID{2}, types.InnerBlock{LayerIndex: lid.Sub(2)}), @@ -1028,8 +1031,8 @@ func TestProposal_FailedToAddProposalTXs(t *testing.T) { th.mf.EXPECT().GetBallots(gomock.Any(), []types.BallotID{p.Votes.Base, p.RefBallot}).Return(nil).Times(1) th.md.EXPECT().GetMissingActiveSet(gomock.Any(), types.ATXIDList{p.AtxID}).Return(types.ATXIDList{p.AtxID}) th.mf.EXPECT().GetAtxs(gomock.Any(), types.ATXIDList{p.AtxID}).Return(nil).Times(1) - th.mv.EXPECT().CheckEligibility(gomock.Any(), gomock.Any()).DoAndReturn( - func(ctx context.Context, ballot *types.Ballot) (bool, error) { + th.mv.EXPECT().CheckEligibility(gomock.Any(), gomock.Any(), nil).DoAndReturn( + func(ctx context.Context, ballot *types.Ballot, _ []types.ATXID) (bool, error) { require.Equal(t, p.Ballot.ID(), ballot.ID()) return true, nil }) @@ -1049,7 +1052,7 @@ func TestProposal_FailedToAddProposalTXs(t *testing.T) { func TestProposal_ProposalGossip_Concurrent(t *testing.T) { th := createTestHandlerNoopDecoder(t) - lid := types.LayerID(100) + lid := th.clock.CurrentLayer() supported := []*types.Block{ types.NewExistingBlock(types.BlockID{1}, types.InnerBlock{LayerIndex: lid.Sub(1)}), types.NewExistingBlock(types.BlockID{2}, types.InnerBlock{LayerIndex: lid.Sub(2)}), @@ -1069,8 +1072,8 @@ func TestProposal_ProposalGossip_Concurrent(t *testing.T) { th.mf.EXPECT().GetBallots(gomock.Any(), []types.BallotID{p.Votes.Base, p.RefBallot}).Return(nil).MinTimes(1).MaxTimes(2) th.md.EXPECT().GetMissingActiveSet(gomock.Any(), types.ATXIDList{p.AtxID}).Return(types.ATXIDList{p.AtxID}).MinTimes(1).MaxTimes(2) th.mf.EXPECT().GetAtxs(gomock.Any(), types.ATXIDList{p.AtxID}).Return(nil).MinTimes(1).MaxTimes(2) - th.mv.EXPECT().CheckEligibility(gomock.Any(), gomock.Any()).DoAndReturn( - func(ctx context.Context, ballot *types.Ballot) (bool, error) { + th.mv.EXPECT().CheckEligibility(gomock.Any(), gomock.Any(), nil).DoAndReturn( + func(ctx context.Context, ballot *types.Ballot, _ []types.ATXID) (bool, error) { require.Equal(t, p.Ballot.ID(), ballot.ID()) return true, nil }).MinTimes(1).MaxTimes(2) @@ -1105,7 +1108,7 @@ func TestProposal_ProposalGossip_Concurrent(t *testing.T) { func TestProposal_BroadcastMaliciousGossip(t *testing.T) { th := createTestHandlerNoopDecoder(t) - lid := types.LayerID(100) + lid := th.clock.CurrentLayer() p := createProposal(t, withLayer(lid)) createAtx(t, th.cdb.Database, p.Layer.GetEpoch()-1, p.AtxID, p.SmesherID) require.NoError(t, ballots.Add(th.cdb, &p.Ballot)) @@ -1129,8 +1132,8 @@ func TestProposal_BroadcastMaliciousGossip(t *testing.T) { th.mf.EXPECT().GetBallots(gomock.Any(), []types.BallotID{pMal.Votes.Base, pMal.RefBallot}) th.md.EXPECT().GetMissingActiveSet(gomock.Any(), types.ATXIDList{pMal.AtxID}).Return(types.ATXIDList{pMal.AtxID}) th.mf.EXPECT().GetAtxs(gomock.Any(), types.ATXIDList{pMal.AtxID}) - th.mv.EXPECT().CheckEligibility(gomock.Any(), gomock.Any()).DoAndReturn( - func(ctx context.Context, ballot *types.Ballot) (bool, error) { + th.mv.EXPECT().CheckEligibility(gomock.Any(), gomock.Any(), nil).DoAndReturn( + func(ctx context.Context, ballot *types.Ballot, _ []types.ATXID) (bool, error) { require.Equal(t, pMal.Ballot.ID(), ballot.ID()) return true, nil }) @@ -1183,7 +1186,7 @@ func TestProposal_ProposalGossip_Fetched(t *testing.T) { tc := tc t.Run(tc.name, func(t *testing.T) { th := createTestHandlerNoopDecoder(t) - lid := types.LayerID(100) + lid := th.clock.CurrentLayer() supported := []*types.Block{ types.NewExistingBlock(types.BlockID{1}, types.InnerBlock{LayerIndex: lid.Sub(1)}), types.NewExistingBlock(types.BlockID{2}, types.InnerBlock{LayerIndex: lid.Sub(2)}), @@ -1203,8 +1206,8 @@ func TestProposal_ProposalGossip_Fetched(t *testing.T) { th.mf.EXPECT().GetBallots(gomock.Any(), []types.BallotID{p.Votes.Base, p.RefBallot}).Return(nil) th.md.EXPECT().GetMissingActiveSet(gomock.Any(), types.ATXIDList{p.AtxID}).Return(types.ATXIDList{p.AtxID}) th.mf.EXPECT().GetAtxs(gomock.Any(), types.ATXIDList{p.AtxID}).Return(nil) - th.mv.EXPECT().CheckEligibility(gomock.Any(), gomock.Any()).DoAndReturn( - func(ctx context.Context, ballot *types.Ballot) (bool, error) { + th.mv.EXPECT().CheckEligibility(gomock.Any(), gomock.Any(), nil).DoAndReturn( + func(ctx context.Context, ballot *types.Ballot, _ []types.ATXID) (bool, error) { require.Equal(t, p.Ballot.ID(), ballot.ID()) if tc.propFetched { // a separate goroutine fetched the propFetched and saved it to database @@ -1231,7 +1234,7 @@ func TestProposal_ProposalGossip_Fetched(t *testing.T) { func TestProposal_ValidProposal(t *testing.T) { th := createTestHandlerNoopDecoder(t) - lid := types.LayerID(10) + lid := th.clock.CurrentLayer() blks := []*types.Block{ types.NewExistingBlock(types.BlockID{1}, types.InnerBlock{LayerIndex: lid.Sub(1)}), types.NewExistingBlock(types.BlockID{2}, types.InnerBlock{LayerIndex: lid.Sub(2)}), @@ -1248,8 +1251,8 @@ func TestProposal_ValidProposal(t *testing.T) { th.mf.EXPECT().GetBallots(gomock.Any(), []types.BallotID{p.Votes.Base, p.RefBallot}).Return(nil).Times(1) th.md.EXPECT().GetMissingActiveSet(gomock.Any(), types.ATXIDList{p.AtxID}).Return(types.ATXIDList{p.AtxID}) th.mf.EXPECT().GetAtxs(gomock.Any(), types.ATXIDList{p.AtxID}).Return(nil).Times(1) - th.mv.EXPECT().CheckEligibility(gomock.Any(), gomock.Any()).DoAndReturn( - func(ctx context.Context, ballot *types.Ballot) (bool, error) { + th.mv.EXPECT().CheckEligibility(gomock.Any(), gomock.Any(), nil).DoAndReturn( + func(ctx context.Context, ballot *types.Ballot, _ []types.ATXID) (bool, error) { require.Equal(t, p.Ballot.ID(), ballot.ID()) return true, nil }) @@ -1268,7 +1271,7 @@ func TestProposal_ValidProposal(t *testing.T) { func TestMetrics(t *testing.T) { th := createTestHandlerNoopDecoder(t) - lid := types.LayerID(100) + lid := th.clock.CurrentLayer() supported := []*types.Block{ types.NewExistingBlock(types.BlockID{1}, types.InnerBlock{LayerIndex: lid.Sub(1)}), types.NewExistingBlock(types.BlockID{2}, types.InnerBlock{LayerIndex: lid.Sub(2)}), @@ -1285,8 +1288,8 @@ func TestMetrics(t *testing.T) { th.mf.EXPECT().GetBallots(gomock.Any(), []types.BallotID{p.Votes.Base, p.RefBallot}).Return(nil).Times(1) th.md.EXPECT().GetMissingActiveSet(gomock.Any(), types.ATXIDList{p.AtxID}).Return(types.ATXIDList{p.AtxID}) th.mf.EXPECT().GetAtxs(gomock.Any(), types.ATXIDList{p.AtxID}).Return(nil).Times(1) - th.mv.EXPECT().CheckEligibility(gomock.Any(), gomock.Any()).DoAndReturn( - func(ctx context.Context, ballot *types.Ballot) (bool, error) { + th.mv.EXPECT().CheckEligibility(gomock.Any(), gomock.Any(), nil).DoAndReturn( + func(ctx context.Context, ballot *types.Ballot, _ []types.ATXID) (bool, error) { require.Equal(t, p.Ballot.ID(), ballot.ID()) return true, nil }) @@ -1399,13 +1402,12 @@ func TestHandleActiveSet(t *testing.T) { } } -func gproposal(signer *signing.EdSigner, atxid types.ATXID, activeset []types.ATXID, +func gproposal(signer *signing.EdSigner, atxid types.ATXID, layer types.LayerID, edata *types.EpochData, ) types.Proposal { p := types.Proposal{} p.Layer = layer p.AtxID = atxid - p.ActiveSet = activeset p.EpochData = edata p.Ballot.Signature = signer.Sign(signing.BALLOT, p.Ballot.SignedBytes()) p.Ballot.SmesherID = signer.NodeID() @@ -1418,84 +1420,35 @@ func TestHandleSyncedProposalActiveSet(t *testing.T) { signer, err := signing.NewEdSigner() require.NoError(t, err) - set := []types.ATXID{{1}, {2}} - const acceptEmpty = 20 - good := gproposal(signer, types.ATXID{1}, set, acceptEmpty-1, &types.EpochData{ - ActiveSetHash: types.ATXIDList(set).Hash(), + set := types.ATXIDList{{1}, {2}} + lid := types.LayerID(20) + good := gproposal(signer, types.ATXID{1}, lid, &types.EpochData{ + ActiveSetHash: set.Hash(), Beacon: types.Beacon{1}, }) require.NoError(t, good.Initialize()) - - woActive := good - woActive.ActiveSet = nil - - notSigned := gproposal(signer, types.ATXID{1}, nil, acceptEmpty, &types.EpochData{ - ActiveSetHash: types.ATXIDList(set).Hash(), - Beacon: types.Beacon{1}, - }) - require.NoError(t, notSigned.Initialize()) - notSigned.ActiveSet = set - - notSignedEmpty := notSigned - notSignedEmpty.ActiveSet = nil - for _, tc := range []struct { - desc string - data []byte - id types.Hash32 - requestSet []types.ATXID - err string - }{ - { - desc: "before empty signed active set", - data: codec.MustEncode(&good), - id: good.ID().AsHash32(), - }, - { - desc: "before empty without active set", - data: codec.MustEncode(&woActive), - id: woActive.ID().AsHash32(), - err: "failed to verify proposal signature", - }, - { - desc: "after empty not signed active set", - data: codec.MustEncode(¬Signed), - id: notSigned.ID().AsHash32(), - }, - { - desc: "after empty not signed active set empty", - data: codec.MustEncode(¬SignedEmpty), - id: notSigned.ID().AsHash32(), - requestSet: set, + th := createTestHandler(t) + pid := p2p.Peer("any") + + th.mm.EXPECT().ProcessedLayer().Return(lid - 2).AnyTimes() + th.mclock.EXPECT().LayerToTime(gomock.Any()) + th.mf.EXPECT().RegisterPeerHashes(pid, gomock.Any()).AnyTimes() + th.md.EXPECT().GetMissingActiveSet(gomock.Any(), gomock.Any()).AnyTimes() + th.mf.EXPECT().GetActiveSet(gomock.Any(), set.Hash()).DoAndReturn( + func(_ context.Context, got types.Hash32) error { + require.NoError(t, activesets.Add(th.cdb, got, &types.EpochActiveSet{ + Set: set, + })) + return nil }, - } { - t.Run(tc.desc, func(t *testing.T) { - th := createTestHandler(t) - th.cfg.AllowEmptyActiveSet = acceptEmpty - pid := p2p.Peer("any") + ) + th.mf.EXPECT().GetAtxs(gomock.Any(), gomock.Any()).AnyTimes() + th.mf.EXPECT().GetBallots(gomock.Any(), gomock.Any()).AnyTimes() + th.mockSet.decodeAnyBallots() + th.mv.EXPECT().CheckEligibility(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(true, nil) + th.mm.EXPECT().AddBallot(gomock.Any(), gomock.Any()).AnyTimes() + th.mm.EXPECT().AddTXsFromProposal(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() - th.mclock.EXPECT().LayerToTime(gomock.Any()) - th.mf.EXPECT().RegisterPeerHashes(pid, gomock.Any()).AnyTimes() - th.md.EXPECT().GetMissingActiveSet(gomock.Any(), gomock.Any()).AnyTimes() - if tc.requestSet != nil { - id := types.ATXIDList(tc.requestSet).Hash() - th.mf.EXPECT().GetActiveSet(gomock.Any(), id) - require.NoError(t, activesets.Add(th.cdb, id, &types.EpochActiveSet{ - Set: tc.requestSet, - })) - } - th.mf.EXPECT().GetAtxs(gomock.Any(), gomock.Any()).AnyTimes() - th.mf.EXPECT().GetBallots(gomock.Any(), gomock.Any()).AnyTimes() - th.mockSet.decodeAnyBallots() - th.mv.EXPECT().CheckEligibility(gomock.Any(), gomock.Any()).AnyTimes().Return(true, nil) - th.mm.EXPECT().AddBallot(gomock.Any(), gomock.Any()).AnyTimes() - th.mm.EXPECT().AddTXsFromProposal(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() - - err := th.HandleSyncedProposal(context.Background(), tc.id, pid, tc.data) - if len(tc.err) > 0 { - require.ErrorContains(t, err, tc.err) - } else { - require.NoError(t, err) - } - }) - } + err = th.HandleSyncedProposal(context.Background(), good.ID().AsHash32(), pid, codec.MustEncode(&good)) + require.NoError(t, err) } diff --git a/proposals/interface.go b/proposals/interface.go index ff6d43f74d..2b33cd3a3c 100644 --- a/proposals/interface.go +++ b/proposals/interface.go @@ -11,12 +11,13 @@ import ( //go:generate mockgen -typed -package=proposals -destination=./mocks.go -source=./interface.go type meshProvider interface { + ProcessedLayer() types.LayerID AddBallot(context.Context, *types.Ballot) (*types.MalfeasanceProof, error) AddTXsFromProposal(context.Context, types.LayerID, types.ProposalID, []types.TransactionID) error } type eligibilityValidator interface { - CheckEligibility(context.Context, *types.Ballot) (bool, error) + CheckEligibility(context.Context, *types.Ballot, []types.ATXID) (bool, error) } type tortoiseProvider interface { diff --git a/proposals/metrics.go b/proposals/metrics.go index dc56913e15..006fee1977 100644 --- a/proposals/metrics.go +++ b/proposals/metrics.go @@ -93,6 +93,7 @@ var ( malformed = processErrors.WithLabelValues("mal") failedInit = processErrors.WithLabelValues("init") known = processErrors.WithLabelValues("known") + tooLate = processErrors.WithLabelValues("late") preGenesis = processErrors.WithLabelValues("genesis") badSigProposal = processErrors.WithLabelValues("sigp") badSigBallot = processErrors.WithLabelValues("sigb") diff --git a/proposals/mocks.go b/proposals/mocks.go index 696425c6d0..4c7918c393 100644 --- a/proposals/mocks.go +++ b/proposals/mocks.go @@ -1,6 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: ./interface.go - +// +// Generated by this command: +// +// mockgen -typed -package=proposals -destination=./mocks.go -source=./interface.go +// // Package proposals is a generated GoMock package. package proposals @@ -47,7 +51,7 @@ func (m *MockmeshProvider) AddBallot(arg0 context.Context, arg1 *types.Ballot) ( } // AddBallot indicates an expected call of AddBallot. -func (mr *MockmeshProviderMockRecorder) AddBallot(arg0, arg1 interface{}) *meshProviderAddBallotCall { +func (mr *MockmeshProviderMockRecorder) AddBallot(arg0, arg1 any) *meshProviderAddBallotCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddBallot", reflect.TypeOf((*MockmeshProvider)(nil).AddBallot), arg0, arg1) return &meshProviderAddBallotCall{Call: call} @@ -85,7 +89,7 @@ func (m *MockmeshProvider) AddTXsFromProposal(arg0 context.Context, arg1 types.L } // AddTXsFromProposal indicates an expected call of AddTXsFromProposal. -func (mr *MockmeshProviderMockRecorder) AddTXsFromProposal(arg0, arg1, arg2, arg3 interface{}) *meshProviderAddTXsFromProposalCall { +func (mr *MockmeshProviderMockRecorder) AddTXsFromProposal(arg0, arg1, arg2, arg3 any) *meshProviderAddTXsFromProposalCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddTXsFromProposal", reflect.TypeOf((*MockmeshProvider)(nil).AddTXsFromProposal), arg0, arg1, arg2, arg3) return &meshProviderAddTXsFromProposalCall{Call: call} @@ -114,6 +118,44 @@ func (c *meshProviderAddTXsFromProposalCall) DoAndReturn(f func(context.Context, return c } +// ProcessedLayer mocks base method. +func (m *MockmeshProvider) ProcessedLayer() types.LayerID { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ProcessedLayer") + ret0, _ := ret[0].(types.LayerID) + return ret0 +} + +// ProcessedLayer indicates an expected call of ProcessedLayer. +func (mr *MockmeshProviderMockRecorder) ProcessedLayer() *meshProviderProcessedLayerCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProcessedLayer", reflect.TypeOf((*MockmeshProvider)(nil).ProcessedLayer)) + return &meshProviderProcessedLayerCall{Call: call} +} + +// meshProviderProcessedLayerCall wrap *gomock.Call +type meshProviderProcessedLayerCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *meshProviderProcessedLayerCall) Return(arg0 types.LayerID) *meshProviderProcessedLayerCall { + c.Call = c.Call.Return(arg0) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *meshProviderProcessedLayerCall) Do(f func() types.LayerID) *meshProviderProcessedLayerCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *meshProviderProcessedLayerCall) DoAndReturn(f func() types.LayerID) *meshProviderProcessedLayerCall { + c.Call = c.Call.DoAndReturn(f) + return c +} + // MockeligibilityValidator is a mock of eligibilityValidator interface. type MockeligibilityValidator struct { ctrl *gomock.Controller @@ -138,18 +180,18 @@ func (m *MockeligibilityValidator) EXPECT() *MockeligibilityValidatorMockRecorde } // CheckEligibility mocks base method. -func (m *MockeligibilityValidator) CheckEligibility(arg0 context.Context, arg1 *types.Ballot) (bool, error) { +func (m *MockeligibilityValidator) CheckEligibility(arg0 context.Context, arg1 *types.Ballot, arg2 []types.ATXID) (bool, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CheckEligibility", arg0, arg1) + ret := m.ctrl.Call(m, "CheckEligibility", arg0, arg1, arg2) ret0, _ := ret[0].(bool) ret1, _ := ret[1].(error) return ret0, ret1 } // CheckEligibility indicates an expected call of CheckEligibility. -func (mr *MockeligibilityValidatorMockRecorder) CheckEligibility(arg0, arg1 interface{}) *eligibilityValidatorCheckEligibilityCall { +func (mr *MockeligibilityValidatorMockRecorder) CheckEligibility(arg0, arg1, arg2 any) *eligibilityValidatorCheckEligibilityCall { mr.mock.ctrl.T.Helper() - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckEligibility", reflect.TypeOf((*MockeligibilityValidator)(nil).CheckEligibility), arg0, arg1) + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckEligibility", reflect.TypeOf((*MockeligibilityValidator)(nil).CheckEligibility), arg0, arg1, arg2) return &eligibilityValidatorCheckEligibilityCall{Call: call} } @@ -165,13 +207,13 @@ func (c *eligibilityValidatorCheckEligibilityCall) Return(arg0 bool, arg1 error) } // Do rewrite *gomock.Call.Do -func (c *eligibilityValidatorCheckEligibilityCall) Do(f func(context.Context, *types.Ballot) (bool, error)) *eligibilityValidatorCheckEligibilityCall { +func (c *eligibilityValidatorCheckEligibilityCall) Do(f func(context.Context, *types.Ballot, []types.ATXID) (bool, error)) *eligibilityValidatorCheckEligibilityCall { c.Call = c.Call.Do(f) return c } // DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *eligibilityValidatorCheckEligibilityCall) DoAndReturn(f func(context.Context, *types.Ballot) (bool, error)) *eligibilityValidatorCheckEligibilityCall { +func (c *eligibilityValidatorCheckEligibilityCall) DoAndReturn(f func(context.Context, *types.Ballot, []types.ATXID) (bool, error)) *eligibilityValidatorCheckEligibilityCall { c.Call = c.Call.DoAndReturn(f) return c } @@ -209,7 +251,7 @@ func (m *MocktortoiseProvider) DecodeBallot(arg0 *types.BallotTortoiseData) (*to } // DecodeBallot indicates an expected call of DecodeBallot. -func (mr *MocktortoiseProviderMockRecorder) DecodeBallot(arg0 interface{}) *tortoiseProviderDecodeBallotCall { +func (mr *MocktortoiseProviderMockRecorder) DecodeBallot(arg0 any) *tortoiseProviderDecodeBallotCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DecodeBallot", reflect.TypeOf((*MocktortoiseProvider)(nil).DecodeBallot), arg0) return &tortoiseProviderDecodeBallotCall{Call: call} @@ -247,7 +289,7 @@ func (m *MocktortoiseProvider) GetBallot(arg0 types.BallotID) *tortoise.BallotDa } // GetBallot indicates an expected call of GetBallot. -func (mr *MocktortoiseProviderMockRecorder) GetBallot(arg0 interface{}) *tortoiseProviderGetBallotCall { +func (mr *MocktortoiseProviderMockRecorder) GetBallot(arg0 any) *tortoiseProviderGetBallotCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBallot", reflect.TypeOf((*MocktortoiseProvider)(nil).GetBallot), arg0) return &tortoiseProviderGetBallotCall{Call: call} @@ -285,7 +327,7 @@ func (m *MocktortoiseProvider) GetMissingActiveSet(arg0 types.EpochID, arg1 []ty } // GetMissingActiveSet indicates an expected call of GetMissingActiveSet. -func (mr *MocktortoiseProviderMockRecorder) GetMissingActiveSet(arg0, arg1 interface{}) *tortoiseProviderGetMissingActiveSetCall { +func (mr *MocktortoiseProviderMockRecorder) GetMissingActiveSet(arg0, arg1 any) *tortoiseProviderGetMissingActiveSetCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMissingActiveSet", reflect.TypeOf((*MocktortoiseProvider)(nil).GetMissingActiveSet), arg0, arg1) return &tortoiseProviderGetMissingActiveSetCall{Call: call} @@ -323,7 +365,7 @@ func (m *MocktortoiseProvider) StoreBallot(arg0 *tortoise.DecodedBallot) error { } // StoreBallot indicates an expected call of StoreBallot. -func (mr *MocktortoiseProviderMockRecorder) StoreBallot(arg0 interface{}) *tortoiseProviderStoreBallotCall { +func (mr *MocktortoiseProviderMockRecorder) StoreBallot(arg0 any) *tortoiseProviderStoreBallotCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StoreBallot", reflect.TypeOf((*MocktortoiseProvider)(nil).StoreBallot), arg0) return &tortoiseProviderStoreBallotCall{Call: call} @@ -384,7 +426,7 @@ func (m *MockvrfVerifier) Verify(arg0 types.NodeID, arg1 []byte, arg2 types.VrfS } // Verify indicates an expected call of Verify. -func (mr *MockvrfVerifierMockRecorder) Verify(arg0, arg1, arg2 interface{}) *vrfVerifierVerifyCall { +func (mr *MockvrfVerifierMockRecorder) Verify(arg0, arg1, arg2 any) *vrfVerifierVerifyCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Verify", reflect.TypeOf((*MockvrfVerifier)(nil).Verify), arg0, arg1, arg2) return &vrfVerifierVerifyCall{Call: call} @@ -446,7 +488,7 @@ func (m *MocknonceFetcher) VRFNonce(arg0 types.NodeID, arg1 types.EpochID) (type } // VRFNonce indicates an expected call of VRFNonce. -func (mr *MocknonceFetcherMockRecorder) VRFNonce(arg0, arg1 interface{}) *nonceFetcherVRFNonceCall { +func (mr *MocknonceFetcherMockRecorder) VRFNonce(arg0, arg1 any) *nonceFetcherVRFNonceCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "VRFNonce", reflect.TypeOf((*MocknonceFetcher)(nil).VRFNonce), arg0, arg1) return &nonceFetcherVRFNonceCall{Call: call} @@ -545,7 +587,7 @@ func (m *MocklayerClock) LayerToTime(arg0 types.LayerID) time.Time { } // LayerToTime indicates an expected call of LayerToTime. -func (mr *MocklayerClockMockRecorder) LayerToTime(arg0 interface{}) *layerClockLayerToTimeCall { +func (mr *MocklayerClockMockRecorder) LayerToTime(arg0 any) *layerClockLayerToTimeCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LayerToTime", reflect.TypeOf((*MocklayerClock)(nil).LayerToTime), arg0) return &layerClockLayerToTimeCall{Call: call} diff --git a/proposals/util.go b/proposals/util.go index f4ea8ef49e..ca5e70c431 100644 --- a/proposals/util.go +++ b/proposals/util.go @@ -9,9 +9,8 @@ import ( ) var ( - CalcEligibleLayer = util.CalcEligibleLayer - GetNumEligibleSlots = util.GetNumEligibleSlots - GetLegacyNumEligible = util.GetLegacyNumEligible + CalcEligibleLayer = util.CalcEligibleLayer + GetNumEligibleSlots = util.GetNumEligibleSlots // ComputeWeightPerEligibility computes the ballot weight per eligibility w.r.t the active set recorded in its reference ballot. ComputeWeightPerEligibility = util.ComputeWeightPerEligibility ) diff --git a/proposals/util/util.go b/proposals/util/util.go index bcd0f90a40..55d5405f69 100644 --- a/proposals/util/util.go +++ b/proposals/util/util.go @@ -8,6 +8,7 @@ import ( "github.com/spacemeshos/go-spacemesh/common/types" "github.com/spacemeshos/go-spacemesh/datastore" + "github.com/spacemeshos/go-spacemesh/sql/activesets" "github.com/spacemeshos/go-spacemesh/sql/ballots" ) @@ -29,14 +30,6 @@ func CalcEligibleLayer(epochNumber types.EpochID, layersPerEpoch uint32, vrfSig return epochNumber.FirstLayer().Add(uint32(eligibleLayerOffset)) } -func GetLegacyNumEligible(lid types.LayerID, weight, minWeight, totalWeight uint64, committeeSize, layersPerEpoch uint32) (uint32, error) { - legacyLayer := types.GetLegacyLayer() - if legacyLayer != 0 && legacyLayer >= lid.Uint32() { - return 1, nil - } - return GetNumEligibleSlots(weight, minWeight, totalWeight, committeeSize, layersPerEpoch) -} - // GetNumEligibleSlots calculates the number of eligible slots for a smesher in an epoch. func GetNumEligibleSlots(weight, minWeight, totalWeight uint64, committeeSize, layersPerEpoch uint32) (uint32, error) { if totalWeight == 0 { @@ -69,16 +62,20 @@ func ComputeWeightPerEligibility( return nil, fmt.Errorf("%w: missing ref ballot %s (for %s)", err, ballot.RefBallot, ballot.ID()) } } - if len(refBallot.ActiveSet) == 0 { - return nil, fmt.Errorf("ref ballot missing active set %s (for %s)", ballot.RefBallot, ballot.ID()) - } if refBallot.EpochData == nil { return nil, fmt.Errorf("epoch data is nil on ballot %d/%s", refBallot.Layer, refBallot.ID()) } if refBallot.EpochData.EligibilityCount == 0 { return nil, fmt.Errorf("eligibility count is 0 on ballot %d/%s", refBallot.Layer, refBallot.ID()) } - for _, atxID := range refBallot.ActiveSet { + actives, err := activesets.Get(cdb, refBallot.EpochData.ActiveSetHash) + if err != nil { + return nil, fmt.Errorf("get active set %s (%s)", refBallot.EpochData.ActiveSetHash.ShortString(), refBallot.ID()) + } + if len(actives.Set) == 0 { + return nil, fmt.Errorf("empty active set %s (%s)", refBallot.EpochData.ActiveSetHash.ShortString(), refBallot.ID()) + } + for _, atxID := range actives.Set { hdr, err = cdb.GetAtxHeader(atxID) if err != nil { return nil, fmt.Errorf("%w: missing atx %s in active set of %s (for %s)", err, atxID, refBallot.ID(), ballot.ID()) diff --git a/proposals/util/util_test.go b/proposals/util/util_test.go deleted file mode 100644 index 2528cd1cfb..0000000000 --- a/proposals/util/util_test.go +++ /dev/null @@ -1,22 +0,0 @@ -package util - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/spacemeshos/go-spacemesh/common/types" -) - -func TestNumEligible(t *testing.T) { - types.SetLegacyLayers(10) - n, err := GetLegacyNumEligible(11, 100, 0, 1000, 4032, 50) - require.NoError(t, err) - require.Equal(t, 20160, int(n)) - n, err = GetLegacyNumEligible(types.LayerID(types.GetLegacyLayer()), 100, 0, 1000, 4032, 50) - require.NoError(t, err) - require.Equal(t, 1, int(n)) - n, err = GetLegacyNumEligible(0, 100, 0, 1000, 4032, 50) - require.NoError(t, err) - require.Equal(t, 1, int(n)) -} diff --git a/proposals/util_test.go b/proposals/util_test.go index 16916b96fb..196dc28620 100644 --- a/proposals/util_test.go +++ b/proposals/util_test.go @@ -16,6 +16,7 @@ import ( putil "github.com/spacemeshos/go-spacemesh/proposals/util" "github.com/spacemeshos/go-spacemesh/signing" "github.com/spacemeshos/go-spacemesh/sql" + "github.com/spacemeshos/go-spacemesh/sql/activesets" "github.com/spacemeshos/go-spacemesh/sql/atxs" "github.com/spacemeshos/go-spacemesh/sql/ballots" ) @@ -72,7 +73,6 @@ func createBallots(tb testing.TB, signer *signing.EdSigner, activeSet types.ATXI Beacon: beacon, EligibilityCount: eligibleSlots, } - b.ActiveSet = activeSet } else { b.RefBallot = blts[0].ID() } @@ -90,12 +90,14 @@ func TestComputeWeightPerEligibility(t *testing.T) { signing.WithKeyFromRand(rand.New(rand.NewSource(1001))), ) require.NoError(t, err) + cdb := datastore.NewCachedDB(sql.InMemory(), logtest.New(t)) beacon := types.Beacon{1, 1, 1} - blts := createBallots(t, signer, genActiveSet(), beacon) + actives := genActiveSet() + blts := createBallots(t, signer, actives, beacon) rb := blts[0] - cdb := datastore.NewCachedDB(sql.InMemory(), logtest.New(t)) + activesets.Add(cdb, rb.EpochData.ActiveSetHash, &types.EpochActiveSet{Set: actives}) require.NoError(t, ballots.Add(cdb, rb)) - for _, id := range rb.ActiveSet { + for _, id := range actives { atx := &types.ActivationTx{InnerActivationTx: types.InnerActivationTx{ NIPostChallenge: types.NIPostChallenge{ PublishEpoch: epoch - 1, @@ -158,9 +160,12 @@ func TestComputeWeightPerEligibility_FailATX(t *testing.T) { ) require.NoError(t, err) beacon := types.Beacon{1, 1, 1} - blts := createBallots(t, signer, genActiveSet(), beacon) cdb := datastore.NewCachedDB(sql.InMemory(), logtest.New(t)) - got, err := ComputeWeightPerEligibility(cdb, blts[0]) + actives := genActiveSet() + blts := createBallots(t, signer, actives, beacon) + rb := blts[0] + activesets.Add(cdb, rb.EpochData.ActiveSetHash, &types.EpochActiveSet{Set: actives}) + got, err := ComputeWeightPerEligibility(cdb, rb) require.ErrorIs(t, err, sql.ErrNotFound) require.True(t, strings.Contains(err.Error(), "missing atx")) require.Nil(t, got) diff --git a/prune/interface.go b/prune/interface.go new file mode 100644 index 0000000000..559a9639f6 --- /dev/null +++ b/prune/interface.go @@ -0,0 +1,11 @@ +package prune + +import ( + "github.com/spacemeshos/go-spacemesh/common/types" +) + +//go:generate mockgen -typed -package=prune -destination=./mocks.go -source=./interface.go + +type layerClock interface { + CurrentLayer() types.LayerID +} diff --git a/prune/metrics.go b/prune/metrics.go new file mode 100644 index 0000000000..97eb060fc8 --- /dev/null +++ b/prune/metrics.go @@ -0,0 +1,22 @@ +package prune + +import ( + "github.com/prometheus/client_golang/prometheus" + + "github.com/spacemeshos/go-spacemesh/metrics" +) + +const namespace = "prune" + +var ( + pruneLatency = metrics.NewHistogramWithBuckets( + "prune_seconds", + namespace, + "prune time in seconds", + []string{"step"}, + prometheus.ExponentialBuckets(0.01, 2, 10), + ) + proposalLatency = pruneLatency.WithLabelValues("proposal") + certLatency = pruneLatency.WithLabelValues("cert") + propTxLatency = pruneLatency.WithLabelValues("proptxs") +) diff --git a/prune/mocks.go b/prune/mocks.go new file mode 100644 index 0000000000..328eb8db10 --- /dev/null +++ b/prune/mocks.go @@ -0,0 +1,77 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: ./interface.go +// +// Generated by this command: +// +// mockgen -typed -package=prune -destination=./mocks.go -source=./interface.go +// +// Package prune is a generated GoMock package. +package prune + +import ( + reflect "reflect" + + types "github.com/spacemeshos/go-spacemesh/common/types" + gomock "go.uber.org/mock/gomock" +) + +// MocklayerClock is a mock of layerClock interface. +type MocklayerClock struct { + ctrl *gomock.Controller + recorder *MocklayerClockMockRecorder +} + +// MocklayerClockMockRecorder is the mock recorder for MocklayerClock. +type MocklayerClockMockRecorder struct { + mock *MocklayerClock +} + +// NewMocklayerClock creates a new mock instance. +func NewMocklayerClock(ctrl *gomock.Controller) *MocklayerClock { + mock := &MocklayerClock{ctrl: ctrl} + mock.recorder = &MocklayerClockMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MocklayerClock) EXPECT() *MocklayerClockMockRecorder { + return m.recorder +} + +// CurrentLayer mocks base method. +func (m *MocklayerClock) CurrentLayer() types.LayerID { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CurrentLayer") + ret0, _ := ret[0].(types.LayerID) + return ret0 +} + +// CurrentLayer indicates an expected call of CurrentLayer. +func (mr *MocklayerClockMockRecorder) CurrentLayer() *layerClockCurrentLayerCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CurrentLayer", reflect.TypeOf((*MocklayerClock)(nil).CurrentLayer)) + return &layerClockCurrentLayerCall{Call: call} +} + +// layerClockCurrentLayerCall wrap *gomock.Call +type layerClockCurrentLayerCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *layerClockCurrentLayerCall) Return(arg0 types.LayerID) *layerClockCurrentLayerCall { + c.Call = c.Call.Return(arg0) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *layerClockCurrentLayerCall) Do(f func() types.LayerID) *layerClockCurrentLayerCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *layerClockCurrentLayerCall) DoAndReturn(f func() types.LayerID) *layerClockCurrentLayerCall { + c.Call = c.Call.DoAndReturn(f) + return c +} diff --git a/prune/prune.go b/prune/prune.go new file mode 100644 index 0000000000..b5722be7c1 --- /dev/null +++ b/prune/prune.go @@ -0,0 +1,60 @@ +package prune + +import ( + "context" + "time" + + "go.uber.org/zap" + + "github.com/spacemeshos/go-spacemesh/common/types" + "github.com/spacemeshos/go-spacemesh/sql" + "github.com/spacemeshos/go-spacemesh/sql/certificates" + "github.com/spacemeshos/go-spacemesh/sql/proposals" + "github.com/spacemeshos/go-spacemesh/sql/transactions" +) + +func Prune( + ctx context.Context, + logger *zap.Logger, + db sql.Executor, + lc layerClock, + safeDist uint32, + interval time.Duration, +) { + logger.With().Info("db pruning launched", + zap.Uint32("dist", safeDist), + zap.Duration("interval", interval), + ) + for { + select { + case <-ctx.Done(): + return + case <-time.After(interval): + oldest := lc.CurrentLayer() - types.LayerID(safeDist) + t0 := time.Now() + if err := proposals.DeleteBefore(db, oldest); err != nil { + logger.Error("failed to delete proposals", + zap.Stringer("lid", oldest), + zap.Error(err), + ) + } + proposalLatency.Observe(time.Since(t0).Seconds()) + t1 := time.Now() + if err := certificates.DeleteCertBefore(db, oldest); err != nil { + logger.Error("failed to delete certificates", + zap.Stringer("lid", oldest), + zap.Error(err), + ) + } + certLatency.Observe(time.Since(t1).Seconds()) + t2 := time.Now() + if err := transactions.DeleteProposalTxsBefore(db, oldest); err != nil { + logger.Error("failed to delete proposal tx mapping", + zap.Stringer("lid", oldest), + zap.Error(err), + ) + } + propTxLatency.Observe(time.Since(t2).Seconds()) + } + } +} diff --git a/prune/prune_test.go b/prune/prune_test.go new file mode 100644 index 0000000000..286725459e --- /dev/null +++ b/prune/prune_test.go @@ -0,0 +1,95 @@ +package prune + +import ( + "context" + "testing" + "time" + + "github.com/stretchr/testify/require" + "go.uber.org/mock/gomock" + "golang.org/x/sync/errgroup" + + "github.com/spacemeshos/go-spacemesh/common/types" + "github.com/spacemeshos/go-spacemesh/log/logtest" + "github.com/spacemeshos/go-spacemesh/sql" + "github.com/spacemeshos/go-spacemesh/sql/ballots" + "github.com/spacemeshos/go-spacemesh/sql/certificates" + "github.com/spacemeshos/go-spacemesh/sql/proposals" + "github.com/spacemeshos/go-spacemesh/sql/transactions" +) + +func TestPrune(t *testing.T) { + db := sql.InMemory() + current := types.LayerID(10) + mc := NewMocklayerClock(gomock.NewController(t)) + done := make(chan struct{}) + count := 0 + mc.EXPECT().CurrentLayer().DoAndReturn(func() types.LayerID { + if count == 0 { + close(done) + } + count++ + return current + }).AnyTimes() + lyrProps := make([]*types.Proposal, 0, current) + for lid := types.LayerID(0); lid < current; lid++ { + blt := types.NewExistingBallot(types.RandomBallotID(), types.RandomEdSignature(), types.NodeID{1}, lid) + require.NoError(t, ballots.Add(db, &blt)) + p := &types.Proposal{ + InnerProposal: types.InnerProposal{ + Ballot: blt, + TxIDs: []types.TransactionID{types.RandomTransactionID(), types.RandomTransactionID()}, + }, + Signature: types.RandomEdSignature(), + } + p.SetID(types.RandomProposalID()) + require.NoError(t, proposals.Add(db, p)) + require.NoError(t, certificates.Add(db, lid, &types.Certificate{BlockID: types.RandomBlockID()})) + for _, tid := range p.TxIDs { + require.NoError(t, transactions.AddToProposal(db, tid, lid, p.ID())) + } + lyrProps = append(lyrProps, p) + } + confidenceDist := uint32(3) + ctx, cancel := context.WithCancel(context.Background()) + var eg errgroup.Group + eg.Go(func() error { + Prune(ctx, logtest.New(t).Zap(), db, mc, confidenceDist, time.Millisecond) + return nil + }) + require.Eventually(t, func() bool { + select { + case <-done: + oldest := current - types.LayerID(confidenceDist) + for lid := types.LayerID(0); lid < oldest; lid++ { + _, err := certificates.CertifiedBlock(db, lid) + require.ErrorIs(t, err, sql.ErrNotFound) + _, err = proposals.GetByLayer(db, lid) + require.ErrorIs(t, err, sql.ErrNotFound) + for _, tid := range lyrProps[lid].TxIDs { + exists, err := transactions.HasProposalTX(db, lyrProps[lid].ID(), tid) + require.NoError(t, err) + require.False(t, exists) + } + } + for lid := oldest; lid < current; lid++ { + got, err := certificates.CertifiedBlock(db, lid) + require.NoError(t, err) + require.NotEqual(t, types.EmptyBlockID, got) + pps, err := proposals.GetByLayer(db, lid) + require.NoError(t, err) + require.NotEmpty(t, pps) + for _, tid := range lyrProps[lid].TxIDs { + exists, err := transactions.HasProposalTX(db, lyrProps[lid].ID(), tid) + require.NoError(t, err) + require.True(t, exists) + } + } + return true + default: + return false + } + }, time.Second, 10*time.Millisecond) + cancel() + require.NoError(t, eg.Wait()) +} diff --git a/sql/ballots/ballots.go b/sql/ballots/ballots.go index 827a29df95..d539a3ef05 100644 --- a/sql/ballots/ballots.go +++ b/sql/ballots/ballots.go @@ -70,6 +70,17 @@ func Has(db sql.Executor, id types.BallotID) (bool, error) { return rows > 0, nil } +func UpdateBlob(db sql.Executor, bid types.BallotID, blob []byte) error { + if _, err := db.Exec(`update ballots set ballot = ?2 where id = ?1;`, + func(stmt *sql.Statement) { + stmt.BindBytes(1, bid.Bytes()) + stmt.BindBytes(2, blob[:]) + }, nil); err != nil { + return fmt.Errorf("update blob %s: %w", bid.String(), err) + } + return nil +} + // Get ballot with id from database. func Get(db sql.Executor, id types.BallotID) (rst *types.Ballot, err error) { if rows, err := db.Exec(`select pubkey, ballot, length(identities.proof) @@ -118,6 +129,31 @@ func Layer(db sql.Executor, lid types.LayerID) (rst []*types.Ballot, err error) return rst, err } +// LayerNoMalicious returns full ballot without joining malicious identities. +func LayerNoMalicious(db sql.Executor, lid types.LayerID) (rst []*types.Ballot, err error) { + var derr error + if _, err = db.Exec(`select id, ballot from ballots where layer = ?1;`, + func(stmt *sql.Statement) { + stmt.BindInt64(1, int64(lid)) + }, func(stmt *sql.Statement) bool { + id := types.BallotID{} + stmt.ColumnBytes(0, id[:]) + var ballot types.Ballot + _, derr := codec.DecodeFrom(stmt.ColumnReader(1), &ballot) + if derr != nil { + return false + } + ballot.SetID(id) + rst = append(rst, &ballot) + return true + }); err != nil { + return nil, fmt.Errorf("selecting %d: %w", lid, err) + } else if derr != nil { + return nil, fmt.Errorf("decoding %d: %w", lid, err) + } + return rst, err +} + // IDsInLayer returns ballots ids in the layer. func IDsInLayer(db sql.Executor, lid types.LayerID) (rst []types.BallotID, err error) { if _, err := db.Exec("select id from ballots where layer = ?1;", func(stmt *sql.Statement) { diff --git a/sql/ballots/ballots_test.go b/sql/ballots/ballots_test.go index 88dd3b8b77..ef384b394d 100644 --- a/sql/ballots/ballots_test.go +++ b/sql/ballots/ballots_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/require" + "github.com/spacemeshos/go-spacemesh/codec" "github.com/spacemeshos/go-spacemesh/common/types" "github.com/spacemeshos/go-spacemesh/signing" "github.com/spacemeshos/go-spacemesh/sql" @@ -53,6 +54,13 @@ func TestLayer(t *testing.T) { for _, ballot := range rst { require.True(t, ballot.IsMalicious()) } + + rst, err = LayerNoMalicious(db, start) + require.NoError(t, err) + require.Len(t, rst, len(ballots)) + for _, ballot := range rst { + require.False(t, ballot.IsMalicious()) + } } func TestAdd(t *testing.T) { @@ -75,6 +83,26 @@ func TestAdd(t *testing.T) { require.True(t, stored.IsMalicious()) } +func TestUpdateBlob(t *testing.T) { + db := sql.InMemory() + nodeID := types.RandomNodeID() + ballot := types.NewExistingBallot(types.BallotID{1}, types.RandomEdSignature(), nodeID, types.LayerID(0)) + ballot.EpochData = &types.EpochData{ + ActiveSetHash: types.RandomHash(), + } + ballot.ActiveSet = types.RandomActiveSet(199) + require.NoError(t, Add(db, &ballot)) + got, err := Get(db, types.BallotID{1}) + require.NoError(t, err) + require.Equal(t, ballot, *got) + + ballot.ActiveSet = nil + require.NoError(t, UpdateBlob(db, types.BallotID{1}, codec.MustEncode(&ballot))) + got, err = Get(db, types.BallotID{1}) + require.NoError(t, err) + require.Empty(t, got.ActiveSet) +} + func TestHas(t *testing.T) { db := sql.InMemory() ballot := types.NewExistingBallot(types.BallotID{1}, types.EmptyEdSignature, types.EmptyNodeID, types.LayerID(0)) diff --git a/sql/ballots/util/extract.go b/sql/ballots/util/extract.go new file mode 100644 index 0000000000..52e097a06c --- /dev/null +++ b/sql/ballots/util/extract.go @@ -0,0 +1,58 @@ +package util + +import ( + "errors" + "fmt" + + "github.com/spacemeshos/go-spacemesh/common/types" + "github.com/spacemeshos/go-spacemesh/log" + "github.com/spacemeshos/go-spacemesh/sql" + "github.com/spacemeshos/go-spacemesh/sql/activesets" + "github.com/spacemeshos/go-spacemesh/sql/ballots" +) + +func ExtractActiveSet(db sql.Executor) error { + latest, err := ballots.LatestLayer(db) + if err != nil { + return fmt.Errorf("extract get latest: %w", err) + } + extracted := 0 + unique := 0 + log.With().Info("extracting ballots active sets", + log.Uint32("from", types.EpochID(2).FirstLayer().Uint32()), + log.Uint32("to", latest.Uint32()), + ) + for lid := types.EpochID(2).FirstLayer(); lid <= latest; lid++ { + blts, err := ballots.Layer(db, lid) + if err != nil { + return fmt.Errorf("extract layer %d: %w", lid, err) + } + for _, b := range blts { + if b.EpochData == nil { + continue + } + if len(b.ActiveSet) == 0 { + continue + } + if err := activesets.Add(db, b.EpochData.ActiveSetHash, &types.EpochActiveSet{ + Epoch: b.Layer.GetEpoch(), + Set: b.ActiveSet, + }); err != nil && !errors.Is(err, sql.ErrObjectExists) { + return fmt.Errorf("add active set %s (%s): %w", b.ID().String(), b.EpochData.ActiveSetHash.ShortString(), err) + } else if err == nil { + unique++ + } + // TODO: prune ballot active set after migration 4 is released + //b.ActiveSet = nil + //if err := ballots.UpdateBlob(db, b.ID(), codec.MustEncode(b)); err != nil { + // return fmt.Errorf("update ballot %s: %w", b.ID().String(), err) + //} + extracted++ + } + } + log.With().Info("extracted active sets from ballots", + log.Int("num", extracted), + log.Int("unique", unique), + ) + return nil +} diff --git a/sql/ballots/util/extract_test.go b/sql/ballots/util/extract_test.go new file mode 100644 index 0000000000..c9df4416a3 --- /dev/null +++ b/sql/ballots/util/extract_test.go @@ -0,0 +1,57 @@ +package util + +import ( + "os" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/spacemeshos/go-spacemesh/common/types" + "github.com/spacemeshos/go-spacemesh/sql" + "github.com/spacemeshos/go-spacemesh/sql/activesets" + "github.com/spacemeshos/go-spacemesh/sql/ballots" +) + +func TestMain(m *testing.M) { + types.SetLayersPerEpoch(4) + res := m.Run() + os.Exit(res) +} + +func TestExtractActiveSet(t *testing.T) { + db := sql.InMemory() + current := types.LayerID(20) + blts := make([]*types.Ballot, 0, current) + hashes := []types.Hash32{types.RandomHash(), types.RandomHash()} + actives := [][]types.ATXID{types.RandomActiveSet(11), types.RandomActiveSet(19)} + for lid := types.EpochID(2).FirstLayer(); lid < current; lid++ { + blt := types.NewExistingBallot(types.RandomBallotID(), types.RandomEdSignature(), types.NodeID{1}, lid) + if lid%3 == 0 { + blt.EpochData = &types.EpochData{ + ActiveSetHash: hashes[0], + } + blt.ActiveSet = actives[0] + } + if lid%3 == 1 { + blt.EpochData = &types.EpochData{ + ActiveSetHash: hashes[1], + } + blt.ActiveSet = actives[1] + } + require.NoError(t, ballots.Add(db, &blt)) + blts = append(blts, &blt) + } + require.NoError(t, ExtractActiveSet(db)) + for _, b := range blts { + got, err := ballots.Get(db, b.ID()) + require.NoError(t, err) + if b.Layer%3 != 2 { + require.NotEmpty(t, got.ActiveSet) + } + } + for i, h := range hashes { + got, err := activesets.Get(db, h) + require.NoError(t, err) + require.Equal(t, actives[i], got.Set) + } +} diff --git a/sql/certificates/certs.go b/sql/certificates/certs.go index 9ec75165d0..b5010091a0 100644 --- a/sql/certificates/certs.go +++ b/sql/certificates/certs.go @@ -164,3 +164,13 @@ func SetInvalid(db sql.Executor, lid types.LayerID, bid types.BlockID) error { } return nil } + +func DeleteCertBefore(db sql.Executor, lid types.LayerID) error { + if _, err := db.Exec(`update certificates set cert = null where layer < ?1;`, + func(stmt *sql.Statement) { + stmt.BindInt64(1, int64(lid)) + }, nil); err != nil { + return fmt.Errorf("delete %s: %w", lid, err) + } + return nil +} diff --git a/sql/certificates/certs_test.go b/sql/certificates/certs_test.go index b345de33bf..cfe4ff9104 100644 --- a/sql/certificates/certs_test.go +++ b/sql/certificates/certs_test.go @@ -160,6 +160,22 @@ func TestCertifiedBlock(t *testing.T) { require.Equal(t, types.EmptyBlockID, got) } +func TestDeleteCert(t *testing.T) { + db := sql.InMemory() + require.NoError(t, Add(db, types.LayerID(2), &types.Certificate{BlockID: types.BlockID{2}})) + require.NoError(t, Add(db, types.LayerID(3), &types.Certificate{BlockID: types.BlockID{3}})) + require.NoError(t, Add(db, types.LayerID(4), &types.Certificate{BlockID: types.BlockID{4}})) + require.NoError(t, DeleteCertBefore(db, 4)) + + _, err := CertifiedBlock(db, types.LayerID(2)) + require.ErrorIs(t, err, sql.ErrNotFound) + _, err = CertifiedBlock(db, types.LayerID(3)) + require.ErrorIs(t, err, sql.ErrNotFound) + got, err := CertifiedBlock(db, types.LayerID(4)) + require.NoError(t, err) + require.Equal(t, types.BlockID{4}, got) +} + func TestFirstInEpoch(t *testing.T) { db := sql.InMemory() diff --git a/sql/database.go b/sql/database.go index df95109e6f..044bf88c1b 100644 --- a/sql/database.go +++ b/sql/database.go @@ -59,6 +59,9 @@ type conf struct { connections int migrations Migrations enableLatency bool + + // TODO: remove after state is pruned for majority + v5Migration func(Executor) error } // WithConnections overwrites number of pooled connections. @@ -75,6 +78,12 @@ func WithMigrations(migrations Migrations) Opt { } } +func WithV5Migration(cb func(Executor) error) Opt { + return func(c *conf) { + c.v5Migration = cb + } +} + // WithLatencyMetering enables metric that track latency for every database query. // Note that it will be a significant amount of data, and should not be enabled on // multiple nodes by default. @@ -116,6 +125,10 @@ func Open(uri string, opts ...Opt) (*Database, error) { db.latency = newQueryLatency() } if config.migrations != nil { + before, err := version(db) + if err != nil { + return nil, err + } tx, err := db.Tx(context.Background()) if err != nil { return nil, err @@ -128,13 +141,26 @@ func Open(uri string, opts ...Opt) (*Database, error) { if err != nil { return nil, err } + after, err := version(db) + if err != nil { + return nil, err + } + if before <= 4 && after == 5 && config.v5Migration != nil { + // v5 migration (active set extraction) needs the 4rd migration to execute first + if err := config.v5Migration(db); err != nil { + return nil, err + } + if err := Vacuum(db); err != nil { + return nil, err + } + } } for i := 0; i < config.connections; i++ { conn := pool.Get(context.Background()) if err := registerFunctions(conn); err != nil { return nil, err } - defer pool.Put(conn) + pool.Put(conn) } return db, nil } diff --git a/sql/migrations.go b/sql/migrations.go index c6bf08f9fe..aeec91e0bd 100644 --- a/sql/migrations.go +++ b/sql/migrations.go @@ -23,6 +23,17 @@ type migration struct { // Migrations is interface for migrations provider. type Migrations func(Executor) error +func version(db Executor) (int, error) { + var current int + if _, err := db.Exec("PRAGMA user_version;", nil, func(stmt *Statement) bool { + current = stmt.ColumnInt(0) + return true + }); err != nil { + return 0, fmt.Errorf("read user_version %w", err) + } + return current, nil +} + func embeddedMigrations(db Executor) error { var migrations []migration fs.WalkDir(embedded, "migrations", func(path string, d fs.DirEntry, err error) error { @@ -62,13 +73,9 @@ func embeddedMigrations(db Executor) error { return migrations[i].order < migrations[j].order }) - var current int - - if _, err := db.Exec("PRAGMA user_version;", nil, func(stmt *Statement) bool { - current = stmt.ColumnInt(0) - return true - }); err != nil { - return fmt.Errorf("read user_version %w", err) + current, err := version(db) + if err != nil { + return err } for _, m := range migrations { diff --git a/sql/migrations/0003_next.sql b/sql/migrations/0003_v1.1.5.sql similarity index 100% rename from sql/migrations/0003_next.sql rename to sql/migrations/0003_v1.1.5.sql diff --git a/sql/migrations/0004_v1.1.7.sql b/sql/migrations/0004_v1.1.7.sql new file mode 100644 index 0000000000..ec8388a41f --- /dev/null +++ b/sql/migrations/0004_v1.1.7.sql @@ -0,0 +1 @@ +CREATE INDEX ballots_by_atx_by_layer ON ballots (atx, layer asc); diff --git a/sql/migrations/0005_next.sql b/sql/migrations/0005_next.sql new file mode 100644 index 0000000000..7b8a0aded0 --- /dev/null +++ b/sql/migrations/0005_next.sql @@ -0,0 +1,3 @@ +DELETE FROM proposals; +DELETE FROM proposal_transactions; +UPDATE certificates SET cert = NULL WHERE layer < 19000; \ No newline at end of file diff --git a/sql/migrations_test.go b/sql/migrations_test.go index 8a0c637c46..aa74655430 100644 --- a/sql/migrations_test.go +++ b/sql/migrations_test.go @@ -15,5 +15,5 @@ func TestMigrationsAppliedOnce(t *testing.T) { return true }) require.NoError(t, err) - require.Equal(t, version, 3) + require.Equal(t, version, 5) } diff --git a/sql/proposals/proposals.go b/sql/proposals/proposals.go index 30a0c3a154..d410c2b4e9 100644 --- a/sql/proposals/proposals.go +++ b/sql/proposals/proposals.go @@ -186,7 +186,7 @@ func decodeProposal(stmt *sql.Statement) (*types.Proposal, error) { return proposal, nil } -func Delete(db sql.Executor, lid types.LayerID) error { +func DeleteBefore(db sql.Executor, lid types.LayerID) error { if _, err := db.Exec(`delete from proposals where layer < ?1;`, func(stmt *sql.Statement) { stmt.BindInt64(1, int64(lid)) diff --git a/sql/proposals/proposals_test.go b/sql/proposals/proposals_test.go index d9bf0316e9..886b68e91e 100644 --- a/sql/proposals/proposals_test.go +++ b/sql/proposals/proposals_test.go @@ -57,7 +57,7 @@ func TestDelete(t *testing.T) { require.NoError(t, err) require.Len(t, got, numProps) } - require.NoError(t, Delete(db, types.LayerID(maxLayers))) + require.NoError(t, DeleteBefore(db, types.LayerID(maxLayers))) for i := 1; i < maxLayers; i++ { _, err := GetByLayer(db, types.LayerID(i)) require.ErrorIs(t, err, sql.ErrNotFound) diff --git a/sql/transactions/transactions.go b/sql/transactions/transactions.go index 4c7e654107..536b0bf99f 100644 --- a/sql/transactions/transactions.go +++ b/sql/transactions/transactions.go @@ -59,6 +59,17 @@ func AddToProposal(db sql.Executor, tid types.TransactionID, lid types.LayerID, return nil } +func DeleteProposalTxsBefore(db sql.Executor, lid types.LayerID) error { + if _, err := db.Exec(` + delete from proposal_transactions where layer < ?1;`, + func(stmt *sql.Statement) { + stmt.BindInt64(1, int64(lid)) + }, nil); err != nil { + return fmt.Errorf("DeleteProposalTxs %d: %w", lid, err) + } + return nil +} + // HasProposalTX returns true if the given transaction is included in the given proposal. func HasProposalTX(db sql.Executor, pid types.ProposalID, tid types.TransactionID) (bool, error) { rows, err := db.Exec("select 1 from proposal_transactions where pid = ?1 and tid = ?2", diff --git a/sql/transactions/transactions_test.go b/sql/transactions/transactions_test.go index 28a8070ea5..a698b64f4d 100644 --- a/sql/transactions/transactions_test.go +++ b/sql/transactions/transactions_test.go @@ -154,6 +154,37 @@ func TestAddToProposal(t *testing.T) { require.False(t, has) } +func TestDeleteProposalTxs(t *testing.T) { + db := sql.InMemory() + proposals := map[types.LayerID][]types.ProposalID{ + types.LayerID(10): {{1, 1}, {1, 2}}, + types.LayerID(11): {{2, 1}, {2, 2}}, + } + tids := []types.TransactionID{{1, 2}, {2, 3}} + for lid, pids := range proposals { + for _, tid := range tids { + for _, pid := range pids { + require.NoError(t, transactions.AddToProposal(db, tid, lid, pid)) + } + } + } + require.NoError(t, transactions.DeleteProposalTxsBefore(db, types.LayerID(11))) + for _, pid := range proposals[types.LayerID(10)] { + for _, tid := range tids { + has, err := transactions.HasProposalTX(db, pid, tid) + require.NoError(t, err) + require.False(t, has) + } + } + for _, pid := range proposals[types.LayerID(11)] { + for _, tid := range tids { + has, err := transactions.HasProposalTX(db, pid, tid) + require.NoError(t, err) + require.True(t, has) + } + } +} + func TestAddToBlock(t *testing.T) { db := sql.InMemory() diff --git a/sql/vacuum.go b/sql/vacuum.go new file mode 100644 index 0000000000..0f874fe14f --- /dev/null +++ b/sql/vacuum.go @@ -0,0 +1,20 @@ +package sql + +import ( + "fmt" + + "github.com/spacemeshos/go-spacemesh/log" +) + +func Vacuum(db Executor) error { + log.Info("vacuuming db...") + if _, err := db.Exec("vacuum", nil, nil); err != nil { + return fmt.Errorf("vacuum %w", err) + } + log.Info("checkpointing db...") + if _, err := db.Exec("pragma wal_checkpoint(TRUNCATE)", nil, nil); err != nil { + return fmt.Errorf("wal checkpoint %w", err) + } + log.Info("db vacuum completed") + return nil +} diff --git a/sql/vacuum_test.go b/sql/vacuum_test.go new file mode 100644 index 0000000000..b994516279 --- /dev/null +++ b/sql/vacuum_test.go @@ -0,0 +1,12 @@ +package sql + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestVacuumDB(t *testing.T) { + db := InMemory() + require.NoError(t, Vacuum(db)) +} diff --git a/syncer/blockssync/mocks.go b/syncer/blockssync/mocks.go index 3e97a07566..cbbbca4e81 100644 --- a/syncer/blockssync/mocks.go +++ b/syncer/blockssync/mocks.go @@ -1,6 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: ./blocks.go - +// +// Generated by this command: +// +// mockgen -typed -package=blockssync -destination=./mocks.go -source=./blocks.go +// // Package blockssync is a generated GoMock package. package blockssync @@ -44,7 +48,7 @@ func (m *MockblockFetcher) GetBlocks(arg0 context.Context, arg1 []types.BlockID) } // GetBlocks indicates an expected call of GetBlocks. -func (mr *MockblockFetcherMockRecorder) GetBlocks(arg0, arg1 interface{}) *blockFetcherGetBlocksCall { +func (mr *MockblockFetcherMockRecorder) GetBlocks(arg0, arg1 any) *blockFetcherGetBlocksCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlocks", reflect.TypeOf((*MockblockFetcher)(nil).GetBlocks), arg0, arg1) return &blockFetcherGetBlocksCall{Call: call} diff --git a/syncer/data_fetch.go b/syncer/data_fetch.go index 24d273c783..6cd3649dca 100644 --- a/syncer/data_fetch.go +++ b/syncer/data_fetch.go @@ -39,9 +39,6 @@ type dataResponse struct { type opinionResponse struct { opinions []*fetch.LayerOpinion } -type opinionResponse2 struct { - opinions []*fetch.LayerOpinion2 -} type maliciousIDResponse struct { ids map[types.NodeID]struct{} @@ -50,7 +47,6 @@ type maliciousIDResponse struct { type ( dataRequest request[fetch.LayerData, dataResponse] opinionRequest request[fetch.LayerOpinion, opinionResponse] - opinionRequest2 request[fetch.LayerOpinion2, opinionResponse2] maliciousIDRequest request[fetch.MaliciousIDs, maliciousIDResponse] ) @@ -311,8 +307,12 @@ func fetchLayerData(ctx context.Context, logger log.Log, fetcher fetcher, req *d } } -// PollLayerOpinions polls all peers for opinions in the specified layer. -func (d *DataFetch) PollLayerOpinions(ctx context.Context, lid types.LayerID, peers []p2p.Peer) ([]*fetch.LayerOpinion, error) { +func (d *DataFetch) PollLayerOpinions( + ctx context.Context, + lid types.LayerID, + needCert bool, + peers []p2p.Peer, +) ([]*fetch.LayerOpinion, []*types.Certificate, error) { req := &opinionRequest{ lid: lid, peers: peers, @@ -326,83 +326,9 @@ func (d *DataFetch) PollLayerOpinions(ctx context.Context, lid types.LayerID, pe opnsPeerError.Inc() } if err := d.fetcher.GetLayerOpinions(ctx, peers, lid, okFunc, errFunc); err != nil { - return nil, err - } - req.peerResults = map[p2p.Peer]peerResult[fetch.LayerOpinion]{} - var ( - success bool - candidateErr error - ) - for { - select { - case res := <-req.ch: - req.peerResults[res.peer] = res - if res.err == nil { - success = true - req.response.opinions = append(req.response.opinions, res.data) - } else if candidateErr == nil { - candidateErr = res.err - } - if len(req.peerResults) < len(req.peers) { - break - } - // all peer responded - if success { - candidateErr = nil - } - return req.response.opinions, candidateErr - case <-ctx.Done(): - d.logger.WithContext(ctx).Debug("request timed out", lid) - return nil, errTimeout - } - } -} - -func (d *DataFetch) receiveOpinions(ctx context.Context, req *opinionRequest, peer p2p.Peer, data []byte, peerErr error) { - logger := d.logger.WithContext(ctx).WithFields(req.lid, log.Stringer("peer", peer)) - logger.Debug("received layer opinions from peer") - - var ( - result = peerResult[fetch.LayerOpinion]{peer: peer, err: peerErr} - lo fetch.LayerOpinion - ) - if peerErr != nil { - logger.With().Debug("received peer error for layer opinions", log.Err(peerErr)) - } else if result.err = codec.Decode(data, &lo); result.err != nil { - logger.With().Debug("error converting bytes to LayerOpinion", log.Err(result.err)) - } else { - lo.SetPeer(peer) - result.data = &lo - } - select { - case req.ch <- result: - case <-ctx.Done(): - logger.Debug("request timed out") - } -} - -func (d *DataFetch) PollLayerOpinions2( - ctx context.Context, - lid types.LayerID, - needCert bool, - peers []p2p.Peer, -) ([]*fetch.LayerOpinion2, []*types.Certificate, error) { - req := &opinionRequest2{ - lid: lid, - peers: peers, - ch: make(chan peerResult[fetch.LayerOpinion2], len(peers)), - } - okFunc := func(data []byte, peer p2p.Peer) { - d.receiveOpinions2(ctx, req, peer, data, nil) - } - errFunc := func(err error, peer p2p.Peer) { - d.receiveOpinions2(ctx, req, peer, nil, err) - opnsPeerError.Inc() - } - if err := d.fetcher.GetLayerOpinions2(ctx, peers, lid, okFunc, errFunc); err != nil { return nil, nil, err } - req.peerResults = map[p2p.Peer]peerResult[fetch.LayerOpinion2]{} + req.peerResults = map[p2p.Peer]peerResult[fetch.LayerOpinion]{} var ( success bool candidateErr error @@ -458,18 +384,18 @@ func (d *DataFetch) PollLayerOpinions2( } } -func (d *DataFetch) receiveOpinions2(ctx context.Context, req *opinionRequest2, peer p2p.Peer, data []byte, peerErr error) { +func (d *DataFetch) receiveOpinions(ctx context.Context, req *opinionRequest, peer p2p.Peer, data []byte, peerErr error) { logger := d.logger.WithContext(ctx).WithFields(req.lid, log.Stringer("peer", peer)) logger.Debug("received layer opinions from peer") var ( - result = peerResult[fetch.LayerOpinion2]{peer: peer, err: peerErr} - lo fetch.LayerOpinion2 + result = peerResult[fetch.LayerOpinion]{peer: peer, err: peerErr} + lo fetch.LayerOpinion ) if peerErr != nil { logger.With().Debug("received peer error for layer opinions", log.Err(peerErr)) } else if result.err = codec.Decode(data, &lo); result.err != nil { - logger.With().Debug("error decoding LayerOpinion2", log.Err(result.err)) + logger.With().Debug("error decoding LayerOpinion", log.Err(result.err)) } else { lo.SetPeer(peer) result.data = &lo diff --git a/syncer/data_fetch_test.go b/syncer/data_fetch_test.go index 10b2e97887..1b420e4719 100644 --- a/syncer/data_fetch_test.go +++ b/syncer/data_fetch_test.go @@ -55,20 +55,9 @@ func generateMaliciousIDs(t *testing.T) ([]types.NodeID, []byte) { return malicious.NodeIDs, data } -func generateLayerOpinions(t *testing.T) []byte { - t.Helper() - var lo fetch.LayerOpinion - lo.Cert = &types.Certificate{ - BlockID: types.RandomBlockID(), - } - data, err := codec.Encode(&lo) - require.NoError(t, err) - return data -} - func generateLayerOpinions2(t *testing.T, bid *types.BlockID) []byte { t.Helper() - lo := &fetch.LayerOpinion2{ + lo := &fetch.LayerOpinion{ PrevAggHash: types.RandomHash(), Certified: bid, } @@ -225,58 +214,6 @@ func TestDataFetch_PollLayerData_PeerErrors(t *testing.T) { } func TestDataFetch_PollLayerOpinions(t *testing.T) { - const numPeers = 4 - peers := GenPeers(numPeers) - lid := types.LayerID(10) - pe := errors.New("meh") - tt := []struct { - name string - err error - pErrs []error - }{ - { - name: "all peers", - pErrs: []error{nil, nil, nil, nil}, - }, - { - name: "some peers have errors", - pErrs: []error{pe, pe, nil, nil}, - }, - { - name: "all peers have errors", - pErrs: []error{pe, pe, pe, pe}, - err: pe, - }, - } - - for _, tc := range tt { - tc := tc - t.Run(tc.name, func(t *testing.T) { - t.Parallel() - - td := newTestDataFetch(t) - td.mFetcher.EXPECT().GetLayerOpinions(gomock.Any(), peers, lid, gomock.Any(), gomock.Any()).DoAndReturn( - func(_ context.Context, _ []p2p.Peer, _ types.LayerID, okCB func([]byte, p2p.Peer), errCB func(error, p2p.Peer)) error { - for i, peer := range peers { - if tc.pErrs[i] != nil { - errCB(tc.pErrs[i], peer) - } else { - okCB(generateLayerOpinions(t), peer) - } - } - return nil - }) - - got, err := td.PollLayerOpinions(context.TODO(), lid, peers) - require.ErrorIs(t, err, tc.err) - if err == nil { - require.NotEmpty(t, got) - } - }) - } -} - -func TestDataFetch_PollLayerOpinions2(t *testing.T) { const numPeers = 4 peers := GenPeers(numPeers) lid := types.LayerID(10) @@ -335,7 +272,7 @@ func TestDataFetch_PollLayerOpinions2(t *testing.T) { t.Parallel() td := newTestDataFetch(t) - td.mFetcher.EXPECT().GetLayerOpinions2(gomock.Any(), peers, lid, gomock.Any(), gomock.Any()).DoAndReturn( + td.mFetcher.EXPECT().GetLayerOpinions(gomock.Any(), peers, lid, gomock.Any(), gomock.Any()).DoAndReturn( func(_ context.Context, _ []p2p.Peer, _ types.LayerID, okCB func([]byte, p2p.Peer), errCB func(error, p2p.Peer)) error { for i, peer := range peers { if tc.pErrs[i] != nil { @@ -366,7 +303,7 @@ func TestDataFetch_PollLayerOpinions2(t *testing.T) { return nil }) - got, certs, err := td.PollLayerOpinions2(context.TODO(), lid, tc.needCert, peers) + got, certs, err := td.PollLayerOpinions(context.TODO(), lid, tc.needCert, peers) require.ErrorIs(t, err, tc.err) if err == nil { require.NotEmpty(t, got) diff --git a/syncer/interface.go b/syncer/interface.go index fb1b2ba58f..d171dcd529 100644 --- a/syncer/interface.go +++ b/syncer/interface.go @@ -4,8 +4,6 @@ import ( "context" "time" - "github.com/libp2p/go-libp2p/core/protocol" - "github.com/spacemeshos/go-spacemesh/common/types" "github.com/spacemeshos/go-spacemesh/fetch" "github.com/spacemeshos/go-spacemesh/p2p" @@ -32,8 +30,7 @@ type fetchLogic interface { PollMaliciousProofs(ctx context.Context) error PollLayerData(context.Context, types.LayerID, ...p2p.Peer) error - PollLayerOpinions(context.Context, types.LayerID, []p2p.Peer) ([]*fetch.LayerOpinion, error) - PollLayerOpinions2(context.Context, types.LayerID, bool, []p2p.Peer) ([]*fetch.LayerOpinion2, []*types.Certificate, error) + PollLayerOpinions(context.Context, types.LayerID, bool, []p2p.Peer) ([]*fetch.LayerOpinion, []*types.Certificate, error) GetEpochATXs(context.Context, types.EpochID) error } @@ -42,7 +39,6 @@ type fetcher interface { GetMaliciousIDs(context.Context, []p2p.Peer, func([]byte, p2p.Peer), func(error, p2p.Peer)) error GetLayerData(context.Context, []p2p.Peer, types.LayerID, func([]byte, p2p.Peer), func(error, p2p.Peer)) error GetLayerOpinions(context.Context, []p2p.Peer, types.LayerID, func([]byte, p2p.Peer), func(error, p2p.Peer)) error - GetLayerOpinions2(context.Context, []p2p.Peer, types.LayerID, func([]byte, p2p.Peer), func(error, p2p.Peer)) error GetCert(context.Context, types.LayerID, types.BlockID, []p2p.Peer) (*types.Certificate, error) GetMalfeasanceProofs(context.Context, []types.NodeID) error @@ -52,7 +48,6 @@ type fetcher interface { RegisterPeerHashes(peer p2p.Peer, hashes []types.Hash32) GetPeers() []p2p.Peer - PeerProtocols(p2p.Peer) ([]protocol.ID, error) PeerEpochInfo(context.Context, p2p.Peer, types.EpochID) (*fetch.EpochData, error) PeerMeshHashes(context.Context, p2p.Peer, *fetch.MeshHashRequest) (*fetch.MeshHashes, error) } diff --git a/syncer/metrics.go b/syncer/metrics.go index 9a10028c85..87e6d680a2 100644 --- a/syncer/metrics.go +++ b/syncer/metrics.go @@ -89,21 +89,17 @@ var ( certPeerError = peerError.WithLabelValues("cert") malPeerError = peerError.WithLabelValues("mal") - numOpnPoll = metrics.NewCounter( + v2OpnPoll = metrics.NewCounter( "opn_poll", namespace, "number of times opinions are polled", []string{"version"}, - ) - v1OpnPoll = numOpnPoll.WithLabelValues("v1") - v2OpnPoll = numOpnPoll.WithLabelValues("v2") + ).WithLabelValues("v2") - numOpnErr = metrics.NewCounter( + v2OpnErr = metrics.NewCounter( "opn_err", namespace, "number of times opinions poll failed", []string{"version"}, - ) - v1OpnErr = numOpnErr.WithLabelValues("v1") - v2OpnErr = numOpnErr.WithLabelValues("v2") + ).WithLabelValues("v2") ) diff --git a/syncer/mocks/mocks.go b/syncer/mocks/mocks.go index 3ac8060c8c..53eb33263c 100644 --- a/syncer/mocks/mocks.go +++ b/syncer/mocks/mocks.go @@ -1,6 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: ./interface.go - +// +// Generated by this command: +// +// mockgen -typed -package=mocks -destination=./mocks/mocks.go -source=./interface.go +// // Package mocks is a generated GoMock package. package mocks @@ -9,7 +13,6 @@ import ( reflect "reflect" time "time" - protocol "github.com/libp2p/go-libp2p/core/protocol" types "github.com/spacemeshos/go-spacemesh/common/types" fetch "github.com/spacemeshos/go-spacemesh/fetch" p2p "github.com/spacemeshos/go-spacemesh/p2p" @@ -107,7 +110,7 @@ func (m *MockmeshProvider) SetZeroBlockLayer(arg0 context.Context, arg1 types.La } // SetZeroBlockLayer indicates an expected call of SetZeroBlockLayer. -func (mr *MockmeshProviderMockRecorder) SetZeroBlockLayer(arg0, arg1 interface{}) *meshProviderSetZeroBlockLayerCall { +func (mr *MockmeshProviderMockRecorder) SetZeroBlockLayer(arg0, arg1 any) *meshProviderSetZeroBlockLayerCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetZeroBlockLayer", reflect.TypeOf((*MockmeshProvider)(nil).SetZeroBlockLayer), arg0, arg1) return &meshProviderSetZeroBlockLayerCall{Call: call} @@ -168,7 +171,7 @@ func (m *MockactiveSetCache) GetMissingActiveSet(arg0 types.EpochID, arg1 []type } // GetMissingActiveSet indicates an expected call of GetMissingActiveSet. -func (mr *MockactiveSetCacheMockRecorder) GetMissingActiveSet(arg0, arg1 interface{}) *activeSetCacheGetMissingActiveSetCall { +func (mr *MockactiveSetCacheMockRecorder) GetMissingActiveSet(arg0, arg1 any) *activeSetCacheGetMissingActiveSetCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMissingActiveSet", reflect.TypeOf((*MockactiveSetCache)(nil).GetMissingActiveSet), arg0, arg1) return &activeSetCacheGetMissingActiveSetCall{Call: call} @@ -229,7 +232,7 @@ func (m *MockfetchLogic) GetAtxs(arg0 context.Context, arg1 []types.ATXID) error } // GetAtxs indicates an expected call of GetAtxs. -func (mr *MockfetchLogicMockRecorder) GetAtxs(arg0, arg1 interface{}) *fetchLogicGetAtxsCall { +func (mr *MockfetchLogicMockRecorder) GetAtxs(arg0, arg1 any) *fetchLogicGetAtxsCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAtxs", reflect.TypeOf((*MockfetchLogic)(nil).GetAtxs), arg0, arg1) return &fetchLogicGetAtxsCall{Call: call} @@ -267,7 +270,7 @@ func (m *MockfetchLogic) GetBallots(arg0 context.Context, arg1 []types.BallotID) } // GetBallots indicates an expected call of GetBallots. -func (mr *MockfetchLogicMockRecorder) GetBallots(arg0, arg1 interface{}) *fetchLogicGetBallotsCall { +func (mr *MockfetchLogicMockRecorder) GetBallots(arg0, arg1 any) *fetchLogicGetBallotsCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBallots", reflect.TypeOf((*MockfetchLogic)(nil).GetBallots), arg0, arg1) return &fetchLogicGetBallotsCall{Call: call} @@ -305,7 +308,7 @@ func (m *MockfetchLogic) GetBlocks(arg0 context.Context, arg1 []types.BlockID) e } // GetBlocks indicates an expected call of GetBlocks. -func (mr *MockfetchLogicMockRecorder) GetBlocks(arg0, arg1 interface{}) *fetchLogicGetBlocksCall { +func (mr *MockfetchLogicMockRecorder) GetBlocks(arg0, arg1 any) *fetchLogicGetBlocksCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlocks", reflect.TypeOf((*MockfetchLogic)(nil).GetBlocks), arg0, arg1) return &fetchLogicGetBlocksCall{Call: call} @@ -344,7 +347,7 @@ func (m *MockfetchLogic) GetCert(arg0 context.Context, arg1 types.LayerID, arg2 } // GetCert indicates an expected call of GetCert. -func (mr *MockfetchLogicMockRecorder) GetCert(arg0, arg1, arg2, arg3 interface{}) *fetchLogicGetCertCall { +func (mr *MockfetchLogicMockRecorder) GetCert(arg0, arg1, arg2, arg3 any) *fetchLogicGetCertCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCert", reflect.TypeOf((*MockfetchLogic)(nil).GetCert), arg0, arg1, arg2, arg3) return &fetchLogicGetCertCall{Call: call} @@ -382,7 +385,7 @@ func (m *MockfetchLogic) GetEpochATXs(arg0 context.Context, arg1 types.EpochID) } // GetEpochATXs indicates an expected call of GetEpochATXs. -func (mr *MockfetchLogicMockRecorder) GetEpochATXs(arg0, arg1 interface{}) *fetchLogicGetEpochATXsCall { +func (mr *MockfetchLogicMockRecorder) GetEpochATXs(arg0, arg1 any) *fetchLogicGetEpochATXsCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEpochATXs", reflect.TypeOf((*MockfetchLogic)(nil).GetEpochATXs), arg0, arg1) return &fetchLogicGetEpochATXsCall{Call: call} @@ -420,7 +423,7 @@ func (m *MockfetchLogic) GetLayerData(arg0 context.Context, arg1 []p2p.Peer, arg } // GetLayerData indicates an expected call of GetLayerData. -func (mr *MockfetchLogicMockRecorder) GetLayerData(arg0, arg1, arg2, arg3, arg4 interface{}) *fetchLogicGetLayerDataCall { +func (mr *MockfetchLogicMockRecorder) GetLayerData(arg0, arg1, arg2, arg3, arg4 any) *fetchLogicGetLayerDataCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLayerData", reflect.TypeOf((*MockfetchLogic)(nil).GetLayerData), arg0, arg1, arg2, arg3, arg4) return &fetchLogicGetLayerDataCall{Call: call} @@ -458,7 +461,7 @@ func (m *MockfetchLogic) GetLayerOpinions(arg0 context.Context, arg1 []p2p.Peer, } // GetLayerOpinions indicates an expected call of GetLayerOpinions. -func (mr *MockfetchLogicMockRecorder) GetLayerOpinions(arg0, arg1, arg2, arg3, arg4 interface{}) *fetchLogicGetLayerOpinionsCall { +func (mr *MockfetchLogicMockRecorder) GetLayerOpinions(arg0, arg1, arg2, arg3, arg4 any) *fetchLogicGetLayerOpinionsCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLayerOpinions", reflect.TypeOf((*MockfetchLogic)(nil).GetLayerOpinions), arg0, arg1, arg2, arg3, arg4) return &fetchLogicGetLayerOpinionsCall{Call: call} @@ -487,44 +490,6 @@ func (c *fetchLogicGetLayerOpinionsCall) DoAndReturn(f func(context.Context, []p return c } -// GetLayerOpinions2 mocks base method. -func (m *MockfetchLogic) GetLayerOpinions2(arg0 context.Context, arg1 []p2p.Peer, arg2 types.LayerID, arg3 func([]byte, p2p.Peer), arg4 func(error, p2p.Peer)) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetLayerOpinions2", arg0, arg1, arg2, arg3, arg4) - ret0, _ := ret[0].(error) - return ret0 -} - -// GetLayerOpinions2 indicates an expected call of GetLayerOpinions2. -func (mr *MockfetchLogicMockRecorder) GetLayerOpinions2(arg0, arg1, arg2, arg3, arg4 interface{}) *fetchLogicGetLayerOpinions2Call { - mr.mock.ctrl.T.Helper() - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLayerOpinions2", reflect.TypeOf((*MockfetchLogic)(nil).GetLayerOpinions2), arg0, arg1, arg2, arg3, arg4) - return &fetchLogicGetLayerOpinions2Call{Call: call} -} - -// fetchLogicGetLayerOpinions2Call wrap *gomock.Call -type fetchLogicGetLayerOpinions2Call struct { - *gomock.Call -} - -// Return rewrite *gomock.Call.Return -func (c *fetchLogicGetLayerOpinions2Call) Return(arg0 error) *fetchLogicGetLayerOpinions2Call { - c.Call = c.Call.Return(arg0) - return c -} - -// Do rewrite *gomock.Call.Do -func (c *fetchLogicGetLayerOpinions2Call) Do(f func(context.Context, []p2p.Peer, types.LayerID, func([]byte, p2p.Peer), func(error, p2p.Peer)) error) *fetchLogicGetLayerOpinions2Call { - c.Call = c.Call.Do(f) - return c -} - -// DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *fetchLogicGetLayerOpinions2Call) DoAndReturn(f func(context.Context, []p2p.Peer, types.LayerID, func([]byte, p2p.Peer), func(error, p2p.Peer)) error) *fetchLogicGetLayerOpinions2Call { - c.Call = c.Call.DoAndReturn(f) - return c -} - // GetMalfeasanceProofs mocks base method. func (m *MockfetchLogic) GetMalfeasanceProofs(arg0 context.Context, arg1 []types.NodeID) error { m.ctrl.T.Helper() @@ -534,7 +499,7 @@ func (m *MockfetchLogic) GetMalfeasanceProofs(arg0 context.Context, arg1 []types } // GetMalfeasanceProofs indicates an expected call of GetMalfeasanceProofs. -func (mr *MockfetchLogicMockRecorder) GetMalfeasanceProofs(arg0, arg1 interface{}) *fetchLogicGetMalfeasanceProofsCall { +func (mr *MockfetchLogicMockRecorder) GetMalfeasanceProofs(arg0, arg1 any) *fetchLogicGetMalfeasanceProofsCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMalfeasanceProofs", reflect.TypeOf((*MockfetchLogic)(nil).GetMalfeasanceProofs), arg0, arg1) return &fetchLogicGetMalfeasanceProofsCall{Call: call} @@ -572,7 +537,7 @@ func (m *MockfetchLogic) GetMaliciousIDs(arg0 context.Context, arg1 []p2p.Peer, } // GetMaliciousIDs indicates an expected call of GetMaliciousIDs. -func (mr *MockfetchLogicMockRecorder) GetMaliciousIDs(arg0, arg1, arg2, arg3 interface{}) *fetchLogicGetMaliciousIDsCall { +func (mr *MockfetchLogicMockRecorder) GetMaliciousIDs(arg0, arg1, arg2, arg3 any) *fetchLogicGetMaliciousIDsCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMaliciousIDs", reflect.TypeOf((*MockfetchLogic)(nil).GetMaliciousIDs), arg0, arg1, arg2, arg3) return &fetchLogicGetMaliciousIDsCall{Call: call} @@ -649,7 +614,7 @@ func (m *MockfetchLogic) PeerEpochInfo(arg0 context.Context, arg1 p2p.Peer, arg2 } // PeerEpochInfo indicates an expected call of PeerEpochInfo. -func (mr *MockfetchLogicMockRecorder) PeerEpochInfo(arg0, arg1, arg2 interface{}) *fetchLogicPeerEpochInfoCall { +func (mr *MockfetchLogicMockRecorder) PeerEpochInfo(arg0, arg1, arg2 any) *fetchLogicPeerEpochInfoCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PeerEpochInfo", reflect.TypeOf((*MockfetchLogic)(nil).PeerEpochInfo), arg0, arg1, arg2) return &fetchLogicPeerEpochInfoCall{Call: call} @@ -688,7 +653,7 @@ func (m *MockfetchLogic) PeerMeshHashes(arg0 context.Context, arg1 p2p.Peer, arg } // PeerMeshHashes indicates an expected call of PeerMeshHashes. -func (mr *MockfetchLogicMockRecorder) PeerMeshHashes(arg0, arg1, arg2 interface{}) *fetchLogicPeerMeshHashesCall { +func (mr *MockfetchLogicMockRecorder) PeerMeshHashes(arg0, arg1, arg2 any) *fetchLogicPeerMeshHashesCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PeerMeshHashes", reflect.TypeOf((*MockfetchLogic)(nil).PeerMeshHashes), arg0, arg1, arg2) return &fetchLogicPeerMeshHashesCall{Call: call} @@ -717,49 +682,10 @@ func (c *fetchLogicPeerMeshHashesCall) DoAndReturn(f func(context.Context, p2p.P return c } -// PeerProtocols mocks base method. -func (m *MockfetchLogic) PeerProtocols(arg0 p2p.Peer) ([]protocol.ID, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "PeerProtocols", arg0) - ret0, _ := ret[0].([]protocol.ID) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// PeerProtocols indicates an expected call of PeerProtocols. -func (mr *MockfetchLogicMockRecorder) PeerProtocols(arg0 interface{}) *fetchLogicPeerProtocolsCall { - mr.mock.ctrl.T.Helper() - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PeerProtocols", reflect.TypeOf((*MockfetchLogic)(nil).PeerProtocols), arg0) - return &fetchLogicPeerProtocolsCall{Call: call} -} - -// fetchLogicPeerProtocolsCall wrap *gomock.Call -type fetchLogicPeerProtocolsCall struct { - *gomock.Call -} - -// Return rewrite *gomock.Call.Return -func (c *fetchLogicPeerProtocolsCall) Return(arg0 []protocol.ID, arg1 error) *fetchLogicPeerProtocolsCall { - c.Call = c.Call.Return(arg0, arg1) - return c -} - -// Do rewrite *gomock.Call.Do -func (c *fetchLogicPeerProtocolsCall) Do(f func(p2p.Peer) ([]protocol.ID, error)) *fetchLogicPeerProtocolsCall { - c.Call = c.Call.Do(f) - return c -} - -// DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *fetchLogicPeerProtocolsCall) DoAndReturn(f func(p2p.Peer) ([]protocol.ID, error)) *fetchLogicPeerProtocolsCall { - c.Call = c.Call.DoAndReturn(f) - return c -} - // PollLayerData mocks base method. func (m *MockfetchLogic) PollLayerData(arg0 context.Context, arg1 types.LayerID, arg2 ...p2p.Peer) error { m.ctrl.T.Helper() - varargs := []interface{}{arg0, arg1} + varargs := []any{arg0, arg1} for _, a := range arg2 { varargs = append(varargs, a) } @@ -769,9 +695,9 @@ func (m *MockfetchLogic) PollLayerData(arg0 context.Context, arg1 types.LayerID, } // PollLayerData indicates an expected call of PollLayerData. -func (mr *MockfetchLogicMockRecorder) PollLayerData(arg0, arg1 interface{}, arg2 ...interface{}) *fetchLogicPollLayerDataCall { +func (mr *MockfetchLogicMockRecorder) PollLayerData(arg0, arg1 any, arg2 ...any) *fetchLogicPollLayerDataCall { mr.mock.ctrl.T.Helper() - varargs := append([]interface{}{arg0, arg1}, arg2...) + varargs := append([]any{arg0, arg1}, arg2...) call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PollLayerData", reflect.TypeOf((*MockfetchLogic)(nil).PollLayerData), varargs...) return &fetchLogicPollLayerDataCall{Call: call} } @@ -800,18 +726,19 @@ func (c *fetchLogicPollLayerDataCall) DoAndReturn(f func(context.Context, types. } // PollLayerOpinions mocks base method. -func (m *MockfetchLogic) PollLayerOpinions(arg0 context.Context, arg1 types.LayerID, arg2 []p2p.Peer) ([]*fetch.LayerOpinion, error) { +func (m *MockfetchLogic) PollLayerOpinions(arg0 context.Context, arg1 types.LayerID, arg2 bool, arg3 []p2p.Peer) ([]*fetch.LayerOpinion, []*types.Certificate, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "PollLayerOpinions", arg0, arg1, arg2) + ret := m.ctrl.Call(m, "PollLayerOpinions", arg0, arg1, arg2, arg3) ret0, _ := ret[0].([]*fetch.LayerOpinion) - ret1, _ := ret[1].(error) - return ret0, ret1 + ret1, _ := ret[1].([]*types.Certificate) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 } // PollLayerOpinions indicates an expected call of PollLayerOpinions. -func (mr *MockfetchLogicMockRecorder) PollLayerOpinions(arg0, arg1, arg2 interface{}) *fetchLogicPollLayerOpinionsCall { +func (mr *MockfetchLogicMockRecorder) PollLayerOpinions(arg0, arg1, arg2, arg3 any) *fetchLogicPollLayerOpinionsCall { mr.mock.ctrl.T.Helper() - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PollLayerOpinions", reflect.TypeOf((*MockfetchLogic)(nil).PollLayerOpinions), arg0, arg1, arg2) + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PollLayerOpinions", reflect.TypeOf((*MockfetchLogic)(nil).PollLayerOpinions), arg0, arg1, arg2, arg3) return &fetchLogicPollLayerOpinionsCall{Call: call} } @@ -821,59 +748,19 @@ type fetchLogicPollLayerOpinionsCall struct { } // Return rewrite *gomock.Call.Return -func (c *fetchLogicPollLayerOpinionsCall) Return(arg0 []*fetch.LayerOpinion, arg1 error) *fetchLogicPollLayerOpinionsCall { - c.Call = c.Call.Return(arg0, arg1) - return c -} - -// Do rewrite *gomock.Call.Do -func (c *fetchLogicPollLayerOpinionsCall) Do(f func(context.Context, types.LayerID, []p2p.Peer) ([]*fetch.LayerOpinion, error)) *fetchLogicPollLayerOpinionsCall { - c.Call = c.Call.Do(f) - return c -} - -// DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *fetchLogicPollLayerOpinionsCall) DoAndReturn(f func(context.Context, types.LayerID, []p2p.Peer) ([]*fetch.LayerOpinion, error)) *fetchLogicPollLayerOpinionsCall { - c.Call = c.Call.DoAndReturn(f) - return c -} - -// PollLayerOpinions2 mocks base method. -func (m *MockfetchLogic) PollLayerOpinions2(arg0 context.Context, arg1 types.LayerID, arg2 bool, arg3 []p2p.Peer) ([]*fetch.LayerOpinion2, []*types.Certificate, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "PollLayerOpinions2", arg0, arg1, arg2, arg3) - ret0, _ := ret[0].([]*fetch.LayerOpinion2) - ret1, _ := ret[1].([]*types.Certificate) - ret2, _ := ret[2].(error) - return ret0, ret1, ret2 -} - -// PollLayerOpinions2 indicates an expected call of PollLayerOpinions2. -func (mr *MockfetchLogicMockRecorder) PollLayerOpinions2(arg0, arg1, arg2, arg3 interface{}) *fetchLogicPollLayerOpinions2Call { - mr.mock.ctrl.T.Helper() - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PollLayerOpinions2", reflect.TypeOf((*MockfetchLogic)(nil).PollLayerOpinions2), arg0, arg1, arg2, arg3) - return &fetchLogicPollLayerOpinions2Call{Call: call} -} - -// fetchLogicPollLayerOpinions2Call wrap *gomock.Call -type fetchLogicPollLayerOpinions2Call struct { - *gomock.Call -} - -// Return rewrite *gomock.Call.Return -func (c *fetchLogicPollLayerOpinions2Call) Return(arg0 []*fetch.LayerOpinion2, arg1 []*types.Certificate, arg2 error) *fetchLogicPollLayerOpinions2Call { +func (c *fetchLogicPollLayerOpinionsCall) Return(arg0 []*fetch.LayerOpinion, arg1 []*types.Certificate, arg2 error) *fetchLogicPollLayerOpinionsCall { c.Call = c.Call.Return(arg0, arg1, arg2) return c } // Do rewrite *gomock.Call.Do -func (c *fetchLogicPollLayerOpinions2Call) Do(f func(context.Context, types.LayerID, bool, []p2p.Peer) ([]*fetch.LayerOpinion2, []*types.Certificate, error)) *fetchLogicPollLayerOpinions2Call { +func (c *fetchLogicPollLayerOpinionsCall) Do(f func(context.Context, types.LayerID, bool, []p2p.Peer) ([]*fetch.LayerOpinion, []*types.Certificate, error)) *fetchLogicPollLayerOpinionsCall { c.Call = c.Call.Do(f) return c } // DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *fetchLogicPollLayerOpinions2Call) DoAndReturn(f func(context.Context, types.LayerID, bool, []p2p.Peer) ([]*fetch.LayerOpinion2, []*types.Certificate, error)) *fetchLogicPollLayerOpinions2Call { +func (c *fetchLogicPollLayerOpinionsCall) DoAndReturn(f func(context.Context, types.LayerID, bool, []p2p.Peer) ([]*fetch.LayerOpinion, []*types.Certificate, error)) *fetchLogicPollLayerOpinionsCall { c.Call = c.Call.DoAndReturn(f) return c } @@ -887,7 +774,7 @@ func (m *MockfetchLogic) PollMaliciousProofs(ctx context.Context) error { } // PollMaliciousProofs indicates an expected call of PollMaliciousProofs. -func (mr *MockfetchLogicMockRecorder) PollMaliciousProofs(ctx interface{}) *fetchLogicPollMaliciousProofsCall { +func (mr *MockfetchLogicMockRecorder) PollMaliciousProofs(ctx any) *fetchLogicPollMaliciousProofsCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PollMaliciousProofs", reflect.TypeOf((*MockfetchLogic)(nil).PollMaliciousProofs), ctx) return &fetchLogicPollMaliciousProofsCall{Call: call} @@ -923,7 +810,7 @@ func (m *MockfetchLogic) RegisterPeerHashes(peer p2p.Peer, hashes []types.Hash32 } // RegisterPeerHashes indicates an expected call of RegisterPeerHashes. -func (mr *MockfetchLogicMockRecorder) RegisterPeerHashes(peer, hashes interface{}) *fetchLogicRegisterPeerHashesCall { +func (mr *MockfetchLogicMockRecorder) RegisterPeerHashes(peer, hashes any) *fetchLogicRegisterPeerHashesCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterPeerHashes", reflect.TypeOf((*MockfetchLogic)(nil).RegisterPeerHashes), peer, hashes) return &fetchLogicRegisterPeerHashesCall{Call: call} @@ -984,7 +871,7 @@ func (m *Mockfetcher) GetAtxs(arg0 context.Context, arg1 []types.ATXID) error { } // GetAtxs indicates an expected call of GetAtxs. -func (mr *MockfetcherMockRecorder) GetAtxs(arg0, arg1 interface{}) *fetcherGetAtxsCall { +func (mr *MockfetcherMockRecorder) GetAtxs(arg0, arg1 any) *fetcherGetAtxsCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAtxs", reflect.TypeOf((*Mockfetcher)(nil).GetAtxs), arg0, arg1) return &fetcherGetAtxsCall{Call: call} @@ -1022,7 +909,7 @@ func (m *Mockfetcher) GetBallots(arg0 context.Context, arg1 []types.BallotID) er } // GetBallots indicates an expected call of GetBallots. -func (mr *MockfetcherMockRecorder) GetBallots(arg0, arg1 interface{}) *fetcherGetBallotsCall { +func (mr *MockfetcherMockRecorder) GetBallots(arg0, arg1 any) *fetcherGetBallotsCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBallots", reflect.TypeOf((*Mockfetcher)(nil).GetBallots), arg0, arg1) return &fetcherGetBallotsCall{Call: call} @@ -1060,7 +947,7 @@ func (m *Mockfetcher) GetBlocks(arg0 context.Context, arg1 []types.BlockID) erro } // GetBlocks indicates an expected call of GetBlocks. -func (mr *MockfetcherMockRecorder) GetBlocks(arg0, arg1 interface{}) *fetcherGetBlocksCall { +func (mr *MockfetcherMockRecorder) GetBlocks(arg0, arg1 any) *fetcherGetBlocksCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlocks", reflect.TypeOf((*Mockfetcher)(nil).GetBlocks), arg0, arg1) return &fetcherGetBlocksCall{Call: call} @@ -1099,7 +986,7 @@ func (m *Mockfetcher) GetCert(arg0 context.Context, arg1 types.LayerID, arg2 typ } // GetCert indicates an expected call of GetCert. -func (mr *MockfetcherMockRecorder) GetCert(arg0, arg1, arg2, arg3 interface{}) *fetcherGetCertCall { +func (mr *MockfetcherMockRecorder) GetCert(arg0, arg1, arg2, arg3 any) *fetcherGetCertCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCert", reflect.TypeOf((*Mockfetcher)(nil).GetCert), arg0, arg1, arg2, arg3) return &fetcherGetCertCall{Call: call} @@ -1137,7 +1024,7 @@ func (m *Mockfetcher) GetLayerData(arg0 context.Context, arg1 []p2p.Peer, arg2 t } // GetLayerData indicates an expected call of GetLayerData. -func (mr *MockfetcherMockRecorder) GetLayerData(arg0, arg1, arg2, arg3, arg4 interface{}) *fetcherGetLayerDataCall { +func (mr *MockfetcherMockRecorder) GetLayerData(arg0, arg1, arg2, arg3, arg4 any) *fetcherGetLayerDataCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLayerData", reflect.TypeOf((*Mockfetcher)(nil).GetLayerData), arg0, arg1, arg2, arg3, arg4) return &fetcherGetLayerDataCall{Call: call} @@ -1175,7 +1062,7 @@ func (m *Mockfetcher) GetLayerOpinions(arg0 context.Context, arg1 []p2p.Peer, ar } // GetLayerOpinions indicates an expected call of GetLayerOpinions. -func (mr *MockfetcherMockRecorder) GetLayerOpinions(arg0, arg1, arg2, arg3, arg4 interface{}) *fetcherGetLayerOpinionsCall { +func (mr *MockfetcherMockRecorder) GetLayerOpinions(arg0, arg1, arg2, arg3, arg4 any) *fetcherGetLayerOpinionsCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLayerOpinions", reflect.TypeOf((*Mockfetcher)(nil).GetLayerOpinions), arg0, arg1, arg2, arg3, arg4) return &fetcherGetLayerOpinionsCall{Call: call} @@ -1204,44 +1091,6 @@ func (c *fetcherGetLayerOpinionsCall) DoAndReturn(f func(context.Context, []p2p. return c } -// GetLayerOpinions2 mocks base method. -func (m *Mockfetcher) GetLayerOpinions2(arg0 context.Context, arg1 []p2p.Peer, arg2 types.LayerID, arg3 func([]byte, p2p.Peer), arg4 func(error, p2p.Peer)) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetLayerOpinions2", arg0, arg1, arg2, arg3, arg4) - ret0, _ := ret[0].(error) - return ret0 -} - -// GetLayerOpinions2 indicates an expected call of GetLayerOpinions2. -func (mr *MockfetcherMockRecorder) GetLayerOpinions2(arg0, arg1, arg2, arg3, arg4 interface{}) *fetcherGetLayerOpinions2Call { - mr.mock.ctrl.T.Helper() - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLayerOpinions2", reflect.TypeOf((*Mockfetcher)(nil).GetLayerOpinions2), arg0, arg1, arg2, arg3, arg4) - return &fetcherGetLayerOpinions2Call{Call: call} -} - -// fetcherGetLayerOpinions2Call wrap *gomock.Call -type fetcherGetLayerOpinions2Call struct { - *gomock.Call -} - -// Return rewrite *gomock.Call.Return -func (c *fetcherGetLayerOpinions2Call) Return(arg0 error) *fetcherGetLayerOpinions2Call { - c.Call = c.Call.Return(arg0) - return c -} - -// Do rewrite *gomock.Call.Do -func (c *fetcherGetLayerOpinions2Call) Do(f func(context.Context, []p2p.Peer, types.LayerID, func([]byte, p2p.Peer), func(error, p2p.Peer)) error) *fetcherGetLayerOpinions2Call { - c.Call = c.Call.Do(f) - return c -} - -// DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *fetcherGetLayerOpinions2Call) DoAndReturn(f func(context.Context, []p2p.Peer, types.LayerID, func([]byte, p2p.Peer), func(error, p2p.Peer)) error) *fetcherGetLayerOpinions2Call { - c.Call = c.Call.DoAndReturn(f) - return c -} - // GetMalfeasanceProofs mocks base method. func (m *Mockfetcher) GetMalfeasanceProofs(arg0 context.Context, arg1 []types.NodeID) error { m.ctrl.T.Helper() @@ -1251,7 +1100,7 @@ func (m *Mockfetcher) GetMalfeasanceProofs(arg0 context.Context, arg1 []types.No } // GetMalfeasanceProofs indicates an expected call of GetMalfeasanceProofs. -func (mr *MockfetcherMockRecorder) GetMalfeasanceProofs(arg0, arg1 interface{}) *fetcherGetMalfeasanceProofsCall { +func (mr *MockfetcherMockRecorder) GetMalfeasanceProofs(arg0, arg1 any) *fetcherGetMalfeasanceProofsCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMalfeasanceProofs", reflect.TypeOf((*Mockfetcher)(nil).GetMalfeasanceProofs), arg0, arg1) return &fetcherGetMalfeasanceProofsCall{Call: call} @@ -1289,7 +1138,7 @@ func (m *Mockfetcher) GetMaliciousIDs(arg0 context.Context, arg1 []p2p.Peer, arg } // GetMaliciousIDs indicates an expected call of GetMaliciousIDs. -func (mr *MockfetcherMockRecorder) GetMaliciousIDs(arg0, arg1, arg2, arg3 interface{}) *fetcherGetMaliciousIDsCall { +func (mr *MockfetcherMockRecorder) GetMaliciousIDs(arg0, arg1, arg2, arg3 any) *fetcherGetMaliciousIDsCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMaliciousIDs", reflect.TypeOf((*Mockfetcher)(nil).GetMaliciousIDs), arg0, arg1, arg2, arg3) return &fetcherGetMaliciousIDsCall{Call: call} @@ -1366,7 +1215,7 @@ func (m *Mockfetcher) PeerEpochInfo(arg0 context.Context, arg1 p2p.Peer, arg2 ty } // PeerEpochInfo indicates an expected call of PeerEpochInfo. -func (mr *MockfetcherMockRecorder) PeerEpochInfo(arg0, arg1, arg2 interface{}) *fetcherPeerEpochInfoCall { +func (mr *MockfetcherMockRecorder) PeerEpochInfo(arg0, arg1, arg2 any) *fetcherPeerEpochInfoCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PeerEpochInfo", reflect.TypeOf((*Mockfetcher)(nil).PeerEpochInfo), arg0, arg1, arg2) return &fetcherPeerEpochInfoCall{Call: call} @@ -1405,7 +1254,7 @@ func (m *Mockfetcher) PeerMeshHashes(arg0 context.Context, arg1 p2p.Peer, arg2 * } // PeerMeshHashes indicates an expected call of PeerMeshHashes. -func (mr *MockfetcherMockRecorder) PeerMeshHashes(arg0, arg1, arg2 interface{}) *fetcherPeerMeshHashesCall { +func (mr *MockfetcherMockRecorder) PeerMeshHashes(arg0, arg1, arg2 any) *fetcherPeerMeshHashesCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PeerMeshHashes", reflect.TypeOf((*Mockfetcher)(nil).PeerMeshHashes), arg0, arg1, arg2) return &fetcherPeerMeshHashesCall{Call: call} @@ -1434,45 +1283,6 @@ func (c *fetcherPeerMeshHashesCall) DoAndReturn(f func(context.Context, p2p.Peer return c } -// PeerProtocols mocks base method. -func (m *Mockfetcher) PeerProtocols(arg0 p2p.Peer) ([]protocol.ID, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "PeerProtocols", arg0) - ret0, _ := ret[0].([]protocol.ID) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// PeerProtocols indicates an expected call of PeerProtocols. -func (mr *MockfetcherMockRecorder) PeerProtocols(arg0 interface{}) *fetcherPeerProtocolsCall { - mr.mock.ctrl.T.Helper() - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PeerProtocols", reflect.TypeOf((*Mockfetcher)(nil).PeerProtocols), arg0) - return &fetcherPeerProtocolsCall{Call: call} -} - -// fetcherPeerProtocolsCall wrap *gomock.Call -type fetcherPeerProtocolsCall struct { - *gomock.Call -} - -// Return rewrite *gomock.Call.Return -func (c *fetcherPeerProtocolsCall) Return(arg0 []protocol.ID, arg1 error) *fetcherPeerProtocolsCall { - c.Call = c.Call.Return(arg0, arg1) - return c -} - -// Do rewrite *gomock.Call.Do -func (c *fetcherPeerProtocolsCall) Do(f func(p2p.Peer) ([]protocol.ID, error)) *fetcherPeerProtocolsCall { - c.Call = c.Call.Do(f) - return c -} - -// DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *fetcherPeerProtocolsCall) DoAndReturn(f func(p2p.Peer) ([]protocol.ID, error)) *fetcherPeerProtocolsCall { - c.Call = c.Call.DoAndReturn(f) - return c -} - // RegisterPeerHashes mocks base method. func (m *Mockfetcher) RegisterPeerHashes(peer p2p.Peer, hashes []types.Hash32) { m.ctrl.T.Helper() @@ -1480,7 +1290,7 @@ func (m *Mockfetcher) RegisterPeerHashes(peer p2p.Peer, hashes []types.Hash32) { } // RegisterPeerHashes indicates an expected call of RegisterPeerHashes. -func (mr *MockfetcherMockRecorder) RegisterPeerHashes(peer, hashes interface{}) *fetcherRegisterPeerHashesCall { +func (mr *MockfetcherMockRecorder) RegisterPeerHashes(peer, hashes any) *fetcherRegisterPeerHashesCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterPeerHashes", reflect.TypeOf((*Mockfetcher)(nil).RegisterPeerHashes), peer, hashes) return &fetcherRegisterPeerHashesCall{Call: call} @@ -1541,7 +1351,7 @@ func (m *MocklayerPatrol) IsHareInCharge(arg0 types.LayerID) bool { } // IsHareInCharge indicates an expected call of IsHareInCharge. -func (mr *MocklayerPatrolMockRecorder) IsHareInCharge(arg0 interface{}) *layerPatrolIsHareInChargeCall { +func (mr *MocklayerPatrolMockRecorder) IsHareInCharge(arg0 any) *layerPatrolIsHareInChargeCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsHareInCharge", reflect.TypeOf((*MocklayerPatrol)(nil).IsHareInCharge), arg0) return &layerPatrolIsHareInChargeCall{Call: call} @@ -1602,7 +1412,7 @@ func (m *MockcertHandler) HandleSyncedCertificate(arg0 context.Context, arg1 typ } // HandleSyncedCertificate indicates an expected call of HandleSyncedCertificate. -func (mr *MockcertHandlerMockRecorder) HandleSyncedCertificate(arg0, arg1, arg2 interface{}) *certHandlerHandleSyncedCertificateCall { +func (mr *MockcertHandlerMockRecorder) HandleSyncedCertificate(arg0, arg1, arg2 any) *certHandlerHandleSyncedCertificateCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HandleSyncedCertificate", reflect.TypeOf((*MockcertHandler)(nil).HandleSyncedCertificate), arg0, arg1, arg2) return &certHandlerHandleSyncedCertificateCall{Call: call} @@ -1661,7 +1471,7 @@ func (m *MockforkFinder) AddResynced(arg0 types.LayerID, arg1 types.Hash32) { } // AddResynced indicates an expected call of AddResynced. -func (mr *MockforkFinderMockRecorder) AddResynced(arg0, arg1 interface{}) *forkFinderAddResyncedCall { +func (mr *MockforkFinderMockRecorder) AddResynced(arg0, arg1 any) *forkFinderAddResyncedCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddResynced", reflect.TypeOf((*MockforkFinder)(nil).AddResynced), arg0, arg1) return &forkFinderAddResyncedCall{Call: call} @@ -1700,7 +1510,7 @@ func (m *MockforkFinder) FindFork(arg0 context.Context, arg1 p2p.Peer, arg2 type } // FindFork indicates an expected call of FindFork. -func (mr *MockforkFinderMockRecorder) FindFork(arg0, arg1, arg2, arg3 interface{}) *forkFinderFindForkCall { +func (mr *MockforkFinderMockRecorder) FindFork(arg0, arg1, arg2, arg3 any) *forkFinderFindForkCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindFork", reflect.TypeOf((*MockforkFinder)(nil).FindFork), arg0, arg1, arg2, arg3) return &forkFinderFindForkCall{Call: call} @@ -1738,7 +1548,7 @@ func (m *MockforkFinder) NeedResync(arg0 types.LayerID, arg1 types.Hash32) bool } // NeedResync indicates an expected call of NeedResync. -func (mr *MockforkFinderMockRecorder) NeedResync(arg0, arg1 interface{}) *forkFinderNeedResyncCall { +func (mr *MockforkFinderMockRecorder) NeedResync(arg0, arg1 any) *forkFinderNeedResyncCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NeedResync", reflect.TypeOf((*MockforkFinder)(nil).NeedResync), arg0, arg1) return &forkFinderNeedResyncCall{Call: call} @@ -1770,7 +1580,7 @@ func (c *forkFinderNeedResyncCall) DoAndReturn(f func(types.LayerID, types.Hash3 // Purge mocks base method. func (m *MockforkFinder) Purge(arg0 bool, arg1 ...p2p.Peer) { m.ctrl.T.Helper() - varargs := []interface{}{arg0} + varargs := []any{arg0} for _, a := range arg1 { varargs = append(varargs, a) } @@ -1778,9 +1588,9 @@ func (m *MockforkFinder) Purge(arg0 bool, arg1 ...p2p.Peer) { } // Purge indicates an expected call of Purge. -func (mr *MockforkFinderMockRecorder) Purge(arg0 interface{}, arg1 ...interface{}) *forkFinderPurgeCall { +func (mr *MockforkFinderMockRecorder) Purge(arg0 any, arg1 ...any) *forkFinderPurgeCall { mr.mock.ctrl.T.Helper() - varargs := append([]interface{}{arg0}, arg1...) + varargs := append([]any{arg0}, arg1...) call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Purge", reflect.TypeOf((*MockforkFinder)(nil).Purge), varargs...) return &forkFinderPurgeCall{Call: call} } @@ -1815,7 +1625,7 @@ func (m *MockforkFinder) UpdateAgreement(arg0 p2p.Peer, arg1 types.LayerID, arg2 } // UpdateAgreement indicates an expected call of UpdateAgreement. -func (mr *MockforkFinderMockRecorder) UpdateAgreement(arg0, arg1, arg2, arg3 interface{}) *forkFinderUpdateAgreementCall { +func (mr *MockforkFinderMockRecorder) UpdateAgreement(arg0, arg1, arg2, arg3 any) *forkFinderUpdateAgreementCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateAgreement", reflect.TypeOf((*MockforkFinder)(nil).UpdateAgreement), arg0, arg1, arg2, arg3) return &forkFinderUpdateAgreementCall{Call: call} @@ -1877,7 +1687,7 @@ func (m *MockidProvider) IdentityExists(id types.NodeID) (bool, error) { } // IdentityExists indicates an expected call of IdentityExists. -func (mr *MockidProviderMockRecorder) IdentityExists(id interface{}) *idProviderIdentityExistsCall { +func (mr *MockidProviderMockRecorder) IdentityExists(id any) *idProviderIdentityExistsCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IdentityExists", reflect.TypeOf((*MockidProvider)(nil).IdentityExists), id) return &idProviderIdentityExistsCall{Call: call} diff --git a/syncer/state_syncer.go b/syncer/state_syncer.go index 8d263b44de..8ec2b8aa16 100644 --- a/syncer/state_syncer.go +++ b/syncer/state_syncer.go @@ -142,68 +142,12 @@ func (s *Syncer) layerOpinions(ctx context.Context, lid types.LayerID) ([]*peerO return nil, nil, errNoPeers } - if !s.cfg.UseNewProtocol { - return s.fetchOpinions(ctx, lid, peers) - } - - remaining := make(map[p2p.Peer]struct{}, len(peers)) - v2peers := make([]p2p.Peer, 0, len(peers)) - for _, peer := range peers { - remaining[peer] = struct{}{} - if protocols, err := s.dataFetcher.PeerProtocols(peer); err == nil { - for _, p := range protocols { - if p == fetch.OpnProtocol { - v2peers = append(v2peers, peer) - break - } - } - } - } - if len(v2peers) == 0 { - return s.fetchOpinions(ctx, lid, peers) - } - - var ( - results []*peerOpinion - certs []*types.Certificate - err error - ) - results, certs, err = s.fetchOpinions2(ctx, lid, v2peers) - if err == nil { - if len(v2peers) == len(peers) { - return results, certs, nil - } - for _, p := range v2peers { - delete(remaining, p) - } - } - // number of v2 peers are not sufficient. - knownCerts := map[types.BlockID]struct{}{} - for _, cert := range certs { - knownCerts[cert.BlockID] = struct{}{} - } - v1peers := maps.Keys(remaining) - v1results, v1certs, err := s.fetchOpinions(ctx, lid, v1peers) - if err != nil { - return nil, nil, err - } - results = append(results, v1results...) - for _, cert := range v1certs { - if _, ok := knownCerts[cert.BlockID]; !ok { - knownCerts[cert.BlockID] = struct{}{} - certs = append(certs, cert) - } - } - return results, certs, nil -} - -func (s *Syncer) fetchOpinions2(ctx context.Context, lid types.LayerID, peers []p2p.Peer) ([]*peerOpinion, []*types.Certificate, error) { v2OpnPoll.Inc() needCert, err := s.needCert(ctx, lid) if err != nil { return nil, nil, err } - opinions, certs, err := s.dataFetcher.PollLayerOpinions2(ctx, lid, needCert, peers) + opinions, certs, err := s.dataFetcher.PollLayerOpinions(ctx, lid, needCert, peers) if err != nil { v2OpnErr.Inc() s.logger.WithContext(ctx).With().Debug("failed to fetch opinions2", @@ -225,38 +169,6 @@ func (s *Syncer) fetchOpinions2(ctx context.Context, lid types.LayerID, peers [] return result, certs, nil } -func (s *Syncer) fetchOpinions(ctx context.Context, lid types.LayerID, peers []p2p.Peer) ([]*peerOpinion, []*types.Certificate, error) { - v1OpnPoll.Inc() - opinions, err := s.dataFetcher.PollLayerOpinions(ctx, lid, peers) - if err != nil { - v1OpnErr.Inc() - s.logger.WithContext(ctx).With().Debug("failed to fetch opinions", - lid, - log.Int("peers", len(peers)), - log.Err(err), - ) - return nil, nil, fmt.Errorf("PollLayerOpinions: %w", err) - } - var ( - result = make([]*peerOpinion, 0, len(opinions)) - certs = map[types.BlockID]*types.Certificate{} - ) - for _, opn := range opinions { - result = append(result, &peerOpinion{ - prevAggHash: opn.PrevAggHash, - peer: opn.Peer(), - }) - if opn.Cert != nil { - certs[opn.Cert.BlockID] = opn.Cert - if opn.Cert.BlockID != types.EmptyBlockID { - s.dataFetcher.RegisterPeerHashes(opn.Peer(), []types.Hash32{opn.Cert.BlockID.AsHash32()}) - } - } - } - opinionLayer.Set(float64(lid)) - return result, maps.Values(certs), nil -} - func (s *Syncer) checkMeshAgreement(ctx context.Context, lid types.LayerID, opinions []*peerOpinion) error { prevHash, err := layers.GetAggregatedHash(s.cdb, lid.Sub(1)) if err != nil { diff --git a/syncer/state_syncer_test.go b/syncer/state_syncer_test.go index 843545a141..3a76d66b21 100644 --- a/syncer/state_syncer_test.go +++ b/syncer/state_syncer_test.go @@ -6,7 +6,6 @@ import ( "strconv" "testing" - "github.com/libp2p/go-libp2p/core/protocol" "github.com/libp2p/go-libp2p/p2p/host/peerstore/test" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" @@ -23,22 +22,8 @@ import ( ) func opinions(prevHash types.Hash32) []*fetch.LayerOpinion { - return []*fetch.LayerOpinion{ - { - PrevAggHash: prevHash, - }, - { - PrevAggHash: prevHash, - Cert: &types.Certificate{ - BlockID: types.RandomBlockID(), - }, - }, - } -} - -func opinions2(prevHash types.Hash32) []*fetch.LayerOpinion2 { bid := types.RandomBlockID() - return []*fetch.LayerOpinion2{ + return []*fetch.LayerOpinion{ { PrevAggHash: prevHash, }, @@ -60,76 +45,17 @@ func TestProcessLayers_MultiLayers(t *testing.T) { peers := test.GeneratePeerIDs(3) ts.mDataFetcher.EXPECT().GetPeers().Return(peers).AnyTimes() - ts.mDataFetcher.EXPECT().PeerProtocols(gomock.Any()).Return([]protocol.ID{}, nil).AnyTimes() ts.mForkFinder.EXPECT().UpdateAgreement(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() adopted := make(map[types.LayerID]types.BlockID) for lid := gLid.Add(1); lid.Before(current); lid = lid.Add(1) { lid := lid ts.mLyrPatrol.EXPECT().IsHareInCharge(lid).Return(false) - ts.mDataFetcher.EXPECT().PollLayerOpinions(gomock.Any(), lid, peers).DoAndReturn( - func(context.Context, types.LayerID, []p2p.Peer) ([]*fetch.LayerOpinion, error) { + ts.mDataFetcher.EXPECT().PollLayerOpinions(gomock.Any(), lid, true, peers).DoAndReturn( + func(context.Context, types.LayerID, bool, []p2p.Peer) ([]*fetch.LayerOpinion, []*types.Certificate, error) { prevLid := lid.Sub(1) prevHash, err := layers.GetAggregatedHash(ts.cdb, prevLid) require.NoError(t, err) opns := opinions(prevHash) - adopted[lid] = opns[1].Cert.BlockID - return opns, nil - }) - ts.mDataFetcher.EXPECT().RegisterPeerHashes(gomock.Any(), gomock.Any()) - ts.mDataFetcher.EXPECT().GetBlocks(gomock.Any(), gomock.Any()).DoAndReturn( - func(_ context.Context, got []types.BlockID) error { - require.Equal(t, []types.BlockID{adopted[lid]}, got) - for _, bid := range got { - require.NoError(t, blocks.Add(ts.cdb, types.NewExistingBlock(bid, types.InnerBlock{LayerIndex: lid}))) - } - return nil - }) - ts.mCertHdr.EXPECT().HandleSyncedCertificate(gomock.Any(), lid, gomock.Any()).DoAndReturn( - func(_ context.Context, _ types.LayerID, gotC *types.Certificate) error { - require.Equal(t, adopted[lid], gotC.BlockID) - require.NoError(t, certificates.Add(ts.cdb, lid, gotC)) - return nil - }) - ts.mTortoise.EXPECT().TallyVotes(gomock.Any(), lid) - ts.mTortoise.EXPECT().Updates().DoAndReturn(func() []result.Layer { - return fixture.RLayers(fixture.RLayer(lid, fixture.RBlock(adopted[lid], fixture.Good()))) - }) - ts.mVm.EXPECT().Apply(gomock.Any(), gomock.Any(), gomock.Any()) - ts.mConState.EXPECT().UpdateCache(gomock.Any(), lid, gomock.Any(), nil, nil).DoAndReturn( - func(_ context.Context, _ types.LayerID, got types.BlockID, _ []types.TransactionWithResult, _ []types.Transaction) error { - require.Equal(t, adopted[lid], got) - return nil - }) - ts.mVm.EXPECT().GetStateRoot() - } - require.False(t, ts.syncer.stateSynced()) - require.NoError(t, ts.syncer.processLayers(context.Background())) - require.True(t, ts.syncer.stateSynced()) -} - -func TestProcessLayers_MultiLayers_NewOpinionsProtocol(t *testing.T) { - gLid := types.GetEffectiveGenesis() - ts := newTestSyncerForState(t) - ts.syncer.cfg.SyncCertDistance = 10000 - ts.syncer.setATXSynced() - current := gLid.Add(10) - ts.syncer.setLastSyncedLayer(current.Sub(1)) - ts.mTicker.advanceToLayer(current) - - peers := test.GeneratePeerIDs(3) - ts.mDataFetcher.EXPECT().GetPeers().Return(peers).AnyTimes() - ts.mDataFetcher.EXPECT().PeerProtocols(gomock.Any()).Return([]protocol.ID{fetch.OpnProtocol}, nil).AnyTimes() - ts.mForkFinder.EXPECT().UpdateAgreement(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() - adopted := make(map[types.LayerID]types.BlockID) - for lid := gLid.Add(1); lid.Before(current); lid = lid.Add(1) { - lid := lid - ts.mLyrPatrol.EXPECT().IsHareInCharge(lid).Return(false) - ts.mDataFetcher.EXPECT().PollLayerOpinions2(gomock.Any(), lid, true, peers).DoAndReturn( - func(context.Context, types.LayerID, bool, []p2p.Peer) ([]*fetch.LayerOpinion2, []*types.Certificate, error) { - prevLid := lid.Sub(1) - prevHash, err := layers.GetAggregatedHash(ts.cdb, prevLid) - require.NoError(t, err) - opns := opinions2(prevHash) adopted[lid] = *opns[1].Certified return opns, []*types.Certificate{{BlockID: *opns[1].Certified}}, nil }) @@ -164,118 +90,15 @@ func TestProcessLayers_MultiLayers_NewOpinionsProtocol(t *testing.T) { require.True(t, ts.syncer.stateSynced()) } -func TestProcessLayers_MixedOpinionProtocol(t *testing.T) { - gLid := types.GetEffectiveGenesis() - lid := gLid.Add(1) - bids := []types.BlockID{types.RandomBlockID(), types.RandomBlockID()} - const numPeers = 4 - prevHash := types.RandomHash() - tt := []struct { - name string - opns []*fetch.LayerOpinion - opns2 []*fetch.LayerOpinion2 - certs2 []*types.Certificate - numCerts int - disableNewSync bool - }{ - { - name: "both versions", - opns2: []*fetch.LayerOpinion2{ - {PrevAggHash: prevHash, Certified: &bids[1]}, - }, - certs2: []*types.Certificate{ - {BlockID: bids[1]}, - }, - opns: []*fetch.LayerOpinion{ - {PrevAggHash: prevHash, Cert: &types.Certificate{BlockID: bids[0]}}, - {PrevAggHash: prevHash, Cert: &types.Certificate{BlockID: bids[1]}}, - {PrevAggHash: prevHash, Cert: &types.Certificate{BlockID: bids[0]}}, - }, - numCerts: 2, - }, - { - name: "v2 disabled", - opns: []*fetch.LayerOpinion{ - {PrevAggHash: prevHash, Cert: &types.Certificate{BlockID: bids[0]}}, - {PrevAggHash: prevHash, Cert: &types.Certificate{BlockID: bids[0]}}, - {PrevAggHash: prevHash, Cert: &types.Certificate{BlockID: bids[0]}}, - {PrevAggHash: prevHash, Cert: &types.Certificate{BlockID: bids[0]}}, - }, - numCerts: 1, - disableNewSync: true, - }, - { - name: "v1 only", - opns: []*fetch.LayerOpinion{ - {PrevAggHash: prevHash, Cert: &types.Certificate{BlockID: bids[0]}}, - {PrevAggHash: prevHash, Cert: &types.Certificate{BlockID: bids[0]}}, - {PrevAggHash: prevHash, Cert: &types.Certificate{BlockID: bids[1]}}, - {PrevAggHash: prevHash, Cert: &types.Certificate{BlockID: bids[0]}}, - }, - numCerts: 2, - }, - { - name: "v2 only", - opns2: []*fetch.LayerOpinion2{ - {PrevAggHash: prevHash, Certified: &bids[0]}, - {PrevAggHash: prevHash, Certified: &bids[0]}, - {PrevAggHash: prevHash, Certified: &bids[1]}, - {PrevAggHash: prevHash, Certified: &bids[1]}, - }, - certs2: []*types.Certificate{ - {BlockID: bids[0]}, - {BlockID: bids[1]}, - }, - numCerts: 2, - }, - } - for _, tc := range tt { - tc := tc - t.Run(tc.name, func(t *testing.T) { - ts := newTestSyncerForState(t) - ts.syncer.cfg.UseNewProtocol = !tc.disableNewSync - ts.syncer.cfg.SyncCertDistance = 10000 - ts.mTicker.advanceToLayer(lid) - peers := test.GeneratePeerIDs(numPeers) - ts.mDataFetcher.EXPECT().GetPeers().Return(peers).AnyTimes() - numV2 := len(tc.opns2) - for i, p := range peers { - if i < numV2 { - ts.mDataFetcher.EXPECT().PeerProtocols(p).Return([]protocol.ID{fetch.OpnProtocol}, nil).AnyTimes() - } else { - ts.mDataFetcher.EXPECT().PeerProtocols(p).Return([]protocol.ID{}, nil).AnyTimes() - } - } - if len(tc.opns2) > 0 { - ts.mDataFetcher.EXPECT().PollLayerOpinions2(gomock.Any(), lid, true, gomock.Any()).DoAndReturn( - func(_ context.Context, _ types.LayerID, _ bool, got []p2p.Peer) ([]*fetch.LayerOpinion2, []*types.Certificate, error) { - require.ElementsMatch(t, peers[:len(tc.opns2)], got) - return tc.opns2, tc.certs2, nil - }) - } - if len(tc.opns) > 0 { - ts.mDataFetcher.EXPECT().PollLayerOpinions(gomock.Any(), lid, gomock.Any()).DoAndReturn( - func(_ context.Context, _ types.LayerID, got []p2p.Peer) ([]*fetch.LayerOpinion, error) { - require.ElementsMatch(t, peers[len(tc.opns2):], got) - return tc.opns, nil - }) - } - ts.mDataFetcher.EXPECT().RegisterPeerHashes(gomock.Any(), gomock.Any()).AnyTimes() - opns, certs, err := ts.syncer.layerOpinions(context.Background(), lid) - require.Len(t, opns, len(peers)) - require.Len(t, certs, tc.numCerts) - require.NoError(t, err) - }) - } -} - func TestProcessLayers_OpinionsNotAdopted(t *testing.T) { gLid := types.GetEffectiveGenesis() - prevHash := types.RandomHash() lid := gLid.Add(1) + prevHash := types.RandomHash() + certBlock := types.RandomBlockID() tt := []struct { name string opns []*fetch.LayerOpinion + certs []*types.Certificate localCert types.BlockID certErr, fetchErr error }{ @@ -294,107 +117,6 @@ func TestProcessLayers_OpinionsNotAdopted(t *testing.T) { { name: "cert not accepted", opns: []*fetch.LayerOpinion{ - {PrevAggHash: prevHash}, - {PrevAggHash: prevHash, Cert: &types.Certificate{BlockID: types.RandomBlockID()}}, - }, - certErr: errors.New("meh"), - }, - { - name: "cert block failed fetching", - opns: []*fetch.LayerOpinion{ - {PrevAggHash: prevHash}, - {PrevAggHash: prevHash, Cert: &types.Certificate{BlockID: types.RandomBlockID()}}, - }, - fetchErr: errors.New("meh"), - }, - } - for _, tc := range tt { - tc := tc - t.Run(tc.name, func(t *testing.T) { - t.Parallel() - - ts := newTestSyncerForState(t) - require.NoError(t, layers.SetMeshHash(ts.cdb, gLid, prevHash)) - ts.syncer.setATXSynced() - current := lid.Add(1) - ts.syncer.setLastSyncedLayer(current.Sub(1)) - ts.mTicker.advanceToLayer(current) - peers := test.GeneratePeerIDs(3) - ts.mDataFetcher.EXPECT().GetPeers().Return(peers).AnyTimes() - ts.mDataFetcher.EXPECT().PeerProtocols(gomock.Any()).Return([]protocol.ID{}, nil).AnyTimes() - - hasCert := false - for _, opn := range tc.opns { - if opn.Cert != nil { - hasCert = true - } - } - - // saves opinions - if tc.localCert != types.EmptyBlockID { - require.NoError(t, blocks.Add(ts.cdb, types.NewExistingBlock(tc.localCert, types.InnerBlock{LayerIndex: lid}))) - require.NoError(t, certificates.Add(ts.cdb, lid, &types.Certificate{BlockID: tc.localCert})) - require.NoError(t, blocks.SetValid(ts.cdb, tc.localCert)) - ts.mVm.EXPECT().Apply(vm.ApplyContext{Layer: lid}, gomock.Any(), gomock.Any()) - ts.mConState.EXPECT().UpdateCache(gomock.Any(), lid, tc.localCert, nil, nil) - ts.mVm.EXPECT().GetStateRoot() - } else { - ts.mVm.EXPECT().Apply(vm.ApplyContext{Layer: lid}, nil, nil) - ts.mConState.EXPECT().UpdateCache(gomock.Any(), lid, types.EmptyBlockID, nil, nil) - ts.mVm.EXPECT().GetStateRoot() - } - ts.mLyrPatrol.EXPECT().IsHareInCharge(lid).Return(false) - ts.mDataFetcher.EXPECT().PollLayerOpinions(gomock.Any(), lid, peers).Return(tc.opns, nil) - ts.mDataFetcher.EXPECT().RegisterPeerHashes(gomock.Any(), gomock.Any()).MaxTimes(1) - if tc.localCert == types.EmptyBlockID && hasCert { - ts.mCertHdr.EXPECT().HandleSyncedCertificate(gomock.Any(), lid, tc.opns[1].Cert).Return(tc.certErr) - ts.mDataFetcher.EXPECT().GetBlocks(gomock.Any(), gomock.Any()).DoAndReturn( - func(_ context.Context, got []types.BlockID) error { - require.Equal(t, []types.BlockID{tc.opns[1].Cert.BlockID}, got) - return tc.fetchErr - }).MaxTimes(1) - } - ts.mTortoise.EXPECT().TallyVotes(gomock.Any(), lid) - results := fixture.RLayers(fixture.RLayer(lid)) - if tc.localCert != types.EmptyBlockID { - results = fixture.RLayers(fixture.RLayer(lid, fixture.RBlock(tc.localCert, fixture.Good()))) - } - ts.mTortoise.EXPECT().Updates().Return(results) - - require.False(t, ts.syncer.stateSynced()) - require.NoError(t, ts.syncer.processLayers(context.Background())) - require.True(t, ts.syncer.stateSynced()) - }) - } -} - -func TestProcessLayers_OpinionsNotAdopted_NewOpinionsProtocol(t *testing.T) { - gLid := types.GetEffectiveGenesis() - lid := gLid.Add(1) - prevHash := types.RandomHash() - certBlock := types.RandomBlockID() - tt := []struct { - name string - opns []*fetch.LayerOpinion2 - certs []*types.Certificate - localCert types.BlockID - certErr, fetchErr error - }{ - { - name: "node already has cert", - opns: opinions2(prevHash), - localCert: types.RandomBlockID(), - }, - { - name: "no certs available", - opns: []*fetch.LayerOpinion2{ - {PrevAggHash: prevHash}, - {PrevAggHash: prevHash}, - }, - }, - { - name: "cert not accepted", - opns: []*fetch.LayerOpinion2{ {PrevAggHash: prevHash}, {PrevAggHash: prevHash, Certified: &certBlock}, }, @@ -403,7 +125,7 @@ func TestProcessLayers_OpinionsNotAdopted_NewOpinionsProtocol(t *testing.T) { }, { name: "cert block failed fetching", - opns: []*fetch.LayerOpinion2{ + opns: []*fetch.LayerOpinion{ {PrevAggHash: prevHash}, {PrevAggHash: prevHash, Certified: &certBlock}, }, @@ -424,7 +146,6 @@ func TestProcessLayers_OpinionsNotAdopted_NewOpinionsProtocol(t *testing.T) { ts.mTicker.advanceToLayer(current) peers := test.GeneratePeerIDs(3) ts.mDataFetcher.EXPECT().GetPeers().Return(peers).AnyTimes() - ts.mDataFetcher.EXPECT().PeerProtocols(gomock.Any()).Return([]protocol.ID{fetch.OpnProtocol}, nil).AnyTimes() hasCert := false for _, opn := range tc.opns { @@ -447,7 +168,7 @@ func TestProcessLayers_OpinionsNotAdopted_NewOpinionsProtocol(t *testing.T) { ts.mVm.EXPECT().GetStateRoot() } ts.mLyrPatrol.EXPECT().IsHareInCharge(lid).Return(false) - ts.mDataFetcher.EXPECT().PollLayerOpinions2(gomock.Any(), lid, tc.localCert == types.EmptyBlockID, peers).Return(tc.opns, tc.certs, nil) + ts.mDataFetcher.EXPECT().PollLayerOpinions(gomock.Any(), lid, tc.localCert == types.EmptyBlockID, peers).Return(tc.opns, tc.certs, nil) ts.mDataFetcher.EXPECT().RegisterPeerHashes(gomock.Any(), gomock.Any()).MaxTimes(1) if tc.localCert == types.EmptyBlockID && hasCert { ts.mCertHdr.EXPECT().HandleSyncedCertificate(gomock.Any(), lid, tc.certs[0]).Return(tc.certErr) @@ -511,8 +232,7 @@ func TestProcessLayers_HareIsStillWorking(t *testing.T) { ts.mLyrPatrol.EXPECT().IsHareInCharge(lastSynced).Return(false) peers := test.GeneratePeerIDs(3) ts.mDataFetcher.EXPECT().GetPeers().Return(peers) - ts.mDataFetcher.EXPECT().PeerProtocols(gomock.Any()).Return([]protocol.ID{}, nil).Times(len(peers)) - ts.mDataFetcher.EXPECT().PollLayerOpinions(gomock.Any(), lastSynced, peers).Return(nil, nil) + ts.mDataFetcher.EXPECT().PollLayerOpinions(gomock.Any(), lastSynced, true, peers).Return(nil, nil, nil) ts.mTortoise.EXPECT().TallyVotes(gomock.Any(), lastSynced) ts.mTortoise.EXPECT().Updates().Return(fixture.RLayers(fixture.RLayer(lastSynced))) ts.mVm.EXPECT().Apply(gomock.Any(), nil, nil) @@ -538,8 +258,7 @@ func TestProcessLayers_HareTakesTooLong(t *testing.T) { } peers := test.GeneratePeerIDs(3) ts.mDataFetcher.EXPECT().GetPeers().Return(peers) - ts.mDataFetcher.EXPECT().PeerProtocols(gomock.Any()).Return([]protocol.ID{}, nil).Times(len(peers)) - ts.mDataFetcher.EXPECT().PollLayerOpinions(gomock.Any(), lid, peers).Return(nil, nil) + ts.mDataFetcher.EXPECT().PollLayerOpinions(gomock.Any(), lid, gomock.Any(), peers).Return(nil, nil, nil) ts.mTortoise.EXPECT().TallyVotes(gomock.Any(), lid) ts.mTortoise.EXPECT().Updates().Return(fixture.RLayers(fixture.RLayer(lid))) ts.mVm.EXPECT().Apply(vm.ApplyContext{Layer: lid}, nil, nil) @@ -559,8 +278,7 @@ func TestProcessLayers_OpinionsOptional(t *testing.T) { ts.mLyrPatrol.EXPECT().IsHareInCharge(lastSynced).Return(false) peers := test.GeneratePeerIDs(5) ts.mDataFetcher.EXPECT().GetPeers().Return(peers) - ts.mDataFetcher.EXPECT().PeerProtocols(gomock.Any()).Return([]protocol.ID{}, nil).AnyTimes() - ts.mDataFetcher.EXPECT().PollLayerOpinions(gomock.Any(), lastSynced, peers).Return(nil, errors.New("meh")) + ts.mDataFetcher.EXPECT().PollLayerOpinions(gomock.Any(), lastSynced, true, peers).Return(nil, nil, errors.New("meh")) ts.mTortoise.EXPECT().TallyVotes(gomock.Any(), lastSynced) ts.mTortoise.EXPECT().Updates().Return(fixture.RLayers(fixture.RLayer(lastSynced))) require.False(t, ts.syncer.stateSynced()) @@ -617,8 +335,7 @@ func TestProcessLayers_MeshHashDiverged(t *testing.T) { ts.mLyrPatrol.EXPECT().IsHareInCharge(instate).Return(false) peers := test.GeneratePeerIDs(3) ts.mDataFetcher.EXPECT().GetPeers().Return(peers) - ts.mDataFetcher.EXPECT().PeerProtocols(gomock.Any()).Return([]protocol.ID{}, nil).Times(len(peers)) - ts.mDataFetcher.EXPECT().PollLayerOpinions(gomock.Any(), instate, peers).Return(opns, nil) + ts.mDataFetcher.EXPECT().PollLayerOpinions(gomock.Any(), instate, false, peers).Return(opns, nil, nil) ts.mForkFinder.EXPECT().UpdateAgreement(opns[1].Peer(), instate.Sub(1), prevHash, gomock.Any()) for i := 0; i < numPeers; i++ { if i == 1 { @@ -715,8 +432,7 @@ func TestProcessLayers_NoHashResolutionForNewlySyncedNode(t *testing.T) { ts.mLyrPatrol.EXPECT().IsHareInCharge(lid) peers := test.GeneratePeerIDs(3) ts.mDataFetcher.EXPECT().GetPeers().Return(peers) - ts.mDataFetcher.EXPECT().PeerProtocols(gomock.Any()).Return([]protocol.ID{}, nil).Times(len(peers)) - ts.mDataFetcher.EXPECT().PollLayerOpinions(gomock.Any(), lid, peers).Return(opns, nil) + ts.mDataFetcher.EXPECT().PollLayerOpinions(gomock.Any(), lid, gomock.Any(), peers).Return(opns, nil, nil) ts.mTortoise.EXPECT().TallyVotes(gomock.Any(), lid) ts.mTortoise.EXPECT().Updates().Return(fixture.RLayers(fixture.ROpinion(lid.Sub(1), opns[2].PrevAggHash))) if lid != instate && lid != current { diff --git a/syncer/syncer.go b/syncer/syncer.go index 96258158fe..c840e69db9 100644 --- a/syncer/syncer.go +++ b/syncer/syncer.go @@ -27,7 +27,6 @@ type Config struct { SyncCertDistance uint32 MaxStaleDuration time.Duration Standalone bool - UseNewProtocol bool `mapstructure:"use-new-opn"` GossipDuration time.Duration } @@ -39,7 +38,6 @@ func DefaultConfig() Config { HareDelayLayers: 10, SyncCertDistance: 10, MaxStaleDuration: time.Second, - UseNewProtocol: true, GossipDuration: 15 * time.Second, } } diff --git a/syncer/syncer_test.go b/syncer/syncer_test.go index bbce3f1d7b..bd2d36c81a 100644 --- a/syncer/syncer_test.go +++ b/syncer/syncer_test.go @@ -9,14 +9,12 @@ import ( "testing" "time" - "github.com/libp2p/go-libp2p/core/protocol" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "github.com/spacemeshos/go-spacemesh/common/fixture" "github.com/spacemeshos/go-spacemesh/common/types" "github.com/spacemeshos/go-spacemesh/datastore" - "github.com/spacemeshos/go-spacemesh/fetch" "github.com/spacemeshos/go-spacemesh/log/logtest" "github.com/spacemeshos/go-spacemesh/mesh" mmocks "github.com/spacemeshos/go-spacemesh/mesh/mocks" @@ -100,7 +98,6 @@ func newTestSyncer(t *testing.T, interval time.Duration) *testSyncer { EpochEndFraction: 0.66, SyncCertDistance: 4, HareDelayLayers: 5, - UseNewProtocol: true, } ts.syncer = NewSyncer(ts.cdb, ts.mTicker, ts.mBeacon, ts.msh, nil, nil, ts.mLyrPatrol, ts.mCertHdr, WithConfig(cfg), @@ -189,8 +186,7 @@ func advanceState(t testing.TB, ts *testSyncer, from, to types.LayerID) { for lid := from; lid <= to; lid++ { require.NoError(t, certificates.Add(ts.cdb, lid, &types.Certificate{BlockID: types.EmptyBlockID})) ts.mLyrPatrol.EXPECT().IsHareInCharge(lid) - ts.mDataFetcher.EXPECT().PeerProtocols(gomock.Any()).Return([]protocol.ID{fetch.OpnProtocol}, nil) - ts.mDataFetcher.EXPECT().PollLayerOpinions2(gomock.Any(), lid, false, gomock.Any()) + ts.mDataFetcher.EXPECT().PollLayerOpinions(gomock.Any(), lid, false, gomock.Any()) ts.mTortoise.EXPECT().TallyVotes(gomock.Any(), lid) ts.mTortoise.EXPECT().Updates().Return(fixture.RLayers(fixture.RLayer(lid))) ts.mVm.EXPECT().Apply(gomock.Any(), gomock.Any(), gomock.Any()) diff --git a/system/mocks/beacons.go b/system/mocks/beacons.go index adc11eec0b..a64810e27e 100644 --- a/system/mocks/beacons.go +++ b/system/mocks/beacons.go @@ -1,6 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: ./beacons.go - +// +// Generated by this command: +// +// mockgen -typed -package=mocks -destination=./mocks/beacons.go -source=./beacons.go +// // Package mocks is a generated GoMock package. package mocks @@ -42,7 +46,7 @@ func (m *MockBeaconCollector) ReportBeaconFromBallot(arg0 types.EpochID, arg1 *t } // ReportBeaconFromBallot indicates an expected call of ReportBeaconFromBallot. -func (mr *MockBeaconCollectorMockRecorder) ReportBeaconFromBallot(arg0, arg1, arg2, arg3 interface{}) *BeaconCollectorReportBeaconFromBallotCall { +func (mr *MockBeaconCollectorMockRecorder) ReportBeaconFromBallot(arg0, arg1, arg2, arg3 any) *BeaconCollectorReportBeaconFromBallotCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReportBeaconFromBallot", reflect.TypeOf((*MockBeaconCollector)(nil).ReportBeaconFromBallot), arg0, arg1, arg2, arg3) return &BeaconCollectorReportBeaconFromBallotCall{Call: call} @@ -104,7 +108,7 @@ func (m *MockBeaconGetter) GetBeacon(arg0 types.EpochID) (types.Beacon, error) { } // GetBeacon indicates an expected call of GetBeacon. -func (mr *MockBeaconGetterMockRecorder) GetBeacon(arg0 interface{}) *BeaconGetterGetBeaconCall { +func (mr *MockBeaconGetterMockRecorder) GetBeacon(arg0 any) *BeaconGetterGetBeaconCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBeacon", reflect.TypeOf((*MockBeaconGetter)(nil).GetBeacon), arg0) return &BeaconGetterGetBeaconCall{Call: call} diff --git a/system/mocks/fetcher.go b/system/mocks/fetcher.go index 1e271c2c9d..224a5bf6ec 100644 --- a/system/mocks/fetcher.go +++ b/system/mocks/fetcher.go @@ -1,6 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: ./fetcher.go - +// +// Generated by this command: +// +// mockgen -typed -package=mocks -destination=./mocks/fetcher.go -source=./fetcher.go +// // Package mocks is a generated GoMock package. package mocks @@ -45,7 +49,7 @@ func (m *MockFetcher) GetActiveSet(arg0 context.Context, arg1 types.Hash32) erro } // GetActiveSet indicates an expected call of GetActiveSet. -func (mr *MockFetcherMockRecorder) GetActiveSet(arg0, arg1 interface{}) *FetcherGetActiveSetCall { +func (mr *MockFetcherMockRecorder) GetActiveSet(arg0, arg1 any) *FetcherGetActiveSetCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetActiveSet", reflect.TypeOf((*MockFetcher)(nil).GetActiveSet), arg0, arg1) return &FetcherGetActiveSetCall{Call: call} @@ -83,7 +87,7 @@ func (m *MockFetcher) GetAtxs(arg0 context.Context, arg1 []types.ATXID) error { } // GetAtxs indicates an expected call of GetAtxs. -func (mr *MockFetcherMockRecorder) GetAtxs(arg0, arg1 interface{}) *FetcherGetAtxsCall { +func (mr *MockFetcherMockRecorder) GetAtxs(arg0, arg1 any) *FetcherGetAtxsCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAtxs", reflect.TypeOf((*MockFetcher)(nil).GetAtxs), arg0, arg1) return &FetcherGetAtxsCall{Call: call} @@ -121,7 +125,7 @@ func (m *MockFetcher) GetBallots(arg0 context.Context, arg1 []types.BallotID) er } // GetBallots indicates an expected call of GetBallots. -func (mr *MockFetcherMockRecorder) GetBallots(arg0, arg1 interface{}) *FetcherGetBallotsCall { +func (mr *MockFetcherMockRecorder) GetBallots(arg0, arg1 any) *FetcherGetBallotsCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBallots", reflect.TypeOf((*MockFetcher)(nil).GetBallots), arg0, arg1) return &FetcherGetBallotsCall{Call: call} @@ -159,7 +163,7 @@ func (m *MockFetcher) GetBlockTxs(arg0 context.Context, arg1 []types.Transaction } // GetBlockTxs indicates an expected call of GetBlockTxs. -func (mr *MockFetcherMockRecorder) GetBlockTxs(arg0, arg1 interface{}) *FetcherGetBlockTxsCall { +func (mr *MockFetcherMockRecorder) GetBlockTxs(arg0, arg1 any) *FetcherGetBlockTxsCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlockTxs", reflect.TypeOf((*MockFetcher)(nil).GetBlockTxs), arg0, arg1) return &FetcherGetBlockTxsCall{Call: call} @@ -197,7 +201,7 @@ func (m *MockFetcher) GetBlocks(arg0 context.Context, arg1 []types.BlockID) erro } // GetBlocks indicates an expected call of GetBlocks. -func (mr *MockFetcherMockRecorder) GetBlocks(arg0, arg1 interface{}) *FetcherGetBlocksCall { +func (mr *MockFetcherMockRecorder) GetBlocks(arg0, arg1 any) *FetcherGetBlocksCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlocks", reflect.TypeOf((*MockFetcher)(nil).GetBlocks), arg0, arg1) return &FetcherGetBlocksCall{Call: call} @@ -235,7 +239,7 @@ func (m *MockFetcher) GetPoetProof(arg0 context.Context, arg1 types.Hash32) erro } // GetPoetProof indicates an expected call of GetPoetProof. -func (mr *MockFetcherMockRecorder) GetPoetProof(arg0, arg1 interface{}) *FetcherGetPoetProofCall { +func (mr *MockFetcherMockRecorder) GetPoetProof(arg0, arg1 any) *FetcherGetPoetProofCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPoetProof", reflect.TypeOf((*MockFetcher)(nil).GetPoetProof), arg0, arg1) return &FetcherGetPoetProofCall{Call: call} @@ -273,7 +277,7 @@ func (m *MockFetcher) GetProposalTxs(arg0 context.Context, arg1 []types.Transact } // GetProposalTxs indicates an expected call of GetProposalTxs. -func (mr *MockFetcherMockRecorder) GetProposalTxs(arg0, arg1 interface{}) *FetcherGetProposalTxsCall { +func (mr *MockFetcherMockRecorder) GetProposalTxs(arg0, arg1 any) *FetcherGetProposalTxsCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetProposalTxs", reflect.TypeOf((*MockFetcher)(nil).GetProposalTxs), arg0, arg1) return &FetcherGetProposalTxsCall{Call: call} @@ -311,7 +315,7 @@ func (m *MockFetcher) GetProposals(arg0 context.Context, arg1 []types.ProposalID } // GetProposals indicates an expected call of GetProposals. -func (mr *MockFetcherMockRecorder) GetProposals(arg0, arg1 interface{}) *FetcherGetProposalsCall { +func (mr *MockFetcherMockRecorder) GetProposals(arg0, arg1 any) *FetcherGetProposalsCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetProposals", reflect.TypeOf((*MockFetcher)(nil).GetProposals), arg0, arg1) return &FetcherGetProposalsCall{Call: call} @@ -347,7 +351,7 @@ func (m *MockFetcher) RegisterPeerHashes(peer p2p.Peer, hashes []types.Hash32) { } // RegisterPeerHashes indicates an expected call of RegisterPeerHashes. -func (mr *MockFetcherMockRecorder) RegisterPeerHashes(peer, hashes interface{}) *FetcherRegisterPeerHashesCall { +func (mr *MockFetcherMockRecorder) RegisterPeerHashes(peer, hashes any) *FetcherRegisterPeerHashesCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterPeerHashes", reflect.TypeOf((*MockFetcher)(nil).RegisterPeerHashes), peer, hashes) return &FetcherRegisterPeerHashesCall{Call: call} @@ -408,7 +412,7 @@ func (m *MockBlockFetcher) GetBlocks(arg0 context.Context, arg1 []types.BlockID) } // GetBlocks indicates an expected call of GetBlocks. -func (mr *MockBlockFetcherMockRecorder) GetBlocks(arg0, arg1 interface{}) *BlockFetcherGetBlocksCall { +func (mr *MockBlockFetcherMockRecorder) GetBlocks(arg0, arg1 any) *BlockFetcherGetBlocksCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlocks", reflect.TypeOf((*MockBlockFetcher)(nil).GetBlocks), arg0, arg1) return &BlockFetcherGetBlocksCall{Call: call} @@ -469,7 +473,7 @@ func (m *MockAtxFetcher) GetAtxs(arg0 context.Context, arg1 []types.ATXID) error } // GetAtxs indicates an expected call of GetAtxs. -func (mr *MockAtxFetcherMockRecorder) GetAtxs(arg0, arg1 interface{}) *AtxFetcherGetAtxsCall { +func (mr *MockAtxFetcherMockRecorder) GetAtxs(arg0, arg1 any) *AtxFetcherGetAtxsCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAtxs", reflect.TypeOf((*MockAtxFetcher)(nil).GetAtxs), arg0, arg1) return &AtxFetcherGetAtxsCall{Call: call} @@ -530,7 +534,7 @@ func (m *MockTxFetcher) GetBlockTxs(arg0 context.Context, arg1 []types.Transacti } // GetBlockTxs indicates an expected call of GetBlockTxs. -func (mr *MockTxFetcherMockRecorder) GetBlockTxs(arg0, arg1 interface{}) *TxFetcherGetBlockTxsCall { +func (mr *MockTxFetcherMockRecorder) GetBlockTxs(arg0, arg1 any) *TxFetcherGetBlockTxsCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBlockTxs", reflect.TypeOf((*MockTxFetcher)(nil).GetBlockTxs), arg0, arg1) return &TxFetcherGetBlockTxsCall{Call: call} @@ -568,7 +572,7 @@ func (m *MockTxFetcher) GetProposalTxs(arg0 context.Context, arg1 []types.Transa } // GetProposalTxs indicates an expected call of GetProposalTxs. -func (mr *MockTxFetcherMockRecorder) GetProposalTxs(arg0, arg1 interface{}) *TxFetcherGetProposalTxsCall { +func (mr *MockTxFetcherMockRecorder) GetProposalTxs(arg0, arg1 any) *TxFetcherGetProposalTxsCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetProposalTxs", reflect.TypeOf((*MockTxFetcher)(nil).GetProposalTxs), arg0, arg1) return &TxFetcherGetProposalTxsCall{Call: call} @@ -629,7 +633,7 @@ func (m *MockPoetProofFetcher) GetPoetProof(arg0 context.Context, arg1 types.Has } // GetPoetProof indicates an expected call of GetPoetProof. -func (mr *MockPoetProofFetcherMockRecorder) GetPoetProof(arg0, arg1 interface{}) *PoetProofFetcherGetPoetProofCall { +func (mr *MockPoetProofFetcherMockRecorder) GetPoetProof(arg0, arg1 any) *PoetProofFetcherGetPoetProofCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPoetProof", reflect.TypeOf((*MockPoetProofFetcher)(nil).GetPoetProof), arg0, arg1) return &PoetProofFetcherGetPoetProofCall{Call: call} @@ -690,7 +694,7 @@ func (m *MockBallotFetcher) GetBallots(arg0 context.Context, arg1 []types.Ballot } // GetBallots indicates an expected call of GetBallots. -func (mr *MockBallotFetcherMockRecorder) GetBallots(arg0, arg1 interface{}) *BallotFetcherGetBallotsCall { +func (mr *MockBallotFetcherMockRecorder) GetBallots(arg0, arg1 any) *BallotFetcherGetBallotsCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBallots", reflect.TypeOf((*MockBallotFetcher)(nil).GetBallots), arg0, arg1) return &BallotFetcherGetBallotsCall{Call: call} @@ -751,7 +755,7 @@ func (m *MockProposalFetcher) GetProposals(arg0 context.Context, arg1 []types.Pr } // GetProposals indicates an expected call of GetProposals. -func (mr *MockProposalFetcherMockRecorder) GetProposals(arg0, arg1 interface{}) *ProposalFetcherGetProposalsCall { +func (mr *MockProposalFetcherMockRecorder) GetProposals(arg0, arg1 any) *ProposalFetcherGetProposalsCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetProposals", reflect.TypeOf((*MockProposalFetcher)(nil).GetProposals), arg0, arg1) return &ProposalFetcherGetProposalsCall{Call: call} @@ -812,7 +816,7 @@ func (m *MockActiveSetFetcher) GetActiveSet(arg0 context.Context, arg1 types.Has } // GetActiveSet indicates an expected call of GetActiveSet. -func (mr *MockActiveSetFetcherMockRecorder) GetActiveSet(arg0, arg1 interface{}) *ActiveSetFetcherGetActiveSetCall { +func (mr *MockActiveSetFetcherMockRecorder) GetActiveSet(arg0, arg1 any) *ActiveSetFetcherGetActiveSetCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetActiveSet", reflect.TypeOf((*MockActiveSetFetcher)(nil).GetActiveSet), arg0, arg1) return &ActiveSetFetcherGetActiveSetCall{Call: call} @@ -871,7 +875,7 @@ func (m *MockPeerTracker) RegisterPeerHashes(peer p2p.Peer, hashes []types.Hash3 } // RegisterPeerHashes indicates an expected call of RegisterPeerHashes. -func (mr *MockPeerTrackerMockRecorder) RegisterPeerHashes(peer, hashes interface{}) *PeerTrackerRegisterPeerHashesCall { +func (mr *MockPeerTrackerMockRecorder) RegisterPeerHashes(peer, hashes any) *PeerTrackerRegisterPeerHashesCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterPeerHashes", reflect.TypeOf((*MockPeerTracker)(nil).RegisterPeerHashes), peer, hashes) return &PeerTrackerRegisterPeerHashesCall{Call: call} diff --git a/system/mocks/sync.go b/system/mocks/sync.go index ea7d2f05d8..042ba9ea9c 100644 --- a/system/mocks/sync.go +++ b/system/mocks/sync.go @@ -1,6 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: ./sync.go - +// +// Generated by this command: +// +// mockgen -typed -package=mocks -destination=./mocks/sync.go -source=./sync.go +// // Package mocks is a generated GoMock package. package mocks @@ -44,7 +48,7 @@ func (m *MockSyncStateProvider) IsBeaconSynced(arg0 types.EpochID) bool { } // IsBeaconSynced indicates an expected call of IsBeaconSynced. -func (mr *MockSyncStateProviderMockRecorder) IsBeaconSynced(arg0 interface{}) *SyncStateProviderIsBeaconSyncedCall { +func (mr *MockSyncStateProviderMockRecorder) IsBeaconSynced(arg0 any) *SyncStateProviderIsBeaconSyncedCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsBeaconSynced", reflect.TypeOf((*MockSyncStateProvider)(nil).IsBeaconSynced), arg0) return &SyncStateProviderIsBeaconSyncedCall{Call: call} @@ -82,7 +86,7 @@ func (m *MockSyncStateProvider) IsSynced(arg0 context.Context) bool { } // IsSynced indicates an expected call of IsSynced. -func (mr *MockSyncStateProviderMockRecorder) IsSynced(arg0 interface{}) *SyncStateProviderIsSyncedCall { +func (mr *MockSyncStateProviderMockRecorder) IsSynced(arg0 any) *SyncStateProviderIsSyncedCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsSynced", reflect.TypeOf((*MockSyncStateProvider)(nil).IsSynced), arg0) return &SyncStateProviderIsSyncedCall{Call: call} diff --git a/system/mocks/tortoise.go b/system/mocks/tortoise.go index 3bf72e6cb3..e03c2e5c60 100644 --- a/system/mocks/tortoise.go +++ b/system/mocks/tortoise.go @@ -1,6 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: ./tortoise.go - +// +// Generated by this command: +// +// mockgen -typed -package=mocks -destination=./mocks/tortoise.go -source=./tortoise.go +// // Package mocks is a generated GoMock package. package mocks @@ -81,7 +85,7 @@ func (m *MockTortoise) OnAtx(arg0 *types.AtxTortoiseData) { } // OnAtx indicates an expected call of OnAtx. -func (mr *MockTortoiseMockRecorder) OnAtx(arg0 interface{}) *TortoiseOnAtxCall { +func (mr *MockTortoiseMockRecorder) OnAtx(arg0 any) *TortoiseOnAtxCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OnAtx", reflect.TypeOf((*MockTortoise)(nil).OnAtx), arg0) return &TortoiseOnAtxCall{Call: call} @@ -117,7 +121,7 @@ func (m *MockTortoise) OnBlock(arg0 types.BlockHeader) { } // OnBlock indicates an expected call of OnBlock. -func (mr *MockTortoiseMockRecorder) OnBlock(arg0 interface{}) *TortoiseOnBlockCall { +func (mr *MockTortoiseMockRecorder) OnBlock(arg0 any) *TortoiseOnBlockCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OnBlock", reflect.TypeOf((*MockTortoise)(nil).OnBlock), arg0) return &TortoiseOnBlockCall{Call: call} @@ -153,7 +157,7 @@ func (m *MockTortoise) OnHareOutput(arg0 types.LayerID, arg1 types.BlockID) { } // OnHareOutput indicates an expected call of OnHareOutput. -func (mr *MockTortoiseMockRecorder) OnHareOutput(arg0, arg1 interface{}) *TortoiseOnHareOutputCall { +func (mr *MockTortoiseMockRecorder) OnHareOutput(arg0, arg1 any) *TortoiseOnHareOutputCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OnHareOutput", reflect.TypeOf((*MockTortoise)(nil).OnHareOutput), arg0, arg1) return &TortoiseOnHareOutputCall{Call: call} @@ -189,7 +193,7 @@ func (m *MockTortoise) OnMalfeasance(arg0 types.NodeID) { } // OnMalfeasance indicates an expected call of OnMalfeasance. -func (mr *MockTortoiseMockRecorder) OnMalfeasance(arg0 interface{}) *TortoiseOnMalfeasanceCall { +func (mr *MockTortoiseMockRecorder) OnMalfeasance(arg0 any) *TortoiseOnMalfeasanceCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OnMalfeasance", reflect.TypeOf((*MockTortoise)(nil).OnMalfeasance), arg0) return &TortoiseOnMalfeasanceCall{Call: call} @@ -225,7 +229,7 @@ func (m *MockTortoise) OnWeakCoin(arg0 types.LayerID, arg1 bool) { } // OnWeakCoin indicates an expected call of OnWeakCoin. -func (mr *MockTortoiseMockRecorder) OnWeakCoin(arg0, arg1 interface{}) *TortoiseOnWeakCoinCall { +func (mr *MockTortoiseMockRecorder) OnWeakCoin(arg0, arg1 any) *TortoiseOnWeakCoinCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OnWeakCoin", reflect.TypeOf((*MockTortoise)(nil).OnWeakCoin), arg0, arg1) return &TortoiseOnWeakCoinCall{Call: call} @@ -264,7 +268,7 @@ func (m *MockTortoise) Results(from, to types.LayerID) ([]result.Layer, error) { } // Results indicates an expected call of Results. -func (mr *MockTortoiseMockRecorder) Results(from, to interface{}) *TortoiseResultsCall { +func (mr *MockTortoiseMockRecorder) Results(from, to any) *TortoiseResultsCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Results", reflect.TypeOf((*MockTortoise)(nil).Results), from, to) return &TortoiseResultsCall{Call: call} @@ -300,7 +304,7 @@ func (m *MockTortoise) TallyVotes(arg0 context.Context, arg1 types.LayerID) { } // TallyVotes indicates an expected call of TallyVotes. -func (mr *MockTortoiseMockRecorder) TallyVotes(arg0, arg1 interface{}) *TortoiseTallyVotesCall { +func (mr *MockTortoiseMockRecorder) TallyVotes(arg0, arg1 any) *TortoiseTallyVotesCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TallyVotes", reflect.TypeOf((*MockTortoise)(nil).TallyVotes), arg0, arg1) return &TortoiseTallyVotesCall{Call: call} diff --git a/system/mocks/vm.go b/system/mocks/vm.go index bf10dc71df..5fb300c8fd 100644 --- a/system/mocks/vm.go +++ b/system/mocks/vm.go @@ -1,6 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: ./vm.go - +// +// Generated by this command: +// +// mockgen -typed -package=mocks -destination=./mocks/vm.go -source=./vm.go +// // Package mocks is a generated GoMock package. package mocks diff --git a/systest/Makefile b/systest/Makefile index 87f24ba4e8..18efe9a0ca 100644 --- a/systest/Makefile +++ b/systest/Makefile @@ -5,7 +5,7 @@ tmpfile := $(shell mktemp /tmp/systest-XXX) test_name ?= TestSmeshing org ?= spacemeshos image_name ?= $(org)/systest:$(version_info) -poet_image ?= spacemeshos/poet:v0.9.1 +poet_image ?= spacemeshos/poet:v0.9.3 smesher_image ?= $(org)/go-spacemesh-dev:$(version_info) bs_image ?= $(org)/go-spacemesh-dev-bs:$(version_info) test_id ?= systest-$(version_info) diff --git a/systest/cluster/cluster.go b/systest/cluster/cluster.go index 294dd380f2..de0c9eae5d 100644 --- a/systest/cluster/cluster.go +++ b/systest/cluster/cluster.go @@ -167,7 +167,6 @@ func New(cctx *testcontext.Context, opts ...Opt) *Cluster { cluster.addFlag(GenesisExtraData(defaultExtraData)) cluster.addFlag(MinPeers(minPeers(cctx.ClusterSize))) cluster.addFlag(PrivateNetwork()) - cluster.addFlag(DisableLegacyDiscovery()) cluster.addPoetFlag(genesis) cluster.addPoetFlag(PoetRestListen(poetPort)) diff --git a/systest/cluster/nodes.go b/systest/cluster/nodes.go index 750e5513d9..edaec3347f 100644 --- a/systest/cluster/nodes.go +++ b/systest/cluster/nodes.go @@ -671,20 +671,6 @@ func CheckpointLayer(restoreLayer uint32) DeploymentFlag { return DeploymentFlag{Name: "--recovery-layer", Value: strconv.Itoa(int(restoreLayer))} } -func UseNewOpn(use bool) DeploymentFlag { - if use { - return DeploymentFlag{Name: "--use-new-opn", Value: "true"} - } - return DeploymentFlag{Name: "--use-new-opn", Value: "false"} -} - -func ServeNewOpn(newSyncProtocol bool) DeploymentFlag { - if newSyncProtocol { - return DeploymentFlag{Name: "--serve-new-opn", Value: "true"} - } - return DeploymentFlag{Name: "--serve-new-opn", Value: "false"} -} - const ( genesisTimeFlag = "--genesis-time" genesisExtraData = "--genesis-extra-data" @@ -744,7 +730,3 @@ func Bootnode() DeploymentFlag { func PrivateNetwork() DeploymentFlag { return DeploymentFlag{Name: "--p2p-private-network", Value: fmt.Sprintf("%v", true)} } - -func DisableLegacyDiscovery() DeploymentFlag { - return DeploymentFlag{Name: "--p2p-disable-legacy-discovery", Value: fmt.Sprintf("%v", true)} -} diff --git a/systest/tests/nodes_test.go b/systest/tests/nodes_test.go index 6cd218a50c..b188ba1d1a 100644 --- a/systest/tests/nodes_test.go +++ b/systest/tests/nodes_test.go @@ -38,10 +38,7 @@ func TestAddNodes(t *testing.T) { tctx.Log.Info("cluster size changed to ", oldSize) tctx.ClusterSize = oldSize } - cl, err := cluster.ReuseWait(tctx, cluster.WithKeys(10), - cluster.WithSmesherFlag(cluster.UseNewOpn(true)), - cluster.WithSmesherFlag(cluster.ServeNewOpn(true)), - ) + cl, err := cluster.ReuseWait(tctx, cluster.WithKeys(10)) require.NoError(t, err) // increase the cluster size to the original test size @@ -57,10 +54,7 @@ func TestAddNodes(t *testing.T) { "layer", layer.Layer.Number, ) // the new smeshers will use the old sync protocol - return false, cl.AddSmeshers(tctx, addedLater, - cluster.WithFlags(cluster.UseNewOpn(false)), - cluster.WithFlags(cluster.ServeNewOpn(false)), - ) + return false, cl.AddSmeshers(tctx, addedLater) } return true, nil }) diff --git a/timesync/clock.go b/timesync/clock.go index 59ea3393f2..af7132116d 100644 --- a/timesync/clock.go +++ b/timesync/clock.go @@ -4,7 +4,7 @@ import ( "sync" "time" - "github.com/benbjohnson/clock" + "github.com/jonboulle/clockwork" "github.com/prometheus/client_golang/prometheus" "golang.org/x/sync/errgroup" @@ -25,7 +25,7 @@ var tickDistance = metrics.NewHistogramWithBuckets( type NodeClock struct { LayerConverter // layer conversions provider - clock clock.Clock // provides the time + clock clockwork.Clock // provides the time genesis time.Time tickInterval time.Duration @@ -44,7 +44,7 @@ type NodeClock struct { // NewClock return TimeClock struct that notifies tickInterval has passed. func NewClock(opts ...OptionFunc) (*NodeClock, error) { cfg := &option{ - clock: clock.New(), + clock: clockwork.NewRealClock(), } for _, opt := range opts { opt(cfg) @@ -81,7 +81,7 @@ func (t *NodeClock) startClock() error { log.Duration("tick_interval", t.tickInterval), ) - ticker := t.clock.Ticker(t.tickInterval) + ticker := t.clock.NewTicker(t.tickInterval) for { currLayer := t.TimeToLayer(t.clock.Now()) t.log.With().Debug("global clock going to sleep before next tick", @@ -89,7 +89,7 @@ func (t *NodeClock) startClock() error { ) select { - case <-ticker.C: + case <-ticker.Chan(): case <-t.stop: t.log.Info("stopping global clock") ticker.Stop() diff --git a/timesync/clock_options.go b/timesync/clock_options.go index 1fee5056e2..442d75837f 100644 --- a/timesync/clock_options.go +++ b/timesync/clock_options.go @@ -4,13 +4,13 @@ import ( "fmt" "time" - "github.com/benbjohnson/clock" + "github.com/jonboulle/clockwork" "github.com/spacemeshos/go-spacemesh/log" ) type option struct { - clock clock.Clock + clock clockwork.Clock genesisTime time.Time layerDuration time.Duration tickInterval time.Duration @@ -44,7 +44,7 @@ func (o *option) validate() error { type OptionFunc func(*option) error // withClock specifies which clock the NodeClock should use. Defaults to the real clock. -func withClock(clock clock.Clock) OptionFunc { +func withClock(clock clockwork.Clock) OptionFunc { return func(opts *option) error { opts.clock = clock return nil diff --git a/timesync/clock_test.go b/timesync/clock_test.go index 5c98062da7..b8ba4f86fe 100644 --- a/timesync/clock_test.go +++ b/timesync/clock_test.go @@ -6,7 +6,7 @@ import ( "testing" "time" - "github.com/benbjohnson/clock" + "github.com/jonboulle/clockwork" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" @@ -189,8 +189,7 @@ func Test_NodeClock_Await_WithClockMovingBackwards(t *testing.T) { layerDuration := 100 * time.Millisecond tickInterval := 10 * time.Millisecond - mClock := clock.NewMock() - mClock.Set(now) + mClock := clockwork.NewFakeClockAt(now) clock, err := NewClock( withClock(mClock), @@ -213,7 +212,7 @@ func Test_NodeClock_Await_WithClockMovingBackwards(t *testing.T) { } // move the clock backwards by a layer - mClock.Set(now.Add(-2 * layerDuration)) + mClock.Advance(-2 * layerDuration) ch := clock.AwaitLayer(types.LayerID(9)) select { @@ -223,7 +222,8 @@ func Test_NodeClock_Await_WithClockMovingBackwards(t *testing.T) { } // continue clock forward in time - mClock.Add(3 * layerDuration) + mClock.Advance(3 * layerDuration) + clock.tick() select { case <-ch: @@ -238,8 +238,7 @@ func Test_NodeClock_NonMonotonicTick_Forward(t *testing.T) { layerDuration := 100 * time.Millisecond tickInterval := 10 * time.Millisecond - mClock := clock.NewMock() - mClock.Set(genesis.Add(5 * layerDuration)) + mClock := clockwork.NewFakeClockAt(genesis.Add(5 * layerDuration)) clock, err := NewClock( withClock(mClock), @@ -261,7 +260,7 @@ func Test_NodeClock_NonMonotonicTick_Forward(t *testing.T) { } // hibernate for 5 layers (clock jumps forward) - mClock.Add(5 * layerDuration) + mClock.Advance(5 * layerDuration) select { case <-ch: @@ -277,8 +276,7 @@ func Test_NodeClock_NonMonotonicTick_Backward(t *testing.T) { layerDuration := 10 * time.Millisecond tickInterval := 1 * time.Millisecond - mClock := clock.NewMock() - mClock.Set(genesis.Add(5 * layerDuration)) + mClock := clockwork.NewFakeClockAt(genesis.Add(5 * layerDuration)) clock, err := NewClock( withClock(mClock), @@ -304,7 +302,7 @@ func Test_NodeClock_NonMonotonicTick_Backward(t *testing.T) { } // simulate time passing - mClock.Add(1 * layerDuration) + mClock.Advance(1 * layerDuration) select { case <-ch6: @@ -321,7 +319,7 @@ func Test_NodeClock_NonMonotonicTick_Backward(t *testing.T) { } // NTP corrects time backwards - mClock.Add(-1 * layerDuration) + mClock.Advance(-1 * layerDuration) ch6 = clock.AwaitLayer(types.LayerID(6)) select { @@ -335,7 +333,7 @@ func Test_NodeClock_NonMonotonicTick_Backward(t *testing.T) { } // simulate time passing - mClock.Add(2 * layerDuration) + mClock.Advance(2 * layerDuration) select { case <-ch6: @@ -374,8 +372,7 @@ func Fuzz_NodeClock_CurrentLayer(f *testing.F) { layerTime := time.Duration(layerSecs) * time.Second tickInterval := layerTime / 10 - mClock := clock.NewMock() - mClock.Set(nowTime) + mClock := clockwork.NewFakeClockAt(nowTime) clock, err := NewClock( withClock(mClock), diff --git a/timesync/peersync/mocks/mocks.go b/timesync/peersync/mocks/mocks.go index af6bde6957..7d72caeeee 100644 --- a/timesync/peersync/mocks/mocks.go +++ b/timesync/peersync/mocks/mocks.go @@ -1,6 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: ./sync.go - +// +// Generated by this command: +// +// mockgen -typed -package=mocks -destination=./mocks/mocks.go -source=./sync.go +// // Package mocks is a generated GoMock package. package mocks diff --git a/tortoise/algorithm.go b/tortoise/algorithm.go index 11e5a41d49..4a3998610a 100644 --- a/tortoise/algorithm.go +++ b/tortoise/algorithm.go @@ -27,8 +27,7 @@ type Config struct { // MinimalActiveSetWeight denotes weight that will replace weight // recorded in the first ballot, if that weight is less than minimal // for purposes of eligibility computation. - MinimalActiveSetWeight uint64 `mapstructure:"tortoise-activeset-weight"` - EmitEmptyActiveSet types.LayerID `mapstructure:"emit-empty-active-set"` + MinimalActiveSetWeight uint64 `mapstructure:"tortoise-activeset-weight"` LayerSize uint32 } @@ -96,6 +95,9 @@ func New(opts ...Opt) (*Tortoise, error) { zap.Uint32("zdist", t.cfg.Zdist), ) } + if t.cfg.WindowSize == 0 { + t.logger.Panic("tortoise-window-size should not be zero") + } t.trtl = newTurtle(t.logger, t.cfg) if t.tracer != nil { t.tracer.On(&ConfigTrace{ diff --git a/tortoise/algorithm_test.go b/tortoise/algorithm_test.go index c56d247338..aa49aeb22d 100644 --- a/tortoise/algorithm_test.go +++ b/tortoise/algorithm_test.go @@ -8,18 +8,14 @@ import ( func TestGetBallot(t *testing.T) { const n = 2 - var activeset []*atxAction s := newSession(t) for i := 0; i < n; i++ { - activeset = append( - activeset, - s.smesher(i).atx(1, new(aopt).height(100).weight(400)), - ) + s.smesher(i).atx(1, new(aopt).height(100).weight(400)) } ref := s.smesher(0).atx(1).ballot(1, new(bopt). beacon("a"). - activeset(activeset...). + totalEligibilities(s.epochEligibilities()). eligibilities(s.layerSize/n)) secondary := s.smesher(0).atx(1).ballot(2) diff --git a/tortoise/fixture_test.go b/tortoise/fixture_test.go index 2b72fcf747..9a485e2c23 100644 --- a/tortoise/fixture_test.go +++ b/tortoise/fixture_test.go @@ -135,15 +135,12 @@ func (b *bopt) eligibilities(value int) *bopt { return b } -func (b *bopt) activeset(values ...*atxAction) *bopt { +func (b *bopt) totalEligibilities(n int) *bopt { b.opts = append(b.opts, func(ballot *ballotAction) { - ballot.activeset = values - for _, val := range values { - if ballot.EpochData == nil { - ballot.EpochData = &types.ReferenceData{} - } - ballot.EpochData.ActiveSet = append(ballot.EpochData.ActiveSet, val.header.ID) + if ballot.EpochData == nil { + ballot.EpochData = &types.ReferenceData{} } + ballot.EpochData.Eligibilities = uint32(n) }) return b } @@ -233,6 +230,7 @@ func (a *atxAction) rawballot(id types.BallotID, n int, opts ...*bopt) *ballotAc } if a.reference == nil { a.reference = val + val.before = append(val.before, a) } else { val.Ref = &a.reference.ID val.before = append(val.before, a.reference) @@ -244,12 +242,6 @@ func (a *atxAction) rawballot(id types.BallotID, n int, opts ...*bopt) *ballotAc if val.base != nil { val.before = append(val.before, val.base) } - for _, atx := range val.activeset { - val.before = append(val.before, atx) - } - if len(val.activeset) == 0 { - val.before = append(val.before, a) - } a.reg.register(val) a.ballots[id] = val @@ -268,9 +260,8 @@ func (a *atxAction) ballot(n int, opts ...*bopt) *ballotAction { type ballotAction struct { types.BallotTortoiseData - base *ballotAction - activeset []*atxAction - before []action + base *ballotAction + before []action onDecoded func(*DecodedBallot, error) onStored func(error) @@ -407,6 +398,10 @@ func (s *session) smesher(id int) *smesher { return val } +func (s *session) epochEligibilities() int { + return s.layerSize * s.epochSize / len(s.smeshers) +} + func (s *session) register(actions ...action) { s.actions = append(s.actions, actions...) } @@ -740,19 +735,15 @@ func (s *session) tortoise() *Tortoise { func TestSanity(t *testing.T) { const n = 2 - var activeset []*atxAction s := newSession(t) for i := 0; i < n; i++ { - activeset = append( - activeset, - s.smesher(i).atx(1, new(aopt).height(100).weight(400)), - ) + s.smesher(i).atx(1, new(aopt).height(100).weight(400)) } s.beacon(1, "a") for i := 0; i < n; i++ { s.smesher(i).atx(1).ballot(1, new(bopt). beacon("a"). - activeset(activeset...). + totalEligibilities(s.epochEligibilities()). eligibilities(s.layerSize/n)) } s.tally(1) @@ -776,19 +767,15 @@ func TestSanity(t *testing.T) { func TestDisagreement(t *testing.T) { const n = 5 - var activeset []*atxAction s := newSession(t) for i := 0; i < n; i++ { - activeset = append( - activeset, - s.smesher(i).atx(1, new(aopt).height(100).weight(400)), - ) + s.smesher(i).atx(1, new(aopt).height(100).weight(400)) } s.beacon(1, "a") for i := 0; i < n; i++ { s.smesher(i).atx(1).ballot(1, new(bopt). beacon("a"). - activeset(activeset...). + totalEligibilities(s.epochEligibilities()). eligibilities(s.layerSize/n)) } s.hareblock(1, "aa", 0) @@ -816,15 +803,14 @@ func TestDisagreement(t *testing.T) { func TestOpinion(t *testing.T) { s := newSession(t) - var activeset []*atxAction - activeset = append(activeset, - s.smesher(0).atx(1, new(aopt).height(100).weight(2000)), - ) + + s.smesher(0).atx(1, new(aopt).height(100).weight(2000)) + s.beacon(1, "a") s.smesher(0).atx(1).ballot(1, new(bopt). eligibilities(s.layerSize). beacon("a"). - activeset(activeset...), + totalEligibilities(s.epochEligibilities()), ) for i := 2; i < s.epochSize; i++ { id := strconv.Itoa(i) @@ -842,19 +828,15 @@ func TestOpinion(t *testing.T) { } func TestEpochGap(t *testing.T) { - var activeset []*atxAction s := newSession(t).withEpochSize(4) for i := 0; i < 2; i++ { - activeset = append( - activeset, - s.smesher(i).atx(1, new(aopt).height(1).weight(10)), - ) + s.smesher(i).atx(1, new(aopt).height(1).weight(10)) } s.beacon(1, "a") for i := 0; i < 2; i++ { s.smesher(i).atx(1).ballot(1, new(bopt). beacon("a"). - activeset(activeset...). + totalEligibilities(s.epochEligibilities()). eligibilities(s.layerSize/2)) } rst := new(results). diff --git a/tortoise/full.go b/tortoise/full.go index 9b68108d55..ade4f40cf6 100644 --- a/tortoise/full.go +++ b/tortoise/full.go @@ -46,9 +46,10 @@ func (f *full) countBallot(logger *zap.Logger, ballot *ballotInfo) { continue } layer := f.layer(lvote.lid) + height := ballot.reference.height empty := true for _, block := range layer.blocks { - if block.height > ballot.reference.height { + if block.height > height { continue } vote := lvote.getVote(block) diff --git a/tortoise/full_test.go b/tortoise/full_test.go index c66d9d5285..d5563c82f7 100644 --- a/tortoise/full_test.go +++ b/tortoise/full_test.go @@ -9,6 +9,7 @@ import ( "github.com/spacemeshos/go-spacemesh/common/types" "github.com/spacemeshos/go-spacemesh/log/logtest" + "github.com/spacemeshos/go-spacemesh/proposals/util" "github.com/spacemeshos/go-spacemesh/signing" ) @@ -323,7 +324,11 @@ func TestFullCountVotes(t *testing.T) { t.Run(tc.desc, func(t *testing.T) { logger := logtest.Zap(t) tortoise := defaultAlgorithm(t) - var activeset []types.ATXID + var ( + activeset []types.ATXID + total uint64 + weights []uint64 + ) for i := range tc.activeset { atxid := types.ATXID{byte(i + 1)} header := &types.ActivationTxHeader{ @@ -336,6 +341,8 @@ func TestFullCountVotes(t *testing.T) { header.PublishEpoch = 1 tortoise.OnAtx(header.ToData()) activeset = append(activeset, atxid) + weights = append(weights, header.GetWeight()) + total += header.GetWeight() } consensus := tortoise.trtl @@ -372,8 +379,10 @@ func TestFullCountVotes(t *testing.T) { ballot := &types.Ballot{} ballot.EligibilityProofs = []types.VotingEligibility{{J: uint32(j)}} ballot.AtxID = activeset[b.ATX] - ballot.EpochData = &types.EpochData{ActiveSetHash: types.Hash32{1, 2, 3}, EligibilityCount: 1} - ballot.ActiveSet = activeset + + elig, err := util.GetNumEligibleSlots(weights[b.ATX], 0, total, consensus.LayerSize, types.GetLayersPerEpoch()) + require.NoError(t, err) + ballot.EpochData = &types.EpochData{ActiveSetHash: types.Hash32{1, 2, 3}, EligibilityCount: elig} ballot.Layer = lid // don't vote on genesis for simplicity, // since we don't care about block goodness in this test diff --git a/tortoise/model/core.go b/tortoise/model/core.go index f8eab435fc..b57af73012 100644 --- a/tortoise/model/core.go +++ b/tortoise/model/core.go @@ -107,10 +107,6 @@ func (c *core) OnMessage(m Messenger, event Message) { if c.refBallot != nil { ballot.RefBallot = *c.refBallot } else { - _, activeset, err := c.cdb.GetEpochWeight(ev.LayerID.GetEpoch()) - if err != nil { - panic(err) - } beacon, err := c.beacons.GetBeacon(ev.LayerID.GetEpoch()) if err != nil { beacon = types.Beacon{} @@ -118,10 +114,10 @@ func (c *core) OnMessage(m Messenger, event Message) { c.beacons.StoreBeacon(ev.LayerID.GetEpoch(), beacon) } ballot.EpochData = &types.EpochData{ - ActiveSetHash: types.Hash32{1, 2, 3}, - Beacon: beacon, + ActiveSetHash: types.Hash32{1, 2, 3}, + Beacon: beacon, + EligibilityCount: c.eligibilities, } - ballot.ActiveSet = activeset } ballot.Signature = c.signer.Sign(signing.BALLOT, ballot.SignedBytes()) ballot.SmesherID = c.signer.NodeID() @@ -133,7 +129,7 @@ func (c *core) OnMessage(m Messenger, event Message) { m.Send(MessageBallot{Ballot: ballot}) case MessageLayerEnd: if ev.LayerID.After(types.GetEffectiveGenesis()) { - tortoise.RecoverLayer(context.Background(), c.tortoise, c.cdb, c.beacons, ev.LayerID, ev.LayerID) + tortoise.RecoverLayer(context.Background(), c.tortoise, c.cdb, c.beacons, ev.LayerID, ev.LayerID, ev.LayerID) m.Notify(EventVerified{ID: c.id, Verified: c.tortoise.LatestComplete(), Layer: ev.LayerID}) } diff --git a/tortoise/recover.go b/tortoise/recover.go index 555580ef7d..b5eb505a00 100644 --- a/tortoise/recover.go +++ b/tortoise/recover.go @@ -24,7 +24,7 @@ func Recover(db *datastore.CachedDB, latest types.LayerID, beacon system.BeaconG return nil, err } - layer, err := ballots.LatestLayer(db) + last, err := ballots.LatestLayer(db) if err != nil { return nil, fmt.Errorf("failed to load latest known layer: %w", err) } @@ -49,15 +49,15 @@ func Recover(db *datastore.CachedDB, latest types.LayerID, beacon system.BeaconG return nil, fmt.Errorf("failed to load latest epoch: %w", err) } epoch++ // recoverEpoch expects target epoch, rather than publish - if layer.GetEpoch() != epoch { - for eid := layer.GetEpoch(); eid <= epoch; eid++ { + if last.GetEpoch() != epoch { + for eid := last.GetEpoch(); eid <= epoch; eid++ { if err := recoverEpoch(eid, trtl, db, beacon); err != nil { return nil, err } } } - for lid := types.GetEffectiveGenesis().Add(1); !lid.After(layer); lid = lid.Add(1) { - if err := RecoverLayer(context.Background(), trtl, db, beacon, lid, min(layer, latest)); err != nil { + for lid := types.GetEffectiveGenesis().Add(1); !lid.After(last); lid = lid.Add(1) { + if err := RecoverLayer(context.Background(), trtl, db, beacon, lid, last, min(last, latest)); err != nil { return nil, fmt.Errorf("failed to load tortoise state at layer %d: %w", lid, err) } } @@ -78,7 +78,7 @@ func recoverEpoch(epoch types.EpochID, trtl *Tortoise, db *datastore.CachedDB, b return nil } -func RecoverLayer(ctx context.Context, trtl *Tortoise, db *datastore.CachedDB, beacon system.BeaconGetter, lid, current types.LayerID) error { +func RecoverLayer(ctx context.Context, trtl *Tortoise, db *datastore.CachedDB, beacon system.BeaconGetter, lid, last, current types.LayerID) error { if lid.FirstInEpoch() { if err := recoverEpoch(lid.GetEpoch(), trtl, db, beacon); err != nil { return err @@ -106,7 +106,8 @@ func RecoverLayer(ctx context.Context, trtl *Tortoise, db *datastore.CachedDB, b trtl.OnHareOutput(lid, hare) } } - ballotsrst, err := ballots.Layer(db, lid) + // NOTE(dshulyak) we loaded information about malicious identities earlier. + ballotsrst, err := ballots.LayerNoMalicious(db, lid) if err != nil { return err } @@ -127,7 +128,7 @@ func RecoverLayer(ctx context.Context, trtl *Tortoise, db *datastore.CachedDB, b if err == nil { trtl.OnWeakCoin(lid, coin) } - if lid <= current { + if lid <= current && (lid%types.LayerID(trtl.cfg.WindowSize) == 0 || lid == last) { trtl.TallyVotes(ctx, lid) opinion, err := layers.GetAggregatedHash(db, lid-1) diff --git a/tortoise/recover_test.go b/tortoise/recover_test.go index c3befcc724..2c825ed653 100644 --- a/tortoise/recover_test.go +++ b/tortoise/recover_test.go @@ -30,7 +30,7 @@ func (a *recoveryAdapter) TallyVotes(ctx context.Context, current types.LayerID) a.prev = genesis } for lid := a.prev; lid <= current; lid++ { - require.NoError(a, RecoverLayer(ctx, a.Tortoise, a.db, a.beacon, lid, current)) + require.NoError(a, RecoverLayer(ctx, a.Tortoise, a.db, a.beacon, lid, current, current)) a.prev = lid } } diff --git a/tortoise/sim/generator.go b/tortoise/sim/generator.go index 00c1248f90..617a9261dd 100644 --- a/tortoise/sim/generator.go +++ b/tortoise/sim/generator.go @@ -110,7 +110,7 @@ type Generator struct { layers []*types.Layer units [2]int - activations []types.ATXID + activations []*types.VerifiedActivationTx ticksRange [2]int ticks []uint64 prevHeight []uint64 @@ -206,7 +206,7 @@ func (g *Generator) Setup(opts ...SetupOpt) { g.nextLayer = last.Index().Add(1) miners := intInRange(g.rng, conf.Miners) - g.activations = make([]types.ATXID, miners) + g.activations = make([]*types.VerifiedActivationTx, miners) g.prevHeight = make([]uint64, miners) for i := uint32(0); i < miners; i++ { @@ -242,16 +242,15 @@ func (g *Generator) generateAtxs() { } atx.SetEffectiveNumUnits(atx.NumUnits) atx.SetReceived(time.Now()) - vAtx, err := atx.Verify(g.prevHeight[i], ticks) + vatx, err := atx.Verify(g.prevHeight[i], ticks) if err != nil { panic(err) } g.prevHeight[i] += ticks - g.activations[i] = atx.ID() - + g.activations[i] = vatx for _, state := range g.states { - state.OnActivationTx(vAtx) + state.OnActivationTx(vatx) } } } diff --git a/tortoise/sim/layer.go b/tortoise/sim/layer.go index 33422d50d4..11cf957b6d 100644 --- a/tortoise/sim/layer.go +++ b/tortoise/sim/layer.go @@ -3,6 +3,7 @@ package sim import ( "github.com/spacemeshos/go-spacemesh/common/types" "github.com/spacemeshos/go-spacemesh/log" + "github.com/spacemeshos/go-spacemesh/proposals/util" "github.com/spacemeshos/go-spacemesh/signing" ) @@ -154,8 +155,10 @@ func (g *Generator) genLayer(cfg nextConf) types.LayerID { if cfg.LayerSize >= 0 { size = cfg.LayerSize } - activeset := make([]types.ATXID, len(g.activations)) - copy(activeset, g.activations) + var total uint64 + for _, atx := range g.activations { + total += atx.GetWeight() + } miners := make([]uint32, len(g.activations)) for i := 0; i < size; i++ { @@ -167,7 +170,7 @@ func (g *Generator) genLayer(cfg nextConf) types.LayerID { continue } voting := cfg.VoteGen(g.rng, g.layers, miner) - atxid := g.activations[miner] + atx := g.activations[miner] signer := g.keys[miner] proofs := []types.VotingEligibility{} for j := uint32(0); j < maxj; j++ { @@ -177,18 +180,22 @@ func (g *Generator) genLayer(cfg nextConf) types.LayerID { if err != nil { g.logger.With().Panic("failed to get a beacon", log.Err(err)) } + n, err := util.GetNumEligibleSlots(atx.GetWeight(), 0, total, g.conf.LayerSize, g.conf.LayersPerEpoch) + if err != nil { + g.logger.With().Panic("eligible slots", log.Err(err)) + } ballot := &types.Ballot{ InnerBallot: types.InnerBallot{ Layer: g.nextLayer, - AtxID: atxid, + AtxID: atx.ID(), EpochData: &types.EpochData{ - ActiveSetHash: types.Hash32{1, 2, 3}, - Beacon: beacon, + EligibilityCount: n, + ActiveSetHash: types.Hash32{1, 2, 3}, + Beacon: beacon, }, }, Votes: voting, EligibilityProofs: proofs, - ActiveSet: activeset, } ballot.Signature = signer.Sign(signing.BALLOT, ballot.SignedBytes()) ballot.SmesherID = signer.NodeID() diff --git a/tortoise/sim/partition.go b/tortoise/sim/partition.go index 828d656ca5..f6342e1ad1 100644 --- a/tortoise/sim/partition.go +++ b/tortoise/sim/partition.go @@ -4,7 +4,6 @@ import ( "fmt" "github.com/spacemeshos/go-spacemesh/common/types" - "github.com/spacemeshos/go-spacemesh/log" "github.com/spacemeshos/go-spacemesh/sql/ballots" "github.com/spacemeshos/go-spacemesh/sql/blocks" ) @@ -125,23 +124,19 @@ func (g *Generator) mergeKeys(other *Generator) { } func (g *Generator) mergeActivations(other *Generator) { - for _, atxid := range other.activations { + for _, atx := range other.activations { var exists bool for _, existing := range g.activations { - exists = atxid == existing + exists = atx.ID() == existing.ID() if exists { break } } if !exists { - atx, err := other.GetState(0).DB.GetFullAtx(atxid) - if err != nil { - g.logger.With().Panic("failed to get atx", atxid, log.Err(err)) - } for _, state := range g.states { state.OnActivationTx(atx) } - g.activations = append(g.activations, atxid) + g.activations = append(g.activations, atx) g.prevHeight = append(g.prevHeight, atx.TickHeight()) } } diff --git a/tortoise/state.go b/tortoise/state.go index 55f0aea455..5b22420aba 100644 --- a/tortoise/state.go +++ b/tortoise/state.go @@ -56,7 +56,7 @@ type ( evicted types.LayerID epochs map[types.EpochID]*epochInfo - layers map[types.LayerID]*layerInfo + layers layerSlice // ballots should not be referenced by other ballots // each ballot stores references (votes) for X previous layers // those X layers may reference another set of ballots that will @@ -75,7 +75,6 @@ type ( func newState() *state { return &state{ epochs: map[types.EpochID]*epochInfo{}, - layers: map[types.LayerID]*layerInfo{}, ballots: map[types.LayerID][]*ballotInfo{}, ballotRefs: map[types.BallotID]*ballotInfo{}, malnodes: map[types.NodeID]struct{}{}, @@ -91,13 +90,7 @@ func (s *state) expectedWeight(cfg Config, target types.LayerID) weight { } func (s *state) layer(lid types.LayerID) *layerInfo { - layer, exist := s.layers[lid] - if !exist { - layersNumber.Inc() - layer = &layerInfo{lid: lid} - s.layers[lid] = layer - } - return layer + return s.layers.get(s.evicted, lid) } func (s *state) epoch(eid types.EpochID) *epochInfo { @@ -179,6 +172,10 @@ type layerInfo struct { verifying verifyingInfo coinflip sign + // unique opinions recorded from the ballots in this layer. + // ballot votes an opinion and encodes sidecar + opinions map[types.Hash32]votes + opinion types.Hash32 // a pointer to the value stored on the previous layerInfo object // it is stored as a pointer so that when previous layerInfo is evicted @@ -500,14 +497,23 @@ func decodeVotes(evicted, blid types.LayerID, base *ballotInfo, exceptions types return decoded, from, nil } -func activeSetWeight(epoch *epochInfo, aset []types.ATXID) (uint64, error) { - var weight uint64 - for _, id := range aset { - atx, exists := epoch.atxs[id] - if !exists { - return 0, fmt.Errorf("atx %v is not in state", id) - } - weight += atx.weight +type layerSlice struct { + data []*layerInfo +} + +func (s *layerSlice) get(offset, index types.LayerID) *layerInfo { + i := index - offset - 1 + lth := types.LayerID(len(s.data)) + if i < lth { + return s.data[i] + } + last := offset + lth + for lid := last + 1; lid <= index; lid++ { + s.data = append(s.data, &layerInfo{lid: lid, opinions: map[types.Hash32]votes{}}) } - return weight, nil + return s.data[i] +} + +func (s *layerSlice) pop() { + s.data = s.data[1:] } diff --git a/tortoise/state_test.go b/tortoise/state_test.go index 0210012c56..7bce6c34ee 100644 --- a/tortoise/state_test.go +++ b/tortoise/state_test.go @@ -395,3 +395,17 @@ func TestStateDecodeVotes(t *testing.T) { }) } } + +func TestLayersSliceBoundaries(t *testing.T) { + slice := layerSlice{} + const ( + total = 100_000 + capacity = 10_000 + ) + for i := types.LayerID(0); i < total; i++ { + slice.get(i, i+capacity) + slice.pop() + require.True(t, cap(slice.data) < capacity+capacity/2, "slice expected to double on append: cap=%d", cap(slice.data)) + require.Equal(t, capacity-1, len(slice.data)) + } +} diff --git a/tortoise/tortoise.go b/tortoise/tortoise.go index 59e82719bc..c6e3c879f4 100644 --- a/tortoise/tortoise.go +++ b/tortoise/tortoise.go @@ -14,7 +14,6 @@ import ( "github.com/spacemeshos/go-spacemesh/common/types" "github.com/spacemeshos/go-spacemesh/log" - "github.com/spacemeshos/go-spacemesh/proposals/util" ) var ( @@ -58,10 +57,8 @@ func newTurtle(logger *zap.Logger, config Config) *turtle { t.evicted = genesis.Sub(1) t.epochs[genesis.GetEpoch()] = &epochInfo{atxs: map[types.ATXID]atxInfo{}} - t.layers[genesis] = &layerInfo{ - lid: genesis, - hareTerminated: true, - } + genlayer := t.layer(genesis) + genlayer.hareTerminated = true t.verifying = newVerifying(config, t.state) t.full = newFullTortoise(config, t.state) t.full.counted = genesis @@ -92,6 +89,7 @@ func (t *turtle) evict(ctx context.Context) { zap.Stringer("from_layer", t.evicted.Add(1)), zap.Stringer("upto_layer", windowStart), ) + layersNumber.Set(float64(len(t.layers.data))) if !windowStart.After(t.evicted) { return } @@ -100,21 +98,17 @@ func (t *turtle) evict(ctx context.Context) { } for lid := t.evicted.Add(1); lid.Before(windowStart); lid = lid.Add(1) { for _, ballot := range t.ballots[lid] { - ballotsNumber.Dec() delete(t.ballotRefs, ballot.id) } - for range t.layers[lid].blocks { - blocksNumber.Dec() - } - layersNumber.Dec() - delete(t.layers, lid) + + ballotsNumber.Sub(float64(len(t.ballots[lid]))) + blocksNumber.Sub(float64(len(t.layer(lid).blocks))) + t.layers.pop() + delete(t.ballots, lid) if lid.OrdinalInEpoch() == types.GetLayersPerEpoch()-1 { - layersNumber.Dec() epoch := t.epoch(lid.GetEpoch()) - for range epoch.atxs { - atxsNumber.Dec() - } + atxsNumber.Sub(float64(len(epoch.atxs))) delete(t.epochs, lid.GetEpoch()) } } @@ -699,21 +693,13 @@ func (t *turtle) decodeBallot(ballot *types.BallotTortoiseData) (*ballotInfo, ty if !exists { return nil, 0, fmt.Errorf("atx %s/%d not in state", ballot.AtxID, ballot.Layer.GetEpoch()) } - total, err := activeSetWeight(epoch, ballot.EpochData.ActiveSet) - if err != nil { - return nil, 0, err - } - expected, err := util.GetLegacyNumEligible(ballot.Layer, atx.weight, t.MinimalActiveSetWeight, total, t.LayerSize, types.GetLayersPerEpoch()) - if err != nil { - return nil, 0, err - } refinfo = &referenceInfo{ smesher: ballot.Smesher, atxid: ballot.AtxID, expectedBallots: ballot.EpochData.Eligibilities, beacon: ballot.EpochData.Beacon, height: atx.height, - weight: big.NewRat(int64(atx.weight), int64(expected)), + weight: big.NewRat(int64(atx.weight), int64(ballot.EpochData.Eligibilities)), } } else if ballot.Ref != nil { ptr := *ballot.Ref @@ -757,11 +743,23 @@ func (t *turtle) decodeBallot(ballot *types.BallotTortoiseData) (*ballotInfo, ty zap.Uint32("lid", ballot.Layer.Uint32()), ) - votes, min, err := decodeVotes(t.evicted, binfo.layer, base, ballot.Opinion.Votes) - if err != nil { - return nil, 0, err + layer := t.layer(binfo.layer) + + existing, exists := layer.opinions[ballot.Opinion.Hash] + var min types.LayerID + if exists { + binfo.votes = existing + } else { + var ( + votes votes + err error + ) + votes, min, err = decodeVotes(t.evicted, binfo.layer, base, ballot.Opinion.Votes) + if err != nil { + return nil, 0, err + } + binfo.votes = votes } - binfo.votes = votes t.logger.Debug("decoded exceptions", zap.Stringer("block", binfo.id), zap.Uint32("lid", binfo.layer.Uint32()), @@ -780,15 +778,22 @@ func (t *turtle) storeBallot(ballot *ballotInfo, min types.LayerID) error { } t.state.addBallot(ballot) - for current := ballot.votes.tail; current != nil && !current.lid.Before(min); current = current.prev { - for i, block := range current.supported { - existing := t.getBlock(block.header()) - if existing != nil { - current.supported[i] = existing - } else { - t.addBlock(block) + layer := t.layer(ballot.layer) + existing, exists := layer.opinions[ballot.opinion()] + if exists { + ballot.votes = existing + } else { + for current := ballot.votes.tail; current != nil && !current.lid.Before(min); current = current.prev { + for i, block := range current.supported { + existing := t.getBlock(block.header()) + if existing != nil { + current.supported[i] = existing + } else { + t.addBlock(block) + } } } + layer.opinions[ballot.opinion()] = ballot.votes } if !ballot.layer.After(t.processed) { if err := t.countBallot(ballot); err != nil { diff --git a/tortoise/tortoise_test.go b/tortoise/tortoise_test.go index 1eefad13ba..44291eb66d 100644 --- a/tortoise/tortoise_test.go +++ b/tortoise/tortoise_test.go @@ -25,7 +25,6 @@ import ( "github.com/spacemeshos/go-spacemesh/sql/ballots" "github.com/spacemeshos/go-spacemesh/sql/blocks" "github.com/spacemeshos/go-spacemesh/sql/certificates" - "github.com/spacemeshos/go-spacemesh/sql/identities" "github.com/spacemeshos/go-spacemesh/sql/layers" "github.com/spacemeshos/go-spacemesh/tortoise/opinionhash" "github.com/spacemeshos/go-spacemesh/tortoise/sim" @@ -862,7 +861,6 @@ func TestDecodeVotes(t *testing.T) { require.NoError(t, err) ballot := types.NewExistingBallot(types.BallotID{3, 3, 3}, types.EmptyEdSignature, types.EmptyNodeID, ballots[0].Layer) ballot.InnerBallot = ballots[0].InnerBallot - ballot.ActiveSet = ballots[0].ActiveSet hasher := opinionhash.New() supported := types.BlockID{2, 2, 2} hasher.WriteSupport(supported, 0) @@ -1094,6 +1092,7 @@ func TestBaseBallotPrioritization(t *testing.T) { sim.WithSequence(5), }, expected: genesis.Add(5), + window: 1, }, { desc: "BadBlocksIgnored", @@ -1420,18 +1419,11 @@ func TestComputeLocalOpinion(t *testing.T) { func TestComputeBallotWeight(t *testing.T) { type testBallot struct { - ActiveSet []int // optional index to atx's to form an active set - RefBallot int // optional index to the ballot, use it in test if active set is nil - ATX int // non optional index to this ballot atx - ExpectedWeight float64 - Eligibilities int - } - createActiveSet := func(pos []int, atxdis []types.ATXID) []types.ATXID { - var rst []types.ATXID - for _, i := range pos { - rst = append(rst, atxdis[i]) - } - return rst + TotalEligibilities int + RefBallot int // optional index to the ballot, use it in test if active set is nil + ATX int // non optional index to this ballot atx + ExpectedWeight float64 + Eligibilities int } for _, tc := range []struct { @@ -1441,63 +1433,63 @@ func TestComputeBallotWeight(t *testing.T) { layerSize, layersPerEpoch uint32 }{ { - desc: "FromActiveSet", + desc: "total eligibilities", atxs: []uint{50, 50, 50}, layerSize: 5, layersPerEpoch: 3, ballots: []testBallot{ - {ActiveSet: []int{0, 1, 2}, ATX: 0, ExpectedWeight: 10, Eligibilities: 1}, - {ActiveSet: []int{0, 1, 2}, ATX: 1, ExpectedWeight: 10, Eligibilities: 1}, + {TotalEligibilities: 5, ATX: 0, ExpectedWeight: 10, Eligibilities: 1}, + {TotalEligibilities: 5, ATX: 1, ExpectedWeight: 10, Eligibilities: 1}, }, }, { - desc: "FromRefBallot", + desc: "ref ballot", atxs: []uint{50, 50, 50}, layerSize: 5, layersPerEpoch: 3, ballots: []testBallot{ - {ActiveSet: []int{0, 1, 2}, ATX: 0, ExpectedWeight: 10, Eligibilities: 1}, + {TotalEligibilities: 5, ATX: 0, ExpectedWeight: 10, Eligibilities: 1}, {RefBallot: 0, ATX: 0, ExpectedWeight: 10, Eligibilities: 1}, }, }, { - desc: "FromRefBallotMultipleEligibilities", + desc: "ref ballot multiple", atxs: []uint{50, 50, 50}, layerSize: 5, layersPerEpoch: 3, ballots: []testBallot{ - {ActiveSet: []int{0, 1, 2}, ATX: 0, ExpectedWeight: 10, Eligibilities: 1}, + {TotalEligibilities: 5, ATX: 0, ExpectedWeight: 10, Eligibilities: 1}, {RefBallot: 0, ATX: 0, ExpectedWeight: 20, Eligibilities: 2}, }, }, { - desc: "FromRefBallotMultipleEligibilities", + desc: "ref ballot multiple", atxs: []uint{50, 50, 50}, layerSize: 5, layersPerEpoch: 3, ballots: []testBallot{ - {ActiveSet: []int{0, 1, 2}, ATX: 0, ExpectedWeight: 20, Eligibilities: 2}, + {TotalEligibilities: 5, ATX: 0, ExpectedWeight: 20, Eligibilities: 2}, {RefBallot: 0, ATX: 0, ExpectedWeight: 10, Eligibilities: 1}, }, }, { - desc: "FromRefBallotMultipleEligibilities", + desc: "ref ballot multiple", atxs: []uint{50, 50, 50}, layerSize: 5, layersPerEpoch: 3, ballots: []testBallot{ - {ActiveSet: []int{0, 1, 2}, ATX: 0, ExpectedWeight: 20, Eligibilities: 2}, + {TotalEligibilities: 5, ATX: 0, ExpectedWeight: 20, Eligibilities: 2}, {RefBallot: 0, ATX: 0, ExpectedWeight: 30, Eligibilities: 3}, }, }, { - desc: "DifferentActiveSets", + desc: "different weight", atxs: []uint{50, 50, 100, 100}, layerSize: 5, layersPerEpoch: 2, ballots: []testBallot{ - {ActiveSet: []int{0, 1}, ATX: 0, ExpectedWeight: 10, Eligibilities: 1}, - {ActiveSet: []int{2, 3}, ATX: 2, ExpectedWeight: 20, Eligibilities: 1}, + {TotalEligibilities: 5, ATX: 0, ExpectedWeight: 10, Eligibilities: 1}, + {TotalEligibilities: 5, ATX: 2, ExpectedWeight: 20, Eligibilities: 1}, }, }, } { @@ -1546,11 +1538,11 @@ func TestComputeBallotWeight(t *testing.T) { types.VotingEligibility{J: uint32(currentJ)}) currentJ++ } - if b.ActiveSet != nil { + if b.TotalEligibilities != 0 { ballot.EpochData = &types.EpochData{ - ActiveSetHash: types.Hash32{1, 2, 3}, + ActiveSetHash: types.Hash32{1, 2, 3}, + EligibilityCount: uint32(b.TotalEligibilities), } - ballot.ActiveSet = createActiveSet(b.ActiveSet, atxids) } else { ballot.RefBallot = blts[b.RefBallot].ID() } @@ -1892,7 +1884,7 @@ func TestMaliciousBallotsAreIgnored(t *testing.T) { blts, err := ballots.Layer(s.GetState(0).DB, last) require.NoError(t, err) for _, ballot := range blts { - require.NoError(t, identities.SetMalicious(s.GetState(0).DB, ballot.SmesherID, []byte("proof"), time.Now())) + tortoise.OnMalfeasance(ballot.SmesherID) } tortoise.TallyVotes(ctx, s.Next()) @@ -1940,9 +1932,7 @@ func TestStateManagement(t *testing.T) { evicted := tortoise.trtl.evicted require.Equal(t, verified.Sub(window).Sub(1), evicted) - for lid := types.GetEffectiveGenesis(); !lid.After(evicted); lid = lid.Add(1) { - require.Empty(t, tortoise.trtl.layers[lid]) - } + require.EqualValues(t, evicted+1, tortoise.trtl.layers.data[0].lid) for lid := evicted.Add(1); !lid.After(last); lid = lid.Add(1) { for _, ballot := range tortoise.trtl.ballots[lid] { @@ -2291,7 +2281,6 @@ func TestSwitchMode(t *testing.T) { ballot := types.NewExistingBallot(types.BallotID{byte(i)}, types.EmptyEdSignature, types.EmptyNodeID, template.Layer) ballot.InnerBallot = template.InnerBallot ballot.EligibilityProofs = template.EligibilityProofs - ballot.ActiveSet = template.ActiveSet tortoise.OnBallot(ballot.ToTortoiseData()) } tortoise.TallyVotes(ctx, last) @@ -2339,7 +2328,6 @@ func TestOnBallotComputeOpinion(t *testing.T) { ballot := types.NewExistingBallot(id, types.EmptyEdSignature, types.EmptyNodeID, rst[0].Layer) ballot.InnerBallot = rst[0].InnerBallot ballot.EligibilityProofs = rst[0].EligibilityProofs - ballot.ActiveSet = rst[0].ActiveSet ballot.Votes.Base = types.EmptyBallotID ballot.Votes.Support = nil ballot.Votes.Against = nil @@ -2763,8 +2751,10 @@ func TestEncodeVotes(t *testing.T) { tortoise.OnAtx(header.ToData()) tortoise.OnBeacon(lid.GetEpoch(), types.EmptyBeacon) - ballot.EpochData = &types.EpochData{ActiveSetHash: types.Hash32{1, 2, 3}} - ballot.ActiveSet = []types.ATXID{atxid} + ballot.EpochData = &types.EpochData{ + ActiveSetHash: types.Hash32{1, 2, 3}, + EligibilityCount: 1, + } ballot.AtxID = atxid ballot.Layer = lid ballot.Votes.Support = []types.Vote{ @@ -3062,7 +3052,7 @@ func TestMinimalActiveSetWeight(t *testing.T) { s.smesher(0).atx(1, new(aopt).height(10).weight(2)) s.beacon(1, "a") s.smesher(0).atx(1).ballot(1, new(bopt). - activeset(s.smesher(0).atx(1)). + totalEligibilities(s.epochEligibilities()). beacon("a"). eligibilities(1), ) @@ -3076,11 +3066,11 @@ func TestDuplicateBallot(t *testing.T) { s.smesher(0).atx(1, new(aopt).height(10).weight(2)) id := types.BallotID{1} s.smesher(0).atx(1).rawballot(id, 1, new(bopt). - activeset(s.smesher(0).atx(1)). + totalEligibilities(s.epochEligibilities()). eligibilities(1), ) s.smesher(0).atx(1).rawballot(id, 1, new(bopt). - activeset(s.smesher(0).atx(1)). + totalEligibilities(s.epochEligibilities()). eligibilities(1).assert( func(db *DecodedBallot, err error) { require.NotEmpty(t, db) @@ -3099,21 +3089,15 @@ func TestSwitch(t *testing.T) { withHdist(4). withZdist(2) const smeshers = 4 - var ( - elig = s.layerSize / smeshers - activeset []*atxAction - ) + elig := s.layerSize / smeshers for i := 0; i < smeshers; i++ { - activeset = append( - activeset, - s.smesher(i).atx(1, new(aopt).height(10).weight(100)), - ) + s.smesher(i).atx(1, new(aopt).height(10).weight(100)) } s.beacon(1, "a") for i := 0; i < smeshers; i++ { s.smesher(i).atx(1).ballot(1, new(bopt). beacon("a"). - activeset(activeset...). + totalEligibilities(s.epochEligibilities()). eligibilities(elig)) } @@ -3150,21 +3134,15 @@ func TestOnMalfeasance(t *testing.T) { t.Run("atxs", func(t *testing.T) { s := newSession(t) const smeshers = 3 - var ( - elig = s.layerSize / smeshers - activeset []*atxAction - ) + elig := s.layerSize / smeshers for i := 0; i < smeshers; i++ { - activeset = append( - activeset, - s.smesher(i).atx(1, new(aopt).height(10).weight(100)), - ) + s.smesher(i).atx(1, new(aopt).height(10).weight(100)) } s.beacon(1, "a") for i := 0; i < smeshers; i++ { s.smesher(i).atx(1).ballot(1, new(bopt). beacon("a"). - activeset(activeset...). + totalEligibilities(s.epochEligibilities()). eligibilities(elig)) } s.smesher(0).malfeasant() // without this call threshold will be very large, and s.updates fail @@ -3180,21 +3158,15 @@ func TestOnMalfeasance(t *testing.T) { withHdist(1). withZdist(1) const smeshers = 3 - var ( - elig = s.layerSize / smeshers - activeset []*atxAction - ) + elig := s.layerSize / smeshers for i := 0; i < smeshers; i++ { - activeset = append( - activeset, - s.smesher(i).atx(1, new(aopt).height(10).weight(100)), - ) + s.smesher(i).atx(1, new(aopt).height(10).weight(100)) } s.beacon(1, "a") for i := 0; i < smeshers; i++ { s.smesher(i).atx(1).ballot(1, new(bopt). beacon("a"). - activeset(activeset...). + totalEligibilities(s.epochEligibilities()). eligibilities(elig)) } for i := 0; i < smeshers; i++ { @@ -3218,13 +3190,13 @@ func TestOnMalfeasance(t *testing.T) { func TestBaseAbstain(t *testing.T) { s := newSession(t) - activeset := []*atxAction{ - s.smesher(0).atx(1, new(aopt).height(10).weight(100)), - } + + s.smesher(0).atx(1, new(aopt).height(10).weight(100)) + s.beacon(1, "a") s.smesher(0).atx(1).ballot(1, new(bopt). beacon("a"). - activeset(activeset...). + totalEligibilities(s.epochEligibilities()). eligibilities(s.layerSize)) s.smesher(0).atx(1).ballot(2, new(bopt). eligibilities(s.layerSize). diff --git a/tortoise/verifying_test.go b/tortoise/verifying_test.go index 129eca7f13..9186db2901 100644 --- a/tortoise/verifying_test.go +++ b/tortoise/verifying_test.go @@ -584,9 +584,12 @@ func TestVerifying_Verify(t *testing.T) { state.verified = verified state.processed = processed state.last = processed - state.layers = tc.layers + for lid, info := range tc.layers { + layer := state.layers.get(state.evicted, lid) + *layer = *info + } refs := map[types.BlockID]*blockInfo{} - for _, layer := range state.layers { + for _, layer := range state.layers.data { for _, block := range layer.blocks { refs[block.id] = block state.updateRefHeight(layer, block) diff --git a/txs/txs_mocks.go b/txs/txs_mocks.go index b76d2c35ed..02c7c61a51 100644 --- a/txs/txs_mocks.go +++ b/txs/txs_mocks.go @@ -1,6 +1,10 @@ // Code generated by MockGen. DO NOT EDIT. // Source: ./interface.go - +// +// Generated by this command: +// +// mockgen -typed -package=txs -destination=./txs_mocks.go -source=./interface.go +// // Package txs is a generated GoMock package. package txs @@ -47,7 +51,7 @@ func (m *MockconservativeState) AddToCache(arg0 context.Context, arg1 *types.Tra } // AddToCache indicates an expected call of AddToCache. -func (mr *MockconservativeStateMockRecorder) AddToCache(arg0, arg1, arg2 interface{}) *conservativeStateAddToCacheCall { +func (mr *MockconservativeStateMockRecorder) AddToCache(arg0, arg1, arg2 any) *conservativeStateAddToCacheCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddToCache", reflect.TypeOf((*MockconservativeState)(nil).AddToCache), arg0, arg1, arg2) return &conservativeStateAddToCacheCall{Call: call} @@ -85,7 +89,7 @@ func (m *MockconservativeState) AddToDB(arg0 *types.Transaction) error { } // AddToDB indicates an expected call of AddToDB. -func (mr *MockconservativeStateMockRecorder) AddToDB(arg0 interface{}) *conservativeStateAddToDBCall { +func (mr *MockconservativeStateMockRecorder) AddToDB(arg0 any) *conservativeStateAddToDBCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddToDB", reflect.TypeOf((*MockconservativeState)(nil).AddToDB), arg0) return &conservativeStateAddToDBCall{Call: call} @@ -124,7 +128,7 @@ func (m *MockconservativeState) GetMeshTransaction(arg0 types.TransactionID) (*t } // GetMeshTransaction indicates an expected call of GetMeshTransaction. -func (mr *MockconservativeStateMockRecorder) GetMeshTransaction(arg0 interface{}) *conservativeStateGetMeshTransactionCall { +func (mr *MockconservativeStateMockRecorder) GetMeshTransaction(arg0 any) *conservativeStateGetMeshTransactionCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMeshTransaction", reflect.TypeOf((*MockconservativeState)(nil).GetMeshTransaction), arg0) return &conservativeStateGetMeshTransactionCall{Call: call} @@ -163,7 +167,7 @@ func (m *MockconservativeState) HasTx(arg0 types.TransactionID) (bool, error) { } // HasTx indicates an expected call of HasTx. -func (mr *MockconservativeStateMockRecorder) HasTx(arg0 interface{}) *conservativeStateHasTxCall { +func (mr *MockconservativeStateMockRecorder) HasTx(arg0 any) *conservativeStateHasTxCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HasTx", reflect.TypeOf((*MockconservativeState)(nil).HasTx), arg0) return &conservativeStateHasTxCall{Call: call} @@ -201,7 +205,7 @@ func (m *MockconservativeState) Validation(arg0 types.RawTx) system.ValidationRe } // Validation indicates an expected call of Validation. -func (mr *MockconservativeStateMockRecorder) Validation(arg0 interface{}) *conservativeStateValidationCall { +func (mr *MockconservativeStateMockRecorder) Validation(arg0 any) *conservativeStateValidationCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Validation", reflect.TypeOf((*MockconservativeState)(nil).Validation), arg0) return &conservativeStateValidationCall{Call: call} @@ -302,7 +306,7 @@ func (m *MockvmState) GetBalance(arg0 types.Address) (uint64, error) { } // GetBalance indicates an expected call of GetBalance. -func (mr *MockvmStateMockRecorder) GetBalance(arg0 interface{}) *vmStateGetBalanceCall { +func (mr *MockvmStateMockRecorder) GetBalance(arg0 any) *vmStateGetBalanceCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBalance", reflect.TypeOf((*MockvmState)(nil).GetBalance), arg0) return &vmStateGetBalanceCall{Call: call} @@ -341,7 +345,7 @@ func (m *MockvmState) GetLayerApplied(arg0 types.TransactionID) (types.LayerID, } // GetLayerApplied indicates an expected call of GetLayerApplied. -func (mr *MockvmStateMockRecorder) GetLayerApplied(arg0 interface{}) *vmStateGetLayerAppliedCall { +func (mr *MockvmStateMockRecorder) GetLayerApplied(arg0 any) *vmStateGetLayerAppliedCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLayerApplied", reflect.TypeOf((*MockvmState)(nil).GetLayerApplied), arg0) return &vmStateGetLayerAppliedCall{Call: call} @@ -380,7 +384,7 @@ func (m *MockvmState) GetLayerStateRoot(arg0 types.LayerID) (types.Hash32, error } // GetLayerStateRoot indicates an expected call of GetLayerStateRoot. -func (mr *MockvmStateMockRecorder) GetLayerStateRoot(arg0 interface{}) *vmStateGetLayerStateRootCall { +func (mr *MockvmStateMockRecorder) GetLayerStateRoot(arg0 any) *vmStateGetLayerStateRootCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLayerStateRoot", reflect.TypeOf((*MockvmState)(nil).GetLayerStateRoot), arg0) return &vmStateGetLayerStateRootCall{Call: call} @@ -419,7 +423,7 @@ func (m *MockvmState) GetNonce(arg0 types.Address) (types.Nonce, error) { } // GetNonce indicates an expected call of GetNonce. -func (mr *MockvmStateMockRecorder) GetNonce(arg0 interface{}) *vmStateGetNonceCall { +func (mr *MockvmStateMockRecorder) GetNonce(arg0 any) *vmStateGetNonceCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNonce", reflect.TypeOf((*MockvmState)(nil).GetNonce), arg0) return &vmStateGetNonceCall{Call: call} @@ -496,7 +500,7 @@ func (m *MockvmState) Validation(arg0 types.RawTx) system.ValidationRequest { } // Validation indicates an expected call of Validation. -func (mr *MockvmStateMockRecorder) Validation(arg0 interface{}) *vmStateValidationCall { +func (mr *MockvmStateMockRecorder) Validation(arg0 any) *vmStateValidationCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Validation", reflect.TypeOf((*MockvmState)(nil).Validation), arg0) return &vmStateValidationCall{Call: call} @@ -557,7 +561,7 @@ func (m *MockconStateCache) GetMempool(arg0 log.Log) map[types.Address][]*NanoTX } // GetMempool indicates an expected call of GetMempool. -func (mr *MockconStateCacheMockRecorder) GetMempool(arg0 interface{}) *conStateCacheGetMempoolCall { +func (mr *MockconStateCacheMockRecorder) GetMempool(arg0 any) *conStateCacheGetMempoolCall { mr.mock.ctrl.T.Helper() call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMempool", reflect.TypeOf((*MockconStateCache)(nil).GetMempool), arg0) return &conStateCacheGetMempoolCall{Call: call}