From 932ea97f6483ac6471f507ca35f5fcbf13a7630b Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Fri, 22 Sep 2023 17:40:37 +0000 Subject: [PATCH 01/40] Fix post test --- activation/post_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/activation/post_test.go b/activation/post_test.go index ae43a02dec..6a930b0719 100644 --- a/activation/post_test.go +++ b/activation/post_test.go @@ -44,9 +44,10 @@ func TestPostSetupManager(t *testing.T) { status := mgr.Status() req.GreaterOrEqual(status.NumLabelsWritten, lastStatus.NumLabelsWritten) - if status.NumLabelsWritten < uint64(mgr.opts.NumUnits)*mgr.cfg.LabelsPerUnit { - req.Equal(PostSetupStateInProgress, status.State) + if status.NumLabelsWritten == uint64(mgr.opts.NumUnits)*mgr.cfg.LabelsPerUnit { + return nil } + req.Equal(PostSetupStateInProgress, status.State) } } }) @@ -54,8 +55,7 @@ func TestPostSetupManager(t *testing.T) { // Create data. req.NoError(mgr.PrepareInitializer(context.Background(), mgr.opts)) req.NoError(mgr.StartSession(context.Background())) - cancel() - _ = eg.Wait() + require.NoError(t, eg.Wait()) req.Equal(PostSetupStateComplete, mgr.Status().State) From aa04e5657dc3ccbd7ef97194fc184b5508b002a2 Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Sun, 24 Sep 2023 20:12:27 +0000 Subject: [PATCH 02/40] Integrate PostClient in activation package --- activation/activation.go | 41 +++++- activation/interface.go | 15 ++- activation/mocks.go | 280 ++++++++++++++++++--------------------- activation/nipost.go | 92 +++++++++---- activation/post.go | 30 ----- activation/post_test.go | 51 +------ activation/post_types.go | 35 +++++ node/node.go | 2 + 8 files changed, 281 insertions(+), 265 deletions(-) create mode 100644 activation/post_types.go diff --git a/activation/activation.go b/activation/activation.go index 6065b1b927..96a842436d 100644 --- a/activation/activation.go +++ b/activation/activation.go @@ -12,7 +12,6 @@ import ( "sync" "time" - "github.com/spacemeshos/post/proving" "github.com/spacemeshos/post/shared" "go.uber.org/atomic" "golang.org/x/sync/errgroup" @@ -88,6 +87,9 @@ type Builder struct { initialPost *types.Post validator nipostValidator + postMux sync.Mutex + postClient PostClient + // smeshingMutex protects `StartSmeshing` and `StopSmeshing` from concurrent access smeshingMutex sync.Mutex @@ -183,6 +185,41 @@ func NewBuilder( return b } +func (b *Builder) Connected(client PostClient) { + b.postMux.Lock() + defer b.postMux.Unlock() + + if b.postClient != nil { + b.log.With().Error("post service already connected") + return + } + + b.postClient = client +} + +func (b *Builder) Disconnected(client PostClient) { + b.postMux.Lock() + defer b.postMux.Unlock() + + if b.postClient != client { + b.log.With().Debug("post service not connected") + return + } + + b.postClient = nil +} + +func (b *Builder) proof(ctx context.Context, challenge []byte) (*types.Post, *types.PostMetadata, error) { + b.postMux.Lock() + defer b.postMux.Unlock() + + if b.postClient == nil { + return nil, nil, errors.New("post service not connected") + } + + return b.postClient.Proof(ctx, challenge) +} + // Smeshing returns true iff atx builder is smeshing. func (b *Builder) Smeshing() bool { return b.started.Load() @@ -333,7 +370,7 @@ func (b *Builder) generateInitialPost(ctx context.Context) error { startTime := time.Now() var err error events.EmitPostStart(shared.ZeroChallenge) - post, metadata, err := b.postSetupProvider.GenerateProof(ctx, shared.ZeroChallenge, proving.WithPowCreator(b.nodeID.Bytes())) + post, metadata, err := b.proof(ctx, shared.ZeroChallenge) if err != nil { events.EmitPostFailure() return fmt.Errorf("post execution: %w", err) diff --git a/activation/interface.go b/activation/interface.go index 310c43c4bf..da320fe59a 100644 --- a/activation/interface.go +++ b/activation/interface.go @@ -5,7 +5,6 @@ import ( "io" "time" - "github.com/spacemeshos/post/proving" "github.com/spacemeshos/post/shared" "github.com/spacemeshos/post/verifying" @@ -56,20 +55,26 @@ type atxProvider interface { } // PostSetupProvider defines the functionality required for Post setup. +// This interface is used by the atx builder and currently implemented by the PostSetupManager. +// Eventually most of the functionality will be moved to the PoSTClient. type postSetupProvider interface { - Status() *PostSetupStatus - Providers() ([]PostSetupProvider, error) - Benchmark(p PostSetupProvider) (int, error) PrepareInitializer(ctx context.Context, opts PostSetupOpts) error StartSession(context context.Context) error Reset() error - GenerateProof(ctx context.Context, challenge []byte, options ...proving.OptionFunc) (*types.Post, *types.PostMetadata, error) CommitmentAtx() (types.ATXID, error) VRFNonce() (*types.VRFPostIndex, error) LastOpts() *PostSetupOpts Config() PostConfig } +// nipostClient is a temporary interface for the NIPostBuilder. +// it is implemented by the PostSetupManager but will eventually merge with the PoSTClient. +type nipostClient interface { + Status() *PostSetupStatus + CommitmentAtx() (types.ATXID, error) + LastOpts() *PostSetupOpts +} + // SmeshingProvider defines the functionality required for the node's Smesher API. type SmeshingProvider interface { Smeshing() bool diff --git a/activation/mocks.go b/activation/mocks.go index 1e2d041584..482f145fa9 100644 --- a/activation/mocks.go +++ b/activation/mocks.go @@ -14,7 +14,6 @@ import ( time "time" types "github.com/spacemeshos/go-spacemesh/common/types" - proving "github.com/spacemeshos/post/proving" shared "github.com/spacemeshos/post/shared" verifying "github.com/spacemeshos/post/verifying" gomock "go.uber.org/mock/gomock" @@ -930,45 +929,6 @@ func (m *MockpostSetupProvider) EXPECT() *MockpostSetupProviderMockRecorder { return m.recorder } -// Benchmark mocks base method. -func (m *MockpostSetupProvider) Benchmark(p PostSetupProvider) (int, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Benchmark", p) - ret0, _ := ret[0].(int) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Benchmark indicates an expected call of Benchmark. -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} -} - -// postSetupProviderBenchmarkCall wrap *gomock.Call -type postSetupProviderBenchmarkCall struct { - *gomock.Call -} - -// Return rewrite *gomock.Call.Return -func (c *postSetupProviderBenchmarkCall) Return(arg0 int, arg1 error) *postSetupProviderBenchmarkCall { - c.Call = c.Call.Return(arg0, arg1) - return c -} - -// Do rewrite *gomock.Call.Do -func (c *postSetupProviderBenchmarkCall) Do(f func(PostSetupProvider) (int, error)) *postSetupProviderBenchmarkCall { - c.Call = c.Call.Do(f) - return c -} - -// DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *postSetupProviderBenchmarkCall) DoAndReturn(f func(PostSetupProvider) (int, error)) *postSetupProviderBenchmarkCall { - c.Call = c.Call.DoAndReturn(f) - return c -} - // CommitmentAtx mocks base method. func (m *MockpostSetupProvider) CommitmentAtx() (types.ATXID, error) { m.ctrl.T.Helper() @@ -1046,51 +1006,6 @@ func (c *postSetupProviderConfigCall) DoAndReturn(f func() PostConfig) *postSetu return c } -// 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 := []any{ctx, challenge} - for _, a := range options { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "GenerateProof", varargs...) - ret0, _ := ret[0].(*types.Post) - ret1, _ := ret[1].(*types.PostMetadata) - ret2, _ := ret[2].(error) - return ret0, ret1, ret2 -} - -// GenerateProof indicates an expected call of GenerateProof. -func (mr *MockpostSetupProviderMockRecorder) GenerateProof(ctx, challenge any, options ...any) *postSetupProviderGenerateProofCall { - mr.mock.ctrl.T.Helper() - varargs := append([]any{ctx, challenge}, options...) - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GenerateProof", reflect.TypeOf((*MockpostSetupProvider)(nil).GenerateProof), varargs...) - return &postSetupProviderGenerateProofCall{Call: call} -} - -// postSetupProviderGenerateProofCall wrap *gomock.Call -type postSetupProviderGenerateProofCall struct { - *gomock.Call -} - -// Return rewrite *gomock.Call.Return -func (c *postSetupProviderGenerateProofCall) Return(arg0 *types.Post, arg1 *types.PostMetadata, arg2 error) *postSetupProviderGenerateProofCall { - c.Call = c.Call.Return(arg0, arg1, arg2) - return c -} - -// Do rewrite *gomock.Call.Do -func (c *postSetupProviderGenerateProofCall) Do(f func(context.Context, []byte, ...proving.OptionFunc) (*types.Post, *types.PostMetadata, error)) *postSetupProviderGenerateProofCall { - c.Call = c.Call.Do(f) - return c -} - -// DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *postSetupProviderGenerateProofCall) DoAndReturn(f func(context.Context, []byte, ...proving.OptionFunc) (*types.Post, *types.PostMetadata, error)) *postSetupProviderGenerateProofCall { - c.Call = c.Call.DoAndReturn(f) - return c -} - // LastOpts mocks base method. func (m *MockpostSetupProvider) LastOpts() *PostSetupOpts { m.ctrl.T.Helper() @@ -1167,45 +1082,6 @@ func (c *postSetupProviderPrepareInitializerCall) DoAndReturn(f func(context.Con return c } -// Providers mocks base method. -func (m *MockpostSetupProvider) Providers() ([]PostSetupProvider, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Providers") - ret0, _ := ret[0].([]PostSetupProvider) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Providers indicates an expected call of Providers. -func (mr *MockpostSetupProviderMockRecorder) Providers() *postSetupProviderProvidersCall { - mr.mock.ctrl.T.Helper() - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Providers", reflect.TypeOf((*MockpostSetupProvider)(nil).Providers)) - return &postSetupProviderProvidersCall{Call: call} -} - -// postSetupProviderProvidersCall wrap *gomock.Call -type postSetupProviderProvidersCall struct { - *gomock.Call -} - -// Return rewrite *gomock.Call.Return -func (c *postSetupProviderProvidersCall) Return(arg0 []PostSetupProvider, arg1 error) *postSetupProviderProvidersCall { - c.Call = c.Call.Return(arg0, arg1) - return c -} - -// Do rewrite *gomock.Call.Do -func (c *postSetupProviderProvidersCall) Do(f func() ([]PostSetupProvider, error)) *postSetupProviderProvidersCall { - c.Call = c.Call.Do(f) - return c -} - -// DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *postSetupProviderProvidersCall) DoAndReturn(f func() ([]PostSetupProvider, error)) *postSetupProviderProvidersCall { - c.Call = c.Call.DoAndReturn(f) - return c -} - // Reset mocks base method. func (m *MockpostSetupProvider) Reset() error { m.ctrl.T.Helper() @@ -1282,79 +1158,179 @@ func (c *postSetupProviderStartSessionCall) DoAndReturn(f func(context.Context) return c } -// Status mocks base method. -func (m *MockpostSetupProvider) Status() *PostSetupStatus { +// VRFNonce mocks base method. +func (m *MockpostSetupProvider) VRFNonce() (*types.VRFPostIndex, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Status") - ret0, _ := ret[0].(*PostSetupStatus) - return ret0 + ret := m.ctrl.Call(m, "VRFNonce") + ret0, _ := ret[0].(*types.VRFPostIndex) + ret1, _ := ret[1].(error) + return ret0, ret1 } -// Status indicates an expected call of Status. -func (mr *MockpostSetupProviderMockRecorder) Status() *postSetupProviderStatusCall { +// VRFNonce indicates an expected call of VRFNonce. +func (mr *MockpostSetupProviderMockRecorder) VRFNonce() *postSetupProviderVRFNonceCall { mr.mock.ctrl.T.Helper() - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Status", reflect.TypeOf((*MockpostSetupProvider)(nil).Status)) - return &postSetupProviderStatusCall{Call: call} + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "VRFNonce", reflect.TypeOf((*MockpostSetupProvider)(nil).VRFNonce)) + return &postSetupProviderVRFNonceCall{Call: call} } -// postSetupProviderStatusCall wrap *gomock.Call -type postSetupProviderStatusCall struct { +// postSetupProviderVRFNonceCall wrap *gomock.Call +type postSetupProviderVRFNonceCall struct { *gomock.Call } // Return rewrite *gomock.Call.Return -func (c *postSetupProviderStatusCall) Return(arg0 *PostSetupStatus) *postSetupProviderStatusCall { - c.Call = c.Call.Return(arg0) +func (c *postSetupProviderVRFNonceCall) Return(arg0 *types.VRFPostIndex, arg1 error) *postSetupProviderVRFNonceCall { + c.Call = c.Call.Return(arg0, arg1) return c } // Do rewrite *gomock.Call.Do -func (c *postSetupProviderStatusCall) Do(f func() *PostSetupStatus) *postSetupProviderStatusCall { +func (c *postSetupProviderVRFNonceCall) Do(f func() (*types.VRFPostIndex, error)) *postSetupProviderVRFNonceCall { c.Call = c.Call.Do(f) return c } // DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *postSetupProviderStatusCall) DoAndReturn(f func() *PostSetupStatus) *postSetupProviderStatusCall { +func (c *postSetupProviderVRFNonceCall) DoAndReturn(f func() (*types.VRFPostIndex, error)) *postSetupProviderVRFNonceCall { c.Call = c.Call.DoAndReturn(f) return c } -// VRFNonce mocks base method. -func (m *MockpostSetupProvider) VRFNonce() (*types.VRFPostIndex, error) { +// MocknipostClient is a mock of nipostClient interface. +type MocknipostClient struct { + ctrl *gomock.Controller + recorder *MocknipostClientMockRecorder +} + +// MocknipostClientMockRecorder is the mock recorder for MocknipostClient. +type MocknipostClientMockRecorder struct { + mock *MocknipostClient +} + +// NewMocknipostClient creates a new mock instance. +func NewMocknipostClient(ctrl *gomock.Controller) *MocknipostClient { + mock := &MocknipostClient{ctrl: ctrl} + mock.recorder = &MocknipostClientMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MocknipostClient) EXPECT() *MocknipostClientMockRecorder { + return m.recorder +} + +// CommitmentAtx mocks base method. +func (m *MocknipostClient) CommitmentAtx() (types.ATXID, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "VRFNonce") - ret0, _ := ret[0].(*types.VRFPostIndex) + ret := m.ctrl.Call(m, "CommitmentAtx") + ret0, _ := ret[0].(types.ATXID) ret1, _ := ret[1].(error) return ret0, ret1 } -// VRFNonce indicates an expected call of VRFNonce. -func (mr *MockpostSetupProviderMockRecorder) VRFNonce() *postSetupProviderVRFNonceCall { +// CommitmentAtx indicates an expected call of CommitmentAtx. +func (mr *MocknipostClientMockRecorder) CommitmentAtx() *nipostClientCommitmentAtxCall { mr.mock.ctrl.T.Helper() - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "VRFNonce", reflect.TypeOf((*MockpostSetupProvider)(nil).VRFNonce)) - return &postSetupProviderVRFNonceCall{Call: call} + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CommitmentAtx", reflect.TypeOf((*MocknipostClient)(nil).CommitmentAtx)) + return &nipostClientCommitmentAtxCall{Call: call} } -// postSetupProviderVRFNonceCall wrap *gomock.Call -type postSetupProviderVRFNonceCall struct { +// nipostClientCommitmentAtxCall wrap *gomock.Call +type nipostClientCommitmentAtxCall struct { *gomock.Call } // Return rewrite *gomock.Call.Return -func (c *postSetupProviderVRFNonceCall) Return(arg0 *types.VRFPostIndex, arg1 error) *postSetupProviderVRFNonceCall { +func (c *nipostClientCommitmentAtxCall) Return(arg0 types.ATXID, arg1 error) *nipostClientCommitmentAtxCall { c.Call = c.Call.Return(arg0, arg1) return c } // Do rewrite *gomock.Call.Do -func (c *postSetupProviderVRFNonceCall) Do(f func() (*types.VRFPostIndex, error)) *postSetupProviderVRFNonceCall { +func (c *nipostClientCommitmentAtxCall) Do(f func() (types.ATXID, error)) *nipostClientCommitmentAtxCall { c.Call = c.Call.Do(f) return c } // DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *postSetupProviderVRFNonceCall) DoAndReturn(f func() (*types.VRFPostIndex, error)) *postSetupProviderVRFNonceCall { +func (c *nipostClientCommitmentAtxCall) DoAndReturn(f func() (types.ATXID, error)) *nipostClientCommitmentAtxCall { + c.Call = c.Call.DoAndReturn(f) + return c +} + +// LastOpts mocks base method. +func (m *MocknipostClient) LastOpts() *PostSetupOpts { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "LastOpts") + ret0, _ := ret[0].(*PostSetupOpts) + return ret0 +} + +// LastOpts indicates an expected call of LastOpts. +func (mr *MocknipostClientMockRecorder) LastOpts() *nipostClientLastOptsCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LastOpts", reflect.TypeOf((*MocknipostClient)(nil).LastOpts)) + return &nipostClientLastOptsCall{Call: call} +} + +// nipostClientLastOptsCall wrap *gomock.Call +type nipostClientLastOptsCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *nipostClientLastOptsCall) Return(arg0 *PostSetupOpts) *nipostClientLastOptsCall { + c.Call = c.Call.Return(arg0) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *nipostClientLastOptsCall) Do(f func() *PostSetupOpts) *nipostClientLastOptsCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *nipostClientLastOptsCall) DoAndReturn(f func() *PostSetupOpts) *nipostClientLastOptsCall { + c.Call = c.Call.DoAndReturn(f) + return c +} + +// Status mocks base method. +func (m *MocknipostClient) Status() *PostSetupStatus { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Status") + ret0, _ := ret[0].(*PostSetupStatus) + return ret0 +} + +// Status indicates an expected call of Status. +func (mr *MocknipostClientMockRecorder) Status() *nipostClientStatusCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Status", reflect.TypeOf((*MocknipostClient)(nil).Status)) + return &nipostClientStatusCall{Call: call} +} + +// nipostClientStatusCall wrap *gomock.Call +type nipostClientStatusCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *nipostClientStatusCall) Return(arg0 *PostSetupStatus) *nipostClientStatusCall { + c.Call = c.Call.Return(arg0) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *nipostClientStatusCall) Do(f func() *PostSetupStatus) *nipostClientStatusCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *nipostClientStatusCall) DoAndReturn(f func() *PostSetupStatus) *nipostClientStatusCall { c.Call = c.Call.DoAndReturn(f) return c } diff --git a/activation/nipost.go b/activation/nipost.go index 642e04dc0c..9d661ab81f 100644 --- a/activation/nipost.go +++ b/activation/nipost.go @@ -8,11 +8,11 @@ import ( "fmt" "math/rand" "slices" + "sync" "time" "github.com/spacemeshos/merkle-tree" "github.com/spacemeshos/poet/shared" - "github.com/spacemeshos/post/proving" "golang.org/x/sync/errgroup" "github.com/spacemeshos/go-spacemesh/activation/metrics" @@ -83,17 +83,20 @@ func (nb *NIPostBuilder) persistState() { // NIPostBuilder holds the required state and dependencies to create Non-Interactive Proofs of Space-Time (NIPost). type NIPostBuilder struct { - nodeID types.NodeID - dataDir string - postSetupProvider postSetupProvider - poetProvers map[string]PoetProvingServiceClient - poetDB poetDbAPI - state *types.NIPostBuilderState - log log.Log - signer *signing.EdSigner - layerClock layerClock - poetCfg PoetConfig - validator nipostValidator + nodeID types.NodeID + dataDir string + nipostClient nipostClient + poetProvers map[string]PoetProvingServiceClient + poetDB poetDbAPI + state *types.NIPostBuilderState + log log.Log + signer *signing.EdSigner + layerClock layerClock + poetCfg PoetConfig + validator nipostValidator + + postMux sync.Mutex + postClient PostClient } type NIPostBuilderOption func(*NIPostBuilder) @@ -122,7 +125,7 @@ type poetDbAPI interface { // NewNIPostBuilder returns a NIPostBuilder. func NewNIPostBuilder( nodeID types.NodeID, - postSetupProvider postSetupProvider, + nipostClient nipostClient, poetDB poetDbAPI, poetServers []string, dataDir string, @@ -142,16 +145,16 @@ func NewNIPostBuilder( } b := &NIPostBuilder{ - nodeID: nodeID, - postSetupProvider: postSetupProvider, - poetProvers: poetClients, - poetDB: poetDB, - state: &types.NIPostBuilderState{NIPost: &types.NIPost{}}, - dataDir: dataDir, - log: lg, - signer: signer, - poetCfg: poetCfg, - layerClock: layerClock, + nodeID: nodeID, + nipostClient: nipostClient, + poetProvers: poetClients, + poetDB: poetDB, + state: &types.NIPostBuilderState{NIPost: &types.NIPost{}}, + dataDir: dataDir, + log: lg, + signer: signer, + poetCfg: poetCfg, + layerClock: layerClock, } for _, opt := range opts { @@ -164,6 +167,41 @@ func (nb *NIPostBuilder) DataDir() string { return nb.dataDir } +func (nb *NIPostBuilder) Connected(client PostClient) { + nb.postMux.Lock() + defer nb.postMux.Unlock() + + if nb.postClient != nil { + nb.log.With().Error("post service already connected") + return + } + + nb.postClient = client +} + +func (nb *NIPostBuilder) Disconnected(client PostClient) { + nb.postMux.Lock() + defer nb.postMux.Unlock() + + if nb.postClient != client { + nb.log.With().Debug("post service not connected") + return + } + + nb.postClient = nil +} + +func (nb *NIPostBuilder) proof(ctx context.Context, challenge []byte) (*types.Post, *types.PostMetadata, error) { + nb.postMux.Lock() + defer nb.postMux.Unlock() + + if nb.postClient == nil { + return nil, nil, errors.New("post service not connected") + } + + return nb.postClient.Proof(ctx, challenge) +} + // UpdatePoETProvers updates poetProver reference. It should not be executed concurrently with BuildNIPoST. func (nb *NIPostBuilder) UpdatePoETProvers(poetProvers []PoetProvingServiceClient) { // TODO(mafa): this seems incorrect - this makes it impossible for the node to fetch a submitted challenge @@ -221,7 +259,7 @@ func (nb *NIPostBuilder) BuildNIPost(ctx context.Context, challenge *types.NIPos challengeHash := challenge.Hash() nb.loadState(challengeHash) - if s := nb.postSetupProvider.Status(); s.State != PostSetupStateComplete { + if s := nb.nipostClient.Status(); s.State != PostSetupStateComplete { return nil, errors.New("post setup not complete") } @@ -287,12 +325,12 @@ func (nb *NIPostBuilder) BuildNIPost(ctx context.Context, challenge *types.NIPos startTime := time.Now() events.EmitPostStart(nb.state.PoetProofRef[:]) - proof, proofMetadata, err := nb.postSetupProvider.GenerateProof(postCtx, nb.state.PoetProofRef[:], proving.WithPowCreator(nb.nodeID.Bytes())) + proof, proofMetadata, err := nb.proof(postCtx, nb.state.PoetProofRef[:]) if err != nil { events.EmitPostFailure() return nil, fmt.Errorf("failed to generate Post: %w", err) } - commitmentAtxId, err := nb.postSetupProvider.CommitmentAtx() + commitmentAtxId, err := nb.nipostClient.CommitmentAtx() if err != nil { return nil, fmt.Errorf("failed to get commitment ATX: %w", err) } @@ -302,7 +340,7 @@ func (nb *NIPostBuilder) BuildNIPost(ctx context.Context, challenge *types.NIPos commitmentAtxId, proof, proofMetadata, - nb.postSetupProvider.LastOpts().NumUnits, + nb.nipostClient.LastOpts().NumUnits, ); err != nil { events.EmitInvalidPostProof() return nil, fmt.Errorf("failed to verify Post: %w", err) diff --git a/activation/post.go b/activation/post.go index ebf3dbb395..22a0353102 100644 --- a/activation/post.go +++ b/activation/post.go @@ -2,7 +2,6 @@ package activation import ( "context" - "encoding/hex" "errors" "fmt" "runtime" @@ -48,35 +47,6 @@ func (c PostConfig) ToConfig() config.Config { } } -type PowDifficulty [32]byte - -func (d PowDifficulty) String() string { - return fmt.Sprintf("%X", d[:]) -} - -// Set implements pflag.Value.Set. -func (f *PowDifficulty) Set(value string) error { - return f.UnmarshalText([]byte(value)) -} - -// Type implements pflag.Value.Type. -func (PowDifficulty) Type() string { - return "PowDifficulty" -} - -func (d *PowDifficulty) UnmarshalText(text []byte) error { - decodedLen := hex.DecodedLen(len(text)) - if decodedLen != 32 { - return fmt.Errorf("expected 32 bytes, got %d", decodedLen) - } - var dst [32]byte - if _, err := hex.Decode(dst[:], text); err != nil { - return err - } - *d = PowDifficulty(dst) - return nil -} - // PostSetupOpts are the options used to initiate a Post setup data creation session, // either via the public smesher API, or on node launch (via cmd args). type PostSetupOpts struct { diff --git a/activation/post_test.go b/activation/post_test.go index 6a930b0719..5a21916799 100644 --- a/activation/post_test.go +++ b/activation/post_test.go @@ -10,7 +10,6 @@ import ( "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/zap/zaptest" "golang.org/x/sync/errgroup" @@ -39,7 +38,7 @@ func TestPostSetupManager(t *testing.T) { for { select { case <-ctx.Done(): - return ctx.Err() + return nil case <-timer.C: status := mgr.Status() req.GreaterOrEqual(status.NumLabelsWritten, lastStatus.NumLabelsWritten) @@ -55,6 +54,7 @@ func TestPostSetupManager(t *testing.T) { // Create data. req.NoError(mgr.PrepareInitializer(context.Background(), mgr.opts)) req.NoError(mgr.StartSession(context.Background())) + cancel() require.NoError(t, eg.Wait()) req.Equal(PostSetupStateComplete, mgr.Status().State) @@ -220,53 +220,6 @@ func TestPostSetupManager_InitialStatus(t *testing.T) { req.Zero(status.NumLabelsWritten) } -func TestPostSetupManager_GenerateProof(t *testing.T) { - req := require.New(t) - ch := make([]byte, 32) - - mgr := newTestPostManager(t) - - // Attempt to generate proof. - _, _, err := mgr.GenerateProof(context.Background(), ch) - req.EqualError(err, errNotComplete.Error()) - - // Create data. - req.NoError(mgr.PrepareInitializer(context.Background(), mgr.opts)) - req.NoError(mgr.StartSession(context.Background())) - - // Generate proof. - p, m, err := mgr.GenerateProof(context.Background(), ch) - req.NoError(err) - - // Verify the proof - verifier, err := verifying.NewProofVerifier() - req.NoError(err) - defer verifier.Close() - err = verifier.Verify(&shared.Proof{ - Nonce: p.Nonce, - Indices: p.Indices, - Pow: p.Pow, - }, &shared.ProofMetadata{ - NodeId: mgr.id.Bytes(), - CommitmentAtxId: mgr.goldenATXID.Bytes(), - Challenge: ch, - NumUnits: mgr.opts.NumUnits, - LabelsPerUnit: m.LabelsPerUnit, - }, - config.DefaultConfig(), - logtest.New(t).WithName("verifying").Zap(), - verifying.WithLabelScryptParams(mgr.opts.Scrypt), - ) - req.NoError(err) - - // Re-instantiate `PostSetupManager`. - mgr = newTestPostManager(t) - - // Attempt to generate proof. - _, _, err = mgr.GenerateProof(context.Background(), ch) - req.ErrorIs(err, errNotComplete) -} - func TestPostSetupManager_VRFNonce(t *testing.T) { req := require.New(t) diff --git a/activation/post_types.go b/activation/post_types.go new file mode 100644 index 0000000000..b81dadd66d --- /dev/null +++ b/activation/post_types.go @@ -0,0 +1,35 @@ +package activation + +import ( + "encoding/hex" + "fmt" +) + +type PowDifficulty [32]byte + +func (d PowDifficulty) String() string { + return fmt.Sprintf("%X", d[:]) +} + +// Set implements pflag.Value.Set. +func (f *PowDifficulty) Set(value string) error { + return f.UnmarshalText([]byte(value)) +} + +// Type implements pflag.Value.Type. +func (PowDifficulty) Type() string { + return "PowDifficulty" +} + +func (d *PowDifficulty) UnmarshalText(text []byte) error { + decodedLen := hex.DecodedLen(len(text)) + if decodedLen != 32 { + return fmt.Errorf("expected 32 bytes, got %d", decodedLen) + } + var dst [32]byte + if _, err := hex.Decode(dst[:], text); err != nil { + return err + } + *d = PowDifficulty(dst) + return nil +} diff --git a/node/node.go b/node/node.go index 8cfd40ddc8..342fed2ef5 100644 --- a/node/node.go +++ b/node/node.go @@ -336,6 +336,7 @@ type App struct { certifier *blocks.Certifier postSetupMgr *activation.PostSetupManager atxBuilder *activation.Builder + nipostBuilder *activation.NIPostBuilder atxHandler *activation.Handler txHandler *txs.TxHandler validator *activation.Validator @@ -943,6 +944,7 @@ func (app *App) initServices(ctx context.Context) error { app.syncer = newSyncer app.svm = state app.atxBuilder = atxBuilder + app.nipostBuilder = nipostBuilder app.postSetupMgr = postSetupMgr app.atxHandler = atxHandler app.poetDb = poetDb From 4d9c8791ab5dc47fc4d56b2cc7efe459df5ac9d2 Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Wed, 4 Oct 2023 22:20:04 +0000 Subject: [PATCH 03/40] Fix tests --- activation/activation_test.go | 31 +++-- activation/nipost_test.go | 185 ++++++++++++++----------- activation/post_test.go | 1 + api/grpcserver/smesher_service_test.go | 12 +- 4 files changed, 130 insertions(+), 99 deletions(-) diff --git a/activation/activation_test.go b/activation/activation_test.go index e0ce677cce..e8d7e0b349 100644 --- a/activation/activation_test.go +++ b/activation/activation_test.go @@ -96,12 +96,13 @@ type testAtxBuilder struct { coinbase types.Address goldenATXID types.ATXID - mpub *mocks.MockPublisher - mnipost *MocknipostBuilder - mpost *MockpostSetupProvider - mclock *MocklayerClock - msync *Mocksyncer - mValidator *MocknipostValidator + mpub *mocks.MockPublisher + mnipost *MocknipostBuilder + mpost *MockpostSetupProvider + mpostClient *MockPostClient + mclock *MocklayerClock + msync *Mocksyncer + mValidator *MocknipostValidator } func newTestBuilder(tb testing.TB, opts ...BuilderOption) *testAtxBuilder { @@ -118,6 +119,7 @@ func newTestBuilder(tb testing.TB, opts ...BuilderOption) *testAtxBuilder { mpub: mocks.NewMockPublisher(ctrl), mnipost: NewMocknipostBuilder(ctrl), mpost: NewMockpostSetupProvider(ctrl), + mpostClient: NewMockPostClient(ctrl), mclock: NewMocklayerClock(ctrl), msync: NewMocksyncer(ctrl), mValidator: NewMocknipostValidator(ctrl), @@ -143,6 +145,7 @@ func newTestBuilder(tb testing.TB, opts ...BuilderOption) *testAtxBuilder { Nonce: 0, Indices: make([]byte, 10), } + b.Connected(tab.mpostClient) tab.Builder = b dir := tb.TempDir() tab.mnipost.EXPECT().DataDir().Return(dir).AnyTimes() @@ -250,7 +253,7 @@ func TestBuilder_StartSmeshingCoinbase(t *testing.T) { tab.mpost.EXPECT().StartSession(gomock.Any()).AnyTimes() 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.mpostClient.EXPECT().Proof(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()).AnyTimes().Return(nil) tab.mclock.EXPECT().AwaitLayer(gomock.Any()).Return(make(chan struct{})).AnyTimes() require.NoError(t, tab.StartSmeshing(coinbase, postSetupOpts)) @@ -271,7 +274,7 @@ func TestBuilder_RestartSmeshing(t *testing.T) { tab.mpost.EXPECT().CommitmentAtx().Return(types.EmptyATXID, nil).AnyTimes() tab.mpost.EXPECT().LastOpts().Return(&PostSetupOpts{}).AnyTimes() tab.mpost.EXPECT().StartSession(gomock.Any()).AnyTimes() - tab.mpost.EXPECT().GenerateProof(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(&types.Post{}, &types.PostMetadata{ + tab.mpostClient.EXPECT().Proof(gomock.Any(), gomock.Any()).AnyTimes().Return(&types.Post{}, &types.PostMetadata{ Challenge: shared.ZeroChallenge, }, nil) tab.mpost.EXPECT().Reset().AnyTimes() @@ -382,7 +385,7 @@ func TestBuilder_StartSmeshing_PanicsOnErrInStartSession(t *testing.T) { tab.log = l // Stub these methods in case they get called - tab.mpost.EXPECT().GenerateProof(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(&types.Post{}, &types.PostMetadata{}, nil) + tab.mpostClient.EXPECT().Proof(gomock.Any(), gomock.Any()).AnyTimes().Return(&types.Post{}, &types.PostMetadata{}, nil) tab.mclock.EXPECT().AwaitLayer(gomock.Any()).AnyTimes() // Set expectations @@ -407,7 +410,7 @@ func TestBuilder_StartSmeshing_SessionNotStartedOnFailPrepare(t *testing.T) { tab.log = l // Stub these methods in case they get called - tab.mpost.EXPECT().GenerateProof(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(&types.Post{}, &types.PostMetadata{}, nil) + tab.mpostClient.EXPECT().Proof(gomock.Any(), gomock.Any()).AnyTimes().Return(&types.Post{}, &types.PostMetadata{}, nil) tab.mclock.EXPECT().AwaitLayer(gomock.Any()).AnyTimes() // Set PrepareInitializer to fail @@ -430,7 +433,7 @@ func TestBuilder_StopSmeshing_OnPoSTError(t *testing.T) { tab.mpost.EXPECT().StartSession(gomock.Any()).Return(nil).AnyTimes() 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.mpostClient.EXPECT().Proof(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()).AnyTimes().Return(nil) ch := make(chan struct{}) close(ch) @@ -1089,7 +1092,7 @@ func TestBuilder_RetryPublishActivationTx(t *testing.T) { func TestBuilder_InitialProofGeneratedOnce(t *testing.T) { tab := newTestBuilder(t, WithPoetConfig(PoetConfig{PhaseShift: layerDuration * 4})) - tab.mpost.EXPECT().GenerateProof(gomock.Any(), shared.ZeroChallenge, gomock.Any()).Return(&types.Post{}, &types.PostMetadata{}, nil) + tab.mpostClient.EXPECT().Proof(gomock.Any(), shared.ZeroChallenge).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()).AnyTimes().Return(nil) @@ -1121,7 +1124,7 @@ func TestBuilder_InitialPostIsPersisted(t *testing.T) { tab.mpost.EXPECT().Config().AnyTimes().Return(PostConfig{}) 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{ + tab.mpostClient.EXPECT().Proof(gomock.Any(), shared.ZeroChallenge).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()).AnyTimes().Return(nil) @@ -1132,7 +1135,7 @@ func TestBuilder_InitialPostIsPersisted(t *testing.T) { // Remove the persisted post file and try again require.NoError(t, os.Remove(filepath.Join(tab.nipostBuilder.DataDir(), postFilename))) - tab.mpost.EXPECT().GenerateProof(gomock.Any(), shared.ZeroChallenge, gomock.Any()).Return(&types.Post{}, &types.PostMetadata{}, nil) + tab.mpostClient.EXPECT().Proof(gomock.Any(), shared.ZeroChallenge).Return(&types.Post{}, &types.PostMetadata{}, nil) require.NoError(t, tab.generateInitialPost(context.Background())) } diff --git a/activation/nipost_test.go b/activation/nipost_test.go index 23452862d6..d4576d469d 100644 --- a/activation/nipost_test.go +++ b/activation/nipost_test.go @@ -9,7 +9,6 @@ import ( "github.com/spacemeshos/go-scale/tester" "github.com/spacemeshos/poet/logging" - "github.com/spacemeshos/post/proving" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" @@ -53,11 +52,13 @@ func TestNIPostBuilderWithMocks(t *testing.T) { } 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()) + nipostClient := NewMocknipostClient(ctrl) + nipostClient.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) + nipostClient.EXPECT().CommitmentAtx().Return(types.EmptyATXID, nil).AnyTimes() + nipostClient.EXPECT().LastOpts().Return(&PostSetupOpts{}).AnyTimes() + + postClient := NewMockPostClient(ctrl) + postClient.EXPECT().Proof(gomock.Any(), gomock.Any()).Times(1) nipostValidator := NewMocknipostValidator(ctrl) nipostValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(nil) @@ -75,7 +76,7 @@ func TestNIPostBuilderWithMocks(t *testing.T) { require.NoError(t, err) nb, err := NewNIPostBuilder( types.NodeID{1}, - postProvider, + nipostClient, poetDb, []string{}, t.TempDir(), @@ -87,6 +88,8 @@ func TestNIPostBuilderWithMocks(t *testing.T) { withPoetClients([]PoetProvingServiceClient{poetProvider}), ) require.NoError(t, err) + nb.Connected(postClient) + nipost, err := nb.BuildNIPost(context.Background(), &challenge) require.NoError(t, err) require.NotNil(t, nipost) @@ -106,13 +109,17 @@ func TestPostSetup(t *testing.T) { PoetProof: types.PoetProof{}, }, []types.Member{types.Member(challenge.Hash())}, nil) - poetDb := NewMockpoetDbAPI(gomock.NewController(t)) + ctrl := gomock.NewController(t) + poetDb := NewMockpoetDbAPI(ctrl) poetDb.EXPECT().ValidateAndStore(gomock.Any(), gomock.Any()).Return(nil) mclock := defaultLayerClockMock(t) - nipostValidator := NewMocknipostValidator(gomock.NewController(t)) + nipostValidator := NewMocknipostValidator(ctrl) nipostValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(1).Return(nil) + postClient := NewMockPostClient(ctrl) + postClient.EXPECT().Proof(gomock.Any(), gomock.Any()).Times(1) + nb, err := NewNIPostBuilder( postProvider.id, postProvider, @@ -127,6 +134,7 @@ func TestPostSetup(t *testing.T) { withPoetClients([]PoetProvingServiceClient{poetProvider}), ) r.NoError(err) + nb.Connected(postClient) r.NoError(postProvider.PrepareInitializer(context.Background(), postProvider.opts)) r.NoError(postProvider.StartSession(context.Background())) @@ -184,6 +192,7 @@ func spawnPoet(tb testing.TB, opts ...HTTPPoetOpt) *HTTPPoetTestHarness { return poetProver } +// TODO(mafa): start post service with supervisor. func buildNIPost(tb testing.TB, postProvider *testPostManager, nipostChallenge types.NIPostChallenge, poetDb poetDbAPI, validator nipostValidator) *types.NIPost { require.NoError(tb, postProvider.PrepareInitializer(context.Background(), postProvider.opts)) require.NoError(tb, postProvider.StartSession(context.Background())) @@ -222,10 +231,6 @@ func buildNIPost(tb testing.TB, postProvider *testPostManager, nipostChallenge t } func TestNewNIPostBuilderNotInitialized(t *testing.T) { - if testing.Short() { - t.Skip() - } - r := require.New(t) challenge := types.NIPostChallenge{ @@ -290,7 +295,7 @@ func TestNewNIPostBuilderNotInitialized(t *testing.T) { logger := logtest.New(t).WithName("validator") verifier, err := NewPostVerifier(postProvider.cfg, logger) r.NoError(err) - defer verifier.Close() + t.Cleanup(func() { assert.NoError(t, verifier.Close()) }) v := NewValidator(poetDb, postProvider.cfg, postProvider.opts.Scrypt, logger, verifier) _, err = v.NIPost( context.Background(), @@ -310,10 +315,10 @@ func TestNIPostBuilder_BuildNIPost(t *testing.T) { ctrl := gomock.NewController(t) nipostValidator := NewMocknipostValidator(ctrl) - postProvider := NewMockpostSetupProvider(ctrl) - postProvider.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}).AnyTimes() - postProvider.EXPECT().CommitmentAtx().Return(types.EmptyATXID, nil).AnyTimes() - postProvider.EXPECT().LastOpts().Return(&PostSetupOpts{}).AnyTimes() + nipostClient := NewMocknipostClient(ctrl) + nipostClient.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}).AnyTimes() + nipostClient.EXPECT().CommitmentAtx().Return(types.EmptyATXID, nil).AnyTimes() + nipostClient.EXPECT().LastOpts().Return(&PostSetupOpts{}).AnyTimes() challenge := types.NIPostChallenge{ PublishEpoch: postGenesisEpoch + 2, @@ -347,7 +352,7 @@ func TestNIPostBuilder_BuildNIPost(t *testing.T) { nodeID := types.NodeID{1} nb, err := NewNIPostBuilder( nodeID, - postProvider, + nipostClient, poetDb, []string{}, dir, @@ -360,7 +365,10 @@ func TestNIPostBuilder_BuildNIPost(t *testing.T) { ) req.NoError(err) - postProvider.EXPECT().GenerateProof(gomock.Any(), gomock.Any(), gomock.Any()) + postClient := NewMockPostClient(ctrl) + postClient.EXPECT().Proof(gomock.Any(), gomock.Any()).Times(1) + nb.Connected(postClient) + 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) @@ -374,7 +382,7 @@ func TestNIPostBuilder_BuildNIPost(t *testing.T) { req.NoError(err) nb, err = NewNIPostBuilder( nodeID, - postProvider, + nipostClient, poetDb, []string{}, dir, @@ -385,7 +393,9 @@ func TestNIPostBuilder_BuildNIPost(t *testing.T) { withPoetClients([]PoetProvingServiceClient{poetProver}), ) req.NoError(err) - postProvider.EXPECT().GenerateProof(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, nil, fmt.Errorf("error")).Times(1) + postClient.EXPECT().Proof(gomock.Any(), gomock.Any()).Return(nil, nil, fmt.Errorf("error")).Times(1) + nb.Connected(postClient) + // check that proof ref is not called again nipost, err = nb.BuildNIPost(context.Background(), &challenge2) req.Nil(nipost) @@ -398,7 +408,7 @@ func TestNIPostBuilder_BuildNIPost(t *testing.T) { req.NoError(err) nb, err = NewNIPostBuilder( nodeID, - postProvider, + nipostClient, poetDb, []string{}, dir, @@ -410,8 +420,10 @@ func TestNIPostBuilder_BuildNIPost(t *testing.T) { withPoetClients([]PoetProvingServiceClient{poetProver}), ) req.NoError(err) - postProvider.EXPECT().GenerateProof(gomock.Any(), gomock.Any(), gomock.Any()).Times(1) + postClient.EXPECT().Proof(gomock.Any(), gomock.Any()).Times(1) + nb.Connected(postClient) 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) @@ -419,7 +431,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()) + postClient.EXPECT().Proof(gomock.Any(), gomock.Any()).Times(1) 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) @@ -471,12 +483,14 @@ func TestNIPostBuilder_ManyPoETs_SubmittingChallenge_DeadlineReached(t *testing. poetCfg := PoetConfig{ PhaseShift: layerDuration * layersPerEpoch / 2, } - 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()).DoAndReturn( - func(ctx context.Context, challenge []byte, _ ...proving.OptionFunc) (*types.Post, *types.PostMetadata, error) { + nipostClient := NewMocknipostClient(ctrl) + nipostClient.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) + nipostClient.EXPECT().CommitmentAtx().Return(types.EmptyATXID, nil).AnyTimes() + nipostClient.EXPECT().LastOpts().Return(&PostSetupOpts{}).AnyTimes() + + postClient := NewMockPostClient(ctrl) + postClient.EXPECT().Proof(gomock.Any(), gomock.Any()).DoAndReturn( + func(ctx context.Context, challenge []byte) (*types.Post, *types.PostMetadata, error) { return &types.Post{}, &types.PostMetadata{ Challenge: challenge, }, nil @@ -485,7 +499,7 @@ func TestNIPostBuilder_ManyPoETs_SubmittingChallenge_DeadlineReached(t *testing. 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, + nipostClient, poetDb, []string{}, t.TempDir(), @@ -499,6 +513,7 @@ func TestNIPostBuilder_ManyPoETs_SubmittingChallenge_DeadlineReached(t *testing. req.NoError(err) // Act + nb.Connected(postClient) nipost, err := nb.BuildNIPost(context.Background(), &challenge) req.NoError(err) @@ -662,21 +677,24 @@ func TestNIPostBuilder_ManyPoETs_AllFinished(t *testing.T) { sig, err := signing.NewEdSigner() req.NoError(err) - 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()).DoAndReturn( - func(_ context.Context, challenge []byte, _ ...proving.OptionFunc) (*types.Post, *types.PostMetadata, error) { + nipostClient := NewMocknipostClient(ctrl) + nipostClient.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) + nipostClient.EXPECT().CommitmentAtx().Return(types.EmptyATXID, nil).AnyTimes() + nipostClient.EXPECT().LastOpts().Return(&PostSetupOpts{}).AnyTimes() + + postClient := NewMockPostClient(ctrl) + postClient.EXPECT().Proof(gomock.Any(), gomock.Any()).DoAndReturn( + func(ctx context.Context, challenge []byte) (*types.Post, *types.PostMetadata, error) { return &types.Post{}, &types.PostMetadata{ Challenge: challenge, }, 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, + nipostClient, poetDb, []string{}, t.TempDir(), @@ -688,6 +706,7 @@ func TestNIPostBuilder_ManyPoETs_AllFinished(t *testing.T) { withPoetClients(poets), ) req.NoError(err) + nb.Connected(postClient) // Act nipost, err := nb.BuildNIPost(context.Background(), &challenge) @@ -703,8 +722,8 @@ func TestNIPostBuilder_Close(t *testing.T) { r := require.New(t) ctrl := gomock.NewController(t) - postProvider := NewMockpostSetupProvider(ctrl) - postProvider.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) + nipostClient := NewMocknipostClient(ctrl) + nipostClient.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) poetProver := spawnPoet(t, WithGenesis(time.Now()), WithEpochDuration(time.Second)) poetDb := NewMockpoetDbAPI(ctrl) challenge := types.NIPostChallenge{ @@ -716,7 +735,7 @@ func TestNIPostBuilder_Close(t *testing.T) { r.NoError(err) nb, err := NewNIPostBuilder( types.NodeID{1}, - postProvider, + nipostClient, poetDb, []string{poetProver.RestURL().String()}, t.TempDir(), @@ -752,15 +771,15 @@ func TestNIPSTBuilder_PoetUnstable(t *testing.T) { ctrl := gomock.NewController(t) poetDb := NewMockpoetDbAPI(ctrl) mclock := defaultLayerClockMock(t) - postProver := NewMockpostSetupProvider(ctrl) - postProver.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) + nipostClient := NewMocknipostClient(ctrl) + nipostClient.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) poetProver := NewMockPoetProvingServiceClient(ctrl) poetProver.EXPECT().PoetServiceID(gomock.Any()).AnyTimes().Return(types.PoetServiceID{}, errors.New("test")) poetProver.EXPECT().Address().Return("http://localhost:9999") nb, err := NewNIPostBuilder( nodeID, - postProver, + nipostClient, poetDb, []string{}, t.TempDir(), @@ -780,8 +799,8 @@ func TestNIPSTBuilder_PoetUnstable(t *testing.T) { ctrl := gomock.NewController(t) poetDb := NewMockpoetDbAPI(ctrl) mclock := defaultLayerClockMock(t) - postProver := NewMockpostSetupProvider(ctrl) - postProver.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) + nipostClient := NewMocknipostClient(ctrl) + nipostClient.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) poetProver := NewMockPoetProvingServiceClient(ctrl) poetProver.EXPECT().PoetServiceID(gomock.Any()).AnyTimes().Return(types.PoetServiceID{ServiceID: []byte{}}, nil) poetProver.EXPECT().Submit(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, errors.New("test")) @@ -790,7 +809,7 @@ func TestNIPSTBuilder_PoetUnstable(t *testing.T) { nb, err := NewNIPostBuilder( nodeID, - postProver, + nipostClient, poetDb, []string{}, t.TempDir(), @@ -811,8 +830,8 @@ func TestNIPSTBuilder_PoetUnstable(t *testing.T) { ctrl := gomock.NewController(t) poetDb := NewMockpoetDbAPI(ctrl) mclock := defaultLayerClockMock(t) - postProver := NewMockpostSetupProvider(ctrl) - postProver.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) + nipostClient := NewMocknipostClient(ctrl) + nipostClient.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) poetProver := NewMockPoetProvingServiceClient(ctrl) poetProver.EXPECT().PoetServiceID(gomock.Any()).AnyTimes().Return(types.PoetServiceID{ServiceID: []byte{}}, nil) poetProver.EXPECT().Submit(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn( @@ -826,7 +845,7 @@ func TestNIPSTBuilder_PoetUnstable(t *testing.T) { nb, err := NewNIPostBuilder( nodeID, - postProver, + nipostClient, poetDb, []string{}, t.TempDir(), @@ -846,14 +865,14 @@ func TestNIPSTBuilder_PoetUnstable(t *testing.T) { ctrl := gomock.NewController(t) poetDb := NewMockpoetDbAPI(ctrl) mclock := defaultLayerClockMock(t) - postProver := NewMockpostSetupProvider(ctrl) - postProver.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) + nipostClient := NewMocknipostClient(ctrl) + nipostClient.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) poetProver := defaultPoetServiceMock(t, []byte("poet"), "http://localhost:9999") poetProver.EXPECT().Proof(gomock.Any(), "").Return(nil, nil, errors.New("failed")) nb, err := NewNIPostBuilder( nodeID, - postProver, + nipostClient, poetDb, []string{}, t.TempDir(), @@ -874,14 +893,14 @@ func TestNIPSTBuilder_PoetUnstable(t *testing.T) { poetDb := NewMockpoetDbAPI(ctrl) poetDb.EXPECT().ValidateAndStore(gomock.Any(), gomock.Any()).Return(nil) mclock := defaultLayerClockMock(t) - postProver := NewMockpostSetupProvider(ctrl) - postProver.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) + nipostClient := NewMocknipostClient(ctrl) + nipostClient.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) poetProver := defaultPoetServiceMock(t, []byte("poet"), "http://localhost:9999") poetProver.EXPECT().Proof(gomock.Any(), "").Return(&types.PoetProofMessage{PoetProof: types.PoetProof{}}, []types.Member{}, nil) nb, err := NewNIPostBuilder( nodeID, - postProver, + nipostClient, poetDb, []string{}, t.TempDir(), @@ -916,8 +935,8 @@ func TestNIPoSTBuilder_StaleChallenge(t *testing.T) { mclock := NewMocklayerClock(ctrl) poetProver := NewMockPoetProvingServiceClient(ctrl) poetProver.EXPECT().Address().Return("http://localhost:9999") - postProver := NewMockpostSetupProvider(ctrl) - postProver.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) + nipostClient := NewMocknipostClient(ctrl) + nipostClient.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) mclock.EXPECT().LayerToTime(gomock.Any()).DoAndReturn( func(got types.LayerID) time.Time { return genesis.Add(layerDuration * time.Duration(got)) @@ -925,7 +944,7 @@ func TestNIPoSTBuilder_StaleChallenge(t *testing.T) { nb, err := NewNIPostBuilder( types.NodeID{1}, - postProver, + nipostClient, poetDb, []string{}, t.TempDir(), @@ -949,8 +968,8 @@ func TestNIPoSTBuilder_StaleChallenge(t *testing.T) { mclock := NewMocklayerClock(ctrl) poetProver := NewMockPoetProvingServiceClient(ctrl) poetProver.EXPECT().Address().Return("http://localhost:9999") - postProver := NewMockpostSetupProvider(ctrl) - postProver.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) + nipostClient := NewMocknipostClient(ctrl) + nipostClient.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) mclock.EXPECT().LayerToTime(gomock.Any()).DoAndReturn( func(got types.LayerID) time.Time { return genesis.Add(layerDuration * time.Duration(got)) @@ -959,7 +978,7 @@ func TestNIPoSTBuilder_StaleChallenge(t *testing.T) { dir := t.TempDir() nb, err := NewNIPostBuilder( types.NodeID{1}, - postProver, + nipostClient, poetDb, []string{}, dir, @@ -988,8 +1007,8 @@ func TestNIPoSTBuilder_StaleChallenge(t *testing.T) { mclock := NewMocklayerClock(ctrl) poetProver := NewMockPoetProvingServiceClient(ctrl) poetProver.EXPECT().Address().Return("http://localhost:9999") - postProver := NewMockpostSetupProvider(ctrl) - postProver.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) + nipostClient := NewMocknipostClient(ctrl) + nipostClient.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) mclock.EXPECT().LayerToTime(gomock.Any()).DoAndReturn( func(got types.LayerID) time.Time { return genesis.Add(layerDuration * time.Duration(got)) @@ -998,7 +1017,7 @@ func TestNIPoSTBuilder_StaleChallenge(t *testing.T) { dir := t.TempDir() nb, err := NewNIPostBuilder( types.NodeID{1}, - postProver, + nipostClient, poetDb, []string{}, dir, @@ -1065,22 +1084,25 @@ func TestNIPoSTBuilder_Continues_After_Interrupted(t *testing.T) { poetCfg := PoetConfig{ PhaseShift: layerDuration * layersPerEpoch / 2, } - postProvider := NewMockpostSetupProvider(ctrl) - postProvider.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}).Times(2) - postProvider.EXPECT().CommitmentAtx().Return(types.EmptyATXID, nil).AnyTimes() - postProvider.EXPECT().LastOpts().Return(&PostSetupOpts{}).AnyTimes() - postProvider.EXPECT().GenerateProof(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn( - func(ctx context.Context, challenge []byte, _ ...proving.OptionFunc) (*types.Post, *types.PostMetadata, error) { + nipostClient := NewMocknipostClient(ctrl) + nipostClient.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}).Times(2) + nipostClient.EXPECT().CommitmentAtx().Return(types.EmptyATXID, nil).AnyTimes() + nipostClient.EXPECT().LastOpts().Return(&PostSetupOpts{}).AnyTimes() + + postClient := NewMockPostClient(ctrl) + postClient.EXPECT().Proof(gomock.Any(), gomock.Any()).DoAndReturn( + func(ctx context.Context, challenge []byte) (*types.Post, *types.PostMetadata, error) { return &types.Post{}, &types.PostMetadata{ Challenge: challenge, }, nil }, ) + nipostValidator := NewMocknipostValidator(ctrl) 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, + nipostClient, poetDb, []string{}, t.TempDir(), @@ -1092,6 +1114,7 @@ func TestNIPoSTBuilder_Continues_After_Interrupted(t *testing.T) { withPoetClients([]PoetProvingServiceClient{poet}), ) req.NoError(err) + nb.Connected(postClient) // Act nipost, err := nb.BuildNIPost(buildCtx, &challenge) @@ -1176,11 +1199,10 @@ func TestNIPostBuilder_Mainnet_Poet_Workaround(t *testing.T) { } 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()) + nipostClient := NewMocknipostClient(ctrl) + nipostClient.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) + nipostClient.EXPECT().CommitmentAtx().Return(types.EmptyATXID, nil).AnyTimes() + nipostClient.EXPECT().LastOpts().Return(&PostSetupOpts{}).AnyTimes() nipostValidator := NewMocknipostValidator(ctrl) nipostValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(nil) @@ -1227,6 +1249,9 @@ func TestNIPostBuilder_Mainnet_Poet_Workaround(t *testing.T) { }, ) + postClient := NewMockPostClient(ctrl) + postClient.EXPECT().Proof(gomock.Any(), gomock.Any()) + sig, err := signing.NewEdSigner() require.NoError(t, err) poetCfg := PoetConfig{ @@ -1234,7 +1259,7 @@ func TestNIPostBuilder_Mainnet_Poet_Workaround(t *testing.T) { } nb, err := NewNIPostBuilder( types.NodeID{1}, - postProvider, + nipostClient, poetDb, []string{}, t.TempDir(), @@ -1246,6 +1271,8 @@ func TestNIPostBuilder_Mainnet_Poet_Workaround(t *testing.T) { withPoetClients(poets), ) require.NoError(t, err) + nb.Connected(postClient) + nipost, err := nb.BuildNIPost(context.Background(), &challenge) require.NoError(t, err) require.NotNil(t, nipost) diff --git a/activation/post_test.go b/activation/post_test.go index 5a21916799..fd64a1db0a 100644 --- a/activation/post_test.go +++ b/activation/post_test.go @@ -420,6 +420,7 @@ func withPostConfig(cfg PostConfig) newPostSetupMgrOptionFunc { } } +// TODO(mafa): start post service with supervisor. func newTestPostManager(tb testing.TB, o ...newPostSetupMgrOptionFunc) *testPostManager { tb.Helper() diff --git a/api/grpcserver/smesher_service_test.go b/api/grpcserver/smesher_service_test.go index 3de923770c..87423be59d 100644 --- a/api/grpcserver/smesher_service_test.go +++ b/api/grpcserver/smesher_service_test.go @@ -19,7 +19,7 @@ import ( func TestPostConfig(t *testing.T) { ctrl := gomock.NewController(t) - postSetupProvider := activation.NewMockpostSetupProvider(ctrl) + postSetupProvider := grpcserver.NewMockpostSetupProvider(ctrl) smeshingProvider := activation.NewMockSmeshingProvider(ctrl) svc := grpcserver.NewSmesherService(postSetupProvider, smeshingProvider, time.Second, activation.DefaultPostSetupOpts()) @@ -45,7 +45,7 @@ func TestPostConfig(t *testing.T) { func TestStartSmeshingPassesCorrectSmeshingOpts(t *testing.T) { ctrl := gomock.NewController(t) - postSetupProvider := activation.NewMockpostSetupProvider(ctrl) + postSetupProvider := grpcserver.NewMockpostSetupProvider(ctrl) smeshingProvider := activation.NewMockSmeshingProvider(ctrl) svc := grpcserver.NewSmesherService(postSetupProvider, smeshingProvider, time.Second, activation.DefaultPostSetupOpts()) @@ -79,7 +79,7 @@ func TestStartSmeshingPassesCorrectSmeshingOpts(t *testing.T) { func TestSmesherService_PostSetupProviders(t *testing.T) { ctrl := gomock.NewController(t) - postSetupProvider := activation.NewMockpostSetupProvider(ctrl) + postSetupProvider := grpcserver.NewMockpostSetupProvider(ctrl) smeshingProvider := activation.NewMockSmeshingProvider(ctrl) svc := grpcserver.NewSmesherService(postSetupProvider, smeshingProvider, time.Second, activation.DefaultPostSetupOpts()) @@ -120,7 +120,7 @@ func TestSmesherService_PostSetupProviders(t *testing.T) { func TestSmesherService_PostSetupStatus(t *testing.T) { t.Run("completed", func(t *testing.T) { ctrl := gomock.NewController(t) - postSetupProvider := activation.NewMockpostSetupProvider(ctrl) + postSetupProvider := grpcserver.NewMockpostSetupProvider(ctrl) smeshingProvider := activation.NewMockSmeshingProvider(ctrl) svc := grpcserver.NewSmesherService(postSetupProvider, smeshingProvider, time.Second, activation.DefaultPostSetupOpts()) @@ -138,7 +138,7 @@ func TestSmesherService_PostSetupStatus(t *testing.T) { t.Run("completed with last Opts", func(t *testing.T) { ctrl := gomock.NewController(t) - postSetupProvider := activation.NewMockpostSetupProvider(ctrl) + postSetupProvider := grpcserver.NewMockpostSetupProvider(ctrl) smeshingProvider := activation.NewMockSmeshingProvider(ctrl) svc := grpcserver.NewSmesherService(postSetupProvider, smeshingProvider, time.Second, activation.DefaultPostSetupOpts()) @@ -169,7 +169,7 @@ func TestSmesherService_PostSetupStatus(t *testing.T) { t.Run("in progress", func(t *testing.T) { ctrl := gomock.NewController(t) - postSetupProvider := activation.NewMockpostSetupProvider(ctrl) + postSetupProvider := grpcserver.NewMockpostSetupProvider(ctrl) smeshingProvider := activation.NewMockSmeshingProvider(ctrl) svc := grpcserver.NewSmesherService(postSetupProvider, smeshingProvider, time.Second, activation.DefaultPostSetupOpts()) From ed731ece32d183efc561aa744bdce7b269cf253f Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Thu, 5 Oct 2023 09:46:18 +0000 Subject: [PATCH 04/40] Add postConnection listeners to grpc service --- node/node.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node/node.go b/node/node.go index 342fed2ef5..1c7416660c 100644 --- a/node/node.go +++ b/node/node.go @@ -1096,7 +1096,7 @@ func (app *App) initService(ctx context.Context, svc grpcserver.Service) (grpcse case grpcserver.Smesher: return grpcserver.NewSmesherService(app.postSetupMgr, app.atxBuilder, app.Config.API.SmesherStreamInterval, app.Config.SMESHING.Opts), nil case grpcserver.Post: - return grpcserver.NewPostService(app.log.Zap()), nil + return grpcserver.NewPostService(app.log.Zap(), app.nipostBuilder, app.atxBuilder), nil case grpcserver.Transaction: return grpcserver.NewTransactionService(app.db, app.host, app.mesh, app.conState, app.syncer, app.txHandler), nil case grpcserver.Activation: From c76e0c48fa1c8aaa7dff40b26fb526d04d044c82 Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Thu, 5 Oct 2023 11:42:31 +0000 Subject: [PATCH 05/40] Use zap logger directly --- activation/nipost_test.go | 5 ++--- activation/post_verifier.go | 9 +++++---- activation/post_verifier_test.go | 4 ++-- activation/validation.go | 6 ++---- activation/validation_test.go | 16 +++++++--------- 5 files changed, 18 insertions(+), 22 deletions(-) diff --git a/activation/nipost_test.go b/activation/nipost_test.go index d4576d469d..f9fc92ea0d 100644 --- a/activation/nipost_test.go +++ b/activation/nipost_test.go @@ -292,11 +292,10 @@ func TestNewNIPostBuilderNotInitialized(t *testing.T) { r.NoError(err) r.NotNil(nipost) - logger := logtest.New(t).WithName("validator") - verifier, err := NewPostVerifier(postProvider.cfg, logger) + verifier, err := NewPostVerifier(postProvider.cfg, zaptest.NewLogger(t).Named("verifier")) r.NoError(err) t.Cleanup(func() { assert.NoError(t, verifier.Close()) }) - v := NewValidator(poetDb, postProvider.cfg, postProvider.opts.Scrypt, logger, verifier) + v := NewValidator(poetDb, postProvider.cfg, postProvider.opts.Scrypt, verifier) _, err = v.NIPost( context.Background(), postProvider.id, diff --git a/activation/post_verifier.go b/activation/post_verifier.go index 765830065a..2fb9ed10a7 100644 --- a/activation/post_verifier.go +++ b/activation/post_verifier.go @@ -7,6 +7,7 @@ import ( "github.com/spacemeshos/post/config" "github.com/spacemeshos/post/shared" "github.com/spacemeshos/post/verifying" + "go.uber.org/zap" "golang.org/x/sync/errgroup" "github.com/spacemeshos/go-spacemesh/common/types" @@ -37,17 +38,17 @@ type postVerifierWorker struct { type postVerifier struct { *verifying.ProofVerifier - logger log.Log + logger *zap.Logger cfg config.Config } func (v *postVerifier) Verify(ctx context.Context, p *shared.Proof, m *shared.ProofMetadata, opts ...verifying.OptionFunc) error { - v.logger.WithContext(ctx).With().Debug("verifying post", log.FieldNamed("proof_node_id", types.BytesToNodeID(m.NodeId))) - return v.ProofVerifier.Verify(p, m, v.cfg, v.logger.Zap(), opts...) + v.logger.Debug("verifying post", zap.Stringer("proof_node_id", types.BytesToNodeID(m.NodeId))) + return v.ProofVerifier.Verify(p, m, v.cfg, v.logger, opts...) } // NewPostVerifier creates a new post verifier. -func NewPostVerifier(cfg PostConfig, logger log.Log, opts ...verifying.OptionFunc) (PostVerifier, error) { +func NewPostVerifier(cfg PostConfig, logger *zap.Logger, opts ...verifying.OptionFunc) (PostVerifier, error) { verifier, err := verifying.NewProofVerifier(opts...) if err != nil { return nil, err diff --git a/activation/post_verifier_test.go b/activation/post_verifier_test.go index 6c12d3d893..2abad47d1a 100644 --- a/activation/post_verifier_test.go +++ b/activation/post_verifier_test.go @@ -9,11 +9,11 @@ import ( "github.com/spacemeshos/post/shared" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" + "go.uber.org/zap/zaptest" "golang.org/x/sync/errgroup" "github.com/spacemeshos/go-spacemesh/activation" "github.com/spacemeshos/go-spacemesh/log" - "github.com/spacemeshos/go-spacemesh/log/logtest" ) func TestOffloadingPostVerifier(t *testing.T) { @@ -41,7 +41,7 @@ func TestOffloadingPostVerifier(t *testing.T) { } func TestPostVerifierDetectsInvalidProof(t *testing.T) { - verifier, err := activation.NewPostVerifier(activation.PostConfig{}, logtest.New(t)) + verifier, err := activation.NewPostVerifier(activation.PostConfig{}, zaptest.NewLogger(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 4b8b82852d..8274bcae15 100644 --- a/activation/validation.go +++ b/activation/validation.go @@ -15,7 +15,6 @@ import ( "github.com/spacemeshos/go-spacemesh/activation/metrics" "github.com/spacemeshos/go-spacemesh/common/types" "github.com/spacemeshos/go-spacemesh/common/util" - "github.com/spacemeshos/go-spacemesh/log" ) type ErrAtxNotFound struct { @@ -42,13 +41,12 @@ 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, scrypt config.ScryptParams, log log.Log, postVerifier PostVerifier) *Validator { - return &Validator{poetDb, cfg, scrypt, log, postVerifier} +func NewValidator(poetDb poetDbAPI, cfg PostConfig, scrypt config.ScryptParams, postVerifier PostVerifier) *Validator { + return &Validator{poetDb, cfg, scrypt, postVerifier} } // NIPost validates a NIPost, given a node id and expected challenge. It returns an error if the NIPost is invalid. diff --git a/activation/validation_test.go b/activation/validation_test.go index 226562f733..13368d2a5c 100644 --- a/activation/validation_test.go +++ b/activation/validation_test.go @@ -13,8 +13,6 @@ import ( "go.uber.org/mock/gomock" "github.com/spacemeshos/go-spacemesh/common/types" - "github.com/spacemeshos/go-spacemesh/log/logtest" - "github.com/spacemeshos/go-spacemesh/sql" ) func Test_Validation_VRFNonce(t *testing.T) { @@ -48,7 +46,7 @@ func Test_Validation_VRFNonce(t *testing.T) { nonce := (*types.VRFPostIndex)(init.Nonce()) - v := NewValidator(poetDbAPI, postCfg, initOpts.Scrypt, logtest.New(t).WithName("validator"), nil) + v := NewValidator(poetDbAPI, postCfg, initOpts.Scrypt, nil) // Act & Assert t.Run("valid vrf nonce", func(t *testing.T) { @@ -89,7 +87,7 @@ func Test_Validation_InitialNIPostChallenge(t *testing.T) { postCfg := DefaultPostConfig() goldenATXID := types.ATXID{2, 3, 4} - v := NewValidator(poetDbAPI, postCfg, config.ScryptParams{}, logtest.New(t).WithName("validator"), nil) + v := NewValidator(poetDbAPI, postCfg, config.ScryptParams{}, nil) // Act & Assert t.Run("valid initial nipost challenge passes", func(t *testing.T) { @@ -157,7 +155,7 @@ func Test_Validation_NIPostChallenge(t *testing.T) { poetDbAPI := NewMockpoetDbAPI(ctrl) postCfg := DefaultPostConfig() - v := NewValidator(poetDbAPI, postCfg, config.ScryptParams{}, logtest.New(t).WithName("validator"), nil) + v := NewValidator(poetDbAPI, postCfg, config.ScryptParams{}, nil) // Act & Assert t.Run("valid nipost challenge passes", func(t *testing.T) { @@ -283,7 +281,7 @@ func Test_Validation_Post(t *testing.T) { postCfg := DefaultPostConfig() postVerifier := NewMockPostVerifier(ctrl) - v := NewValidator(poetDbAPI, postCfg, config.ScryptParams{}, logtest.New(t).WithName("validator"), postVerifier) + v := NewValidator(poetDbAPI, postCfg, config.ScryptParams{}, postVerifier) post := types.Post{} meta := types.PostMetadata{} @@ -305,7 +303,7 @@ func Test_Validation_PositioningAtx(t *testing.T) { poetDbAPI := NewMockpoetDbAPI(ctrl) postCfg := DefaultPostConfig() - v := NewValidator(poetDbAPI, postCfg, config.ScryptParams{}, logtest.New(t).WithName("validator"), nil) + v := NewValidator(poetDbAPI, postCfg, config.ScryptParams{}, nil) // Act & Assert t.Run("valid nipost challenge passes", func(t *testing.T) { @@ -409,7 +407,7 @@ func Test_Validate_NumUnits(t *testing.T) { poetDbAPI := NewMockpoetDbAPI(ctrl) postCfg := DefaultPostConfig() - v := NewValidator(poetDbAPI, postCfg, config.ScryptParams{}, logtest.New(t).WithName("validator"), nil) + v := NewValidator(poetDbAPI, postCfg, config.ScryptParams{}, nil) // Act & Assert t.Run("valid number of num units passes", func(t *testing.T) { @@ -443,7 +441,7 @@ func Test_Validate_PostMetadata(t *testing.T) { poetDbAPI := NewMockpoetDbAPI(ctrl) postCfg := DefaultPostConfig() - v := NewValidator(poetDbAPI, postCfg, config.ScryptParams{}, logtest.New(t).WithName("validator"), nil) + v := NewValidator(poetDbAPI, postCfg, config.ScryptParams{}, nil) // Act & Assert t.Run("valid post metadata", func(t *testing.T) { From 234b2649102bd1bba48cc56f3094882b03bbb01c Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Thu, 5 Oct 2023 16:10:24 +0000 Subject: [PATCH 06/40] Fix failing tests --- activation/nipost_integration_test.go.bak | 315 ++++++++++++++++++ activation/nipost_test.go | 202 ----------- activation/poet_integration_test.go | 135 ++++++++ activation/poet_test.go | 104 ------ activation/poet_test_harness.go | 71 ---- activation/post_supervisor.go | 36 +- activation/post_test.go | 23 +- activation/validation_integration_test.go.bak | 64 ++++ activation/validation_test.go | 49 --- api/grpcserver/post_client.go | 19 +- api/grpcserver/post_service_test.go | 2 +- common/types/activation.go | 6 + common/types/nodeid.go | 2 +- config/config.go | 2 +- config/mainnet.go | 13 +- config/presets/fastnet.go | 5 + config/presets/standalone.go | 8 +- node/node.go | 12 +- node/node_test.go | 19 +- 19 files changed, 606 insertions(+), 481 deletions(-) create mode 100644 activation/nipost_integration_test.go.bak create mode 100644 activation/poet_integration_test.go delete mode 100644 activation/poet_test_harness.go create mode 100644 activation/validation_integration_test.go.bak diff --git a/activation/nipost_integration_test.go.bak b/activation/nipost_integration_test.go.bak new file mode 100644 index 0000000000..00ff706b5c --- /dev/null +++ b/activation/nipost_integration_test.go.bak @@ -0,0 +1,315 @@ +package activation_test + +import ( + "context" + "errors" + "os" + "testing" + "time" + + "github.com/spacemeshos/poet/logging" + "github.com/spacemeshos/post/config" + "github.com/spacemeshos/post/initialization" + "github.com/stretchr/testify/require" + "github.com/zeebo/assert" + "go.uber.org/mock/gomock" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" + "go.uber.org/zap/zaptest" + "golang.org/x/sync/errgroup" + + "github.com/spacemeshos/go-spacemesh/activation" + "github.com/spacemeshos/go-spacemesh/common/types" + "github.com/spacemeshos/go-spacemesh/datastore" + "github.com/spacemeshos/go-spacemesh/log/logtest" + "github.com/spacemeshos/go-spacemesh/signing" + "github.com/spacemeshos/go-spacemesh/sql" +) + +const ( + layersPerEpoch = 10 + layerDuration = time.Second + postGenesisEpoch types.EpochID = 2 +) + +func TestMain(m *testing.M) { + types.SetLayersPerEpoch(layersPerEpoch) + res := m.Run() + os.Exit(res) +} + +func initPost(tb testing.TB, log *zap.Logger, dir string) { + tb.Helper() + + cfg := activation.DefaultPostConfig() + + sig, err := signing.NewEdSigner() + require.NoError(tb, err) + id := sig.NodeID() + + opts := activation.DefaultPostSetupOpts() + opts.DataDir = dir + opts.ProviderID.SetInt64(int64(initialization.CPUProviderID())) + opts.Scrypt.N = 2 // Speedup initialization in tests. + + goldenATXID := types.ATXID{2, 3, 4} + + cdb := datastore.NewCachedDB(sql.InMemory(), logtest.New(tb)) + provingOpts := activation.DefaultPostProvingOpts() + provingOpts.Flags = config.RecommendedPowFlags() + mgr, err := activation.NewPostSetupManager(id, cfg, log.Named("manager"), cdb, goldenATXID, provingOpts) + require.NoError(tb, err) + + ctx, cancel := context.WithCancel(context.Background()) + tb.Cleanup(cancel) + + var eg errgroup.Group + lastStatus := &activation.PostSetupStatus{} + eg.Go(func() error { + timer := time.NewTicker(50 * time.Millisecond) + defer timer.Stop() + + for { + select { + case <-ctx.Done(): + return ctx.Err() + case <-timer.C: + status := mgr.Status() + require.GreaterOrEqual(tb, status.NumLabelsWritten, lastStatus.NumLabelsWritten) + + if status.NumLabelsWritten == uint64(opts.NumUnits)*cfg.LabelsPerUnit { + return nil + } + require.Equal(tb, activation.PostSetupStateInProgress, status.State) + } + } + }) + + // Create data. + require.NoError(tb, mgr.PrepareInitializer(context.Background(), opts)) + require.NoError(tb, mgr.StartSession(context.Background())) + require.NoError(tb, eg.Wait()) + require.Equal(tb, activation.PostSetupStateComplete, mgr.Status().State) +} + +func spawnPoet(tb testing.TB, opts ...HTTPPoetOpt) *HTTPPoetTestHarness { + tb.Helper() + ctx, cancel := context.WithCancel(logging.NewContext(context.Background(), zaptest.NewLogger(tb))) + + poetProver, err := NewHTTPPoetTestHarness(ctx, tb.TempDir(), opts...) + require.NoError(tb, err) + require.NotNil(tb, poetProver) + + var eg errgroup.Group + tb.Cleanup(func() { + cancel() + eg.Wait() + }) + eg.Go(func() error { + err := poetProver.Service.Start(ctx) + return errors.Join(err, poetProver.Service.Close()) + }) + + return poetProver +} + +// TODO(mafa): start post service with supervisor. +func buildNIPost(tb testing.TB, postProvider *testPostManager, nipostChallenge types.NIPostChallenge, poetDb poetDbAPI, validator nipostValidator) *types.NIPost { + require.NoError(tb, postProvider.PrepareInitializer(context.Background(), postProvider.opts)) + require.NoError(tb, postProvider.StartSession(context.Background())) + mclock := activation.NewMocklayerClock(gomock.NewController(tb)) + mclock.EXPECT().LayerToTime(gomock.Any()).AnyTimes().DoAndReturn( + func(got types.LayerID) time.Time { + // time.Now() ~= currentLayer + genesis := time.Now().Add(-time.Duration(postGenesisEpoch.FirstLayer()) * layerDuration) + return genesis.Add(layerDuration * time.Duration(got)) + }, + ) + + epoch := layersPerEpoch * layerDuration + poetCfg := activation.PoetConfig{ + PhaseShift: epoch / 2, + CycleGap: epoch / 5, + GracePeriod: epoch / 5, + RequestTimeout: epoch / 5, + RequestRetryDelay: epoch / 50, + MaxRequestRetries: 10, + } + + poetProver := spawnPoet(tb, WithGenesis(time.Now()), WithEpochDuration(epoch), WithPhaseShift(poetCfg.PhaseShift), WithCycleGap(poetCfg.CycleGap)) + + signer, err := signing.NewEdSigner() + require.NoError(tb, err) + nb, err := activation.NewNIPostBuilder( + postProvider.id, + postProvider, + poetDb, + []string{poetProver.RestURL().String()}, + tb.TempDir(), + logtest.New(tb, zapcore.DebugLevel), + signer, + poetCfg, + mclock, + activation.WithNipostValidator(validator), + ) + require.NoError(tb, err) + nipost, err := nb.BuildNIPost(context.Background(), &nipostChallenge) + require.NoError(tb, err) + return nipost +} + +func TestNIPostBuilderWithClients(t *testing.T) { + challenge := types.NIPostChallenge{ + PublishEpoch: postGenesisEpoch + 2, + } + poetDb := activation.NewPoetDb(sql.InMemory(), logtest.New(t).WithName("poetDb")) + postCfg := activation.DefaultPostConfig() + postCfg.PowDifficulty[0] = 1 + postProvider := newTestPostManager(t, withPostConfig(postCfg)) + verifier, err := activation.NewPostVerifier(postProvider.Config(), zaptest.NewLogger(t).Named("verifier")) + require.NoError(t, err) + defer verifier.Close() + + v := activation.NewValidator(poetDb, postProvider.Config(), postProvider.opts.Scrypt, verifier) + nipost := buildNIPost(t, postProvider, challenge, poetDb, v) + _, err = v.NIPost( + context.Background(), + postProvider.id, + postProvider.commitmentAtxId, + nipost, + challenge.Hash(), + postProvider.opts.NumUnits, + ) + require.NoError(t, err) +} + +func TestNIPostBuilder_Close(t *testing.T) { + t.Parallel() + r := require.New(t) + + ctrl := gomock.NewController(t) + nipostClient := activation.NewMocknipostClient(ctrl) + nipostClient.EXPECT().Status().Return(&activation.PostSetupStatus{State: activation.PostSetupStateComplete}) + poetProver := spawnPoet(t, WithGenesis(time.Now()), WithEpochDuration(time.Second)) + poetDb := activation.NewMockpoetDbAPI(ctrl) + challenge := types.NIPostChallenge{ + PublishEpoch: postGenesisEpoch + 2, + } + mclock := activation.NewMocklayerClock(gomock.NewController(t)) + mclock.EXPECT().LayerToTime(gomock.Any()).AnyTimes().DoAndReturn( + func(got types.LayerID) time.Time { + // time.Now() ~= currentLayer + genesis := time.Now().Add(-time.Duration(postGenesisEpoch.FirstLayer()) * layerDuration) + return genesis.Add(layerDuration * time.Duration(got)) + }, + ) + + sig, err := signing.NewEdSigner() + r.NoError(err) + nb, err := activation.NewNIPostBuilder( + types.NodeID{1}, + nipostClient, + poetDb, + []string{poetProver.RestURL().String()}, + t.TempDir(), + logtest.New(t), + sig, + activation.PoetConfig{}, + mclock, + ) + r.NoError(err) + + ctx, cancel := context.WithCancel(context.Background()) + cancel() + nipost, err := nb.BuildNIPost(ctx, &challenge) + r.ErrorIs(err, context.Canceled) + r.Nil(nipost) +} + +func TestNewNIPostBuilderNotInitialized(t *testing.T) { + r := require.New(t) + + challenge := types.NIPostChallenge{ + PublishEpoch: postGenesisEpoch + 2, + } + challengeHash := challenge.Hash() + + postProvider := newTestPostManager(t) + + epoch := layersPerEpoch * layerDuration + poetCfg := activation.PoetConfig{ + PhaseShift: epoch / 5, + CycleGap: epoch / 10, + GracePeriod: epoch / 10, + RequestTimeout: epoch / 10, + RequestRetryDelay: epoch / 100, + MaxRequestRetries: 10, + } + + poetClient := activation.NewMockPoetProvingServiceClient(gomock.NewController(t)) + poetClient.EXPECT().Submit(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(&types.PoetRound{}, nil) + poetClient.EXPECT().PoetServiceID(gomock.Any()).Return(types.PoetServiceID{ServiceID: []byte("poet")}, nil) + poetClient.EXPECT().PowParams(gomock.Any()).Return(&activation.PoetPowParams{}, nil) + poetClient.EXPECT().Address().Return("http://localhost:9999") + poetClient.EXPECT().Proof(gomock.Any(), "").Return(&types.PoetProofMessage{ + PoetProof: types.PoetProof{}, + }, []types.Member{types.Member(challenge.Hash())}, nil) + + ctrl := gomock.NewController(t) + poetDb := activation.NewMockpoetDbAPI(ctrl) + poetDb.EXPECT().GetProof(gomock.Any()).Return( + &types.PoetProof{}, &challengeHash, nil, + ) + poetDb.EXPECT().ValidateAndStore(gomock.Any(), gomock.Any()).Return(nil) + mclock := activation.NewMocklayerClock(gomock.NewController(t)) + mclock.EXPECT().LayerToTime(gomock.Any()).AnyTimes().DoAndReturn( + func(got types.LayerID) time.Time { + // time.Now() ~= currentLayer + genesis := time.Now().Add(-time.Duration(postGenesisEpoch.FirstLayer()) * layerDuration) + return genesis.Add(layerDuration * time.Duration(got)) + }, + ) + + nipostValidator := activation.NewMocknipostValidator(ctrl) + nipostValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(1).Return(nil) + + nb, err := activation.NewNIPostBuilder( + postProvider.id, + postProvider, + poetDb, + []string{}, + t.TempDir(), + logtest.New(t), + postProvider.signer, + poetCfg, + mclock, + activation.WithNipostValidator(nipostValidator), + withPoetClients([]activation.PoetProvingServiceClient{poetProvider}), + ) + require.NoError(t, err) + + nipost, err := nb.BuildNIPost(context.Background(), &challenge) + r.EqualError(err, "post setup not complete") + r.Nil(nipost) + + r.NoError(postProvider.PrepareInitializer(context.Background(), postProvider.opts)) + r.NoError(postProvider.StartSession(context.Background())) + + nipost, err = nb.BuildNIPost(context.Background(), &challenge) + r.NoError(err) + r.NotNil(nipost) + + verifier, err := activation.NewPostVerifier(postProvider.cfg, zaptest.NewLogger(t).Named("verifier")) + r.NoError(err) + t.Cleanup(func() { assert.NoError(t, verifier.Close()) }) + v := activation.NewValidator(poetDb, postProvider.cfg, postProvider.opts.Scrypt, verifier) + _, err = v.NIPost( + context.Background(), + postProvider.id, + postProvider.goldenATXID, + nipost, + challenge.Hash(), + postProvider.opts.NumUnits, + ) + r.NoError(err) +} diff --git a/activation/nipost_test.go b/activation/nipost_test.go index f9fc92ea0d..ad545c5940 100644 --- a/activation/nipost_test.go +++ b/activation/nipost_test.go @@ -8,18 +8,14 @@ import ( "time" "github.com/spacemeshos/go-scale/tester" - "github.com/spacemeshos/poet/logging" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "go.uber.org/zap/zapcore" - "go.uber.org/zap/zaptest" - "golang.org/x/sync/errgroup" "github.com/spacemeshos/go-spacemesh/common/types" "github.com/spacemeshos/go-spacemesh/log/logtest" "github.com/spacemeshos/go-spacemesh/signing" - "github.com/spacemeshos/go-spacemesh/sql" ) func defaultPoetServiceMock(tb testing.TB, id []byte, address string) *MockPoetProvingServiceClient { @@ -145,168 +141,6 @@ func TestPostSetup(t *testing.T) { r.NotNil(nipost) } -func TestNIPostBuilderWithClients(t *testing.T) { - challenge := types.NIPostChallenge{ - PublishEpoch: postGenesisEpoch + 2, - } - poetDb := NewPoetDb(sql.InMemory(), logtest.New(t).WithName("poetDb")) - postCfg := DefaultPostConfig() - postCfg.PowDifficulty[0] = 1 - postProvider := newTestPostManager(t, withPostConfig(postCfg)) - logger := logtest.New(t).WithName("validator") - verifier, err := NewPostVerifier(postProvider.Config(), logger) - require.NoError(t, err) - defer verifier.Close() - - v := NewValidator(poetDb, postProvider.Config(), postProvider.opts.Scrypt, logger, verifier) - nipost := buildNIPost(t, postProvider, challenge, poetDb, v) - _, err = v.NIPost( - context.Background(), - postProvider.id, - postProvider.commitmentAtxId, - nipost, - challenge.Hash(), - postProvider.opts.NumUnits, - ) - require.NoError(t, err) -} - -func spawnPoet(tb testing.TB, opts ...HTTPPoetOpt) *HTTPPoetTestHarness { - tb.Helper() - ctx, cancel := context.WithCancel(logging.NewContext(context.Background(), zaptest.NewLogger(tb))) - - poetProver, err := NewHTTPPoetTestHarness(ctx, tb.TempDir(), opts...) - require.NoError(tb, err) - require.NotNil(tb, poetProver) - - var eg errgroup.Group - tb.Cleanup(func() { - cancel() - eg.Wait() - }) - eg.Go(func() error { - err := poetProver.Service.Start(ctx) - return errors.Join(err, poetProver.Service.Close()) - }) - - return poetProver -} - -// TODO(mafa): start post service with supervisor. -func buildNIPost(tb testing.TB, postProvider *testPostManager, nipostChallenge types.NIPostChallenge, poetDb poetDbAPI, validator nipostValidator) *types.NIPost { - require.NoError(tb, postProvider.PrepareInitializer(context.Background(), postProvider.opts)) - require.NoError(tb, postProvider.StartSession(context.Background())) - mclock := defaultLayerClockMock(tb) - - epoch := layersPerEpoch * layerDuration - poetCfg := PoetConfig{ - PhaseShift: epoch / 2, - CycleGap: epoch / 5, - GracePeriod: epoch / 5, - RequestTimeout: epoch / 5, - RequestRetryDelay: epoch / 50, - MaxRequestRetries: 10, - } - - poetProver := spawnPoet(tb, WithGenesis(time.Now()), WithEpochDuration(epoch), WithPhaseShift(poetCfg.PhaseShift), WithCycleGap(poetCfg.CycleGap)) - - signer, err := signing.NewEdSigner() - require.NoError(tb, err) - nb, err := NewNIPostBuilder( - postProvider.id, - postProvider, - poetDb, - []string{poetProver.RestURL().String()}, - tb.TempDir(), - logtest.New(tb, zapcore.DebugLevel), - signer, - poetCfg, - mclock, - WithNipostValidator(validator), - ) - require.NoError(tb, err) - nipost, err := nb.BuildNIPost(context.Background(), &nipostChallenge) - require.NoError(tb, err) - return nipost -} - -func TestNewNIPostBuilderNotInitialized(t *testing.T) { - r := require.New(t) - - challenge := types.NIPostChallenge{ - PublishEpoch: postGenesisEpoch + 2, - } - challengeHash := challenge.Hash() - - postProvider := newTestPostManager(t) - - epoch := layersPerEpoch * layerDuration - poetCfg := PoetConfig{ - PhaseShift: epoch / 5, - CycleGap: epoch / 10, - GracePeriod: epoch / 10, - RequestTimeout: epoch / 10, - RequestRetryDelay: epoch / 100, - MaxRequestRetries: 10, - } - - poetProvider := defaultPoetServiceMock(t, []byte("poet"), "http://localhost:9999") - poetProvider.EXPECT().Proof(gomock.Any(), "").Return(&types.PoetProofMessage{ - PoetProof: types.PoetProof{}, - }, []types.Member{types.Member(challenge.Hash())}, nil) - - ctrl := gomock.NewController(t) - poetDb := NewMockpoetDbAPI(ctrl) - poetDb.EXPECT().GetProof(gomock.Any()).Return( - &types.PoetProof{}, &challengeHash, nil, - ) - poetDb.EXPECT().ValidateAndStore(gomock.Any(), gomock.Any()).Return(nil) - mclock := defaultLayerClockMock(t) - - nipostValidator := NewMocknipostValidator(ctrl) - nipostValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(1).Return(nil) - - nb, err := NewNIPostBuilder( - postProvider.id, - postProvider, - poetDb, - []string{}, - t.TempDir(), - logtest.New(t), - postProvider.signer, - poetCfg, - mclock, - WithNipostValidator(nipostValidator), - withPoetClients([]PoetProvingServiceClient{poetProvider}), - ) - require.NoError(t, err) - - nipost, err := nb.BuildNIPost(context.Background(), &challenge) - r.EqualError(err, "post setup not complete") - r.Nil(nipost) - - r.NoError(postProvider.PrepareInitializer(context.Background(), postProvider.opts)) - r.NoError(postProvider.StartSession(context.Background())) - - nipost, err = nb.BuildNIPost(context.Background(), &challenge) - r.NoError(err) - r.NotNil(nipost) - - verifier, err := NewPostVerifier(postProvider.cfg, zaptest.NewLogger(t).Named("verifier")) - r.NoError(err) - t.Cleanup(func() { assert.NoError(t, verifier.Close()) }) - v := NewValidator(poetDb, postProvider.cfg, postProvider.opts.Scrypt, verifier) - _, err = v.NIPost( - context.Background(), - postProvider.id, - postProvider.goldenATXID, - nipost, - challenge.Hash(), - postProvider.opts.NumUnits, - ) - r.NoError(err) -} - func TestNIPostBuilder_BuildNIPost(t *testing.T) { t.Parallel() req := require.New(t) @@ -716,42 +550,6 @@ func TestNIPostBuilder_ManyPoETs_AllFinished(t *testing.T) { req.EqualValues(ref[:], nipost.PostMetadata.Challenge) } -func TestNIPostBuilder_Close(t *testing.T) { - t.Parallel() - r := require.New(t) - - ctrl := gomock.NewController(t) - nipostClient := NewMocknipostClient(ctrl) - nipostClient.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) - poetProver := spawnPoet(t, WithGenesis(time.Now()), WithEpochDuration(time.Second)) - poetDb := NewMockpoetDbAPI(ctrl) - challenge := types.NIPostChallenge{ - PublishEpoch: postGenesisEpoch + 2, - } - mclock := defaultLayerClockMock(t) - - sig, err := signing.NewEdSigner() - r.NoError(err) - nb, err := NewNIPostBuilder( - types.NodeID{1}, - nipostClient, - poetDb, - []string{poetProver.RestURL().String()}, - t.TempDir(), - logtest.New(t), - sig, - PoetConfig{}, - mclock, - ) - r.NoError(err) - - ctx, cancel := context.WithCancel(context.Background()) - cancel() - nipost, err := nb.BuildNIPost(ctx, &challenge) - r.ErrorIs(err, context.Canceled) - r.Nil(nipost) -} - func TestNIPSTBuilder_PoetUnstable(t *testing.T) { t.Parallel() challenge := types.NIPostChallenge{ diff --git a/activation/poet_integration_test.go b/activation/poet_integration_test.go new file mode 100644 index 0000000000..9d8376c285 --- /dev/null +++ b/activation/poet_integration_test.go @@ -0,0 +1,135 @@ +package activation_test + +import ( + "bytes" + "context" + "errors" + "net/url" + "testing" + "time" + + "github.com/spacemeshos/poet/server" + "github.com/spacemeshos/poet/shared" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zaptest" + "golang.org/x/sync/errgroup" + + "github.com/spacemeshos/go-spacemesh/activation" + "github.com/spacemeshos/go-spacemesh/common/types" + "github.com/spacemeshos/go-spacemesh/signing" +) + +// HTTPPoetTestHarness utilizes a local self-contained poet server instance +// targeted by an HTTP client. It is intended to be used in tests only. +type HTTPPoetTestHarness struct { + Service *server.Server +} + +func (h *HTTPPoetTestHarness) RestURL() *url.URL { + return &url.URL{ + Scheme: "http", + Host: h.Service.GrpcRestProxyAddr().String(), + } +} + +type HTTPPoetOpt func(*server.Config) + +func WithGenesis(genesis time.Time) HTTPPoetOpt { + return func(cfg *server.Config) { + cfg.Genesis = server.Genesis(genesis) + } +} + +func WithEpochDuration(epoch time.Duration) HTTPPoetOpt { + return func(cfg *server.Config) { + cfg.Round.EpochDuration = epoch + } +} + +func WithPhaseShift(phase time.Duration) HTTPPoetOpt { + return func(cfg *server.Config) { + cfg.Round.PhaseShift = phase + } +} + +func WithCycleGap(gap time.Duration) HTTPPoetOpt { + 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 := server.DefaultConfig() + cfg.PoetDir = poetdir + cfg.RawRESTListener = "localhost:0" + cfg.RawRPCListener = "localhost:0" + + for _, opt := range opts { + opt(cfg) + } + + server.SetupConfig(cfg) + + poet, err := server.New(ctx, *cfg) + if err != nil { + return nil, err + } + + return &HTTPPoetTestHarness{ + Service: poet, + }, nil +} + +func TestHTTPPoet(t *testing.T) { + if testing.Short() { + t.Skip() + } + t.Parallel() + r := require.New(t) + + var eg errgroup.Group + + poetDir := t.TempDir() + t.Cleanup(func() { r.NoError(eg.Wait()) }) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + c, err := NewHTTPPoetTestHarness(ctx, poetDir) + r.NoError(err) + r.NotNil(c) + + eg.Go(func() error { + err := c.Service.Start(ctx) + return errors.Join(err, c.Service.Close()) + }) + + client, err := activation.NewHTTPPoetClient(c.RestURL().String(), activation.DefaultPoetConfig(), activation.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(), activation.PoetPoW{ + Nonce: nonce, + Params: *resp, + }) + r.NoError(err) + r.NotNil(poetRound) +} diff --git a/activation/poet_test.go b/activation/poet_test.go index 4490b63c77..00bdca983a 100644 --- a/activation/poet_test.go +++ b/activation/poet_test.go @@ -1,119 +1,15 @@ package activation import ( - "bytes" "context" "errors" "net/http" "net/url" "testing" - "time" - "github.com/spacemeshos/poet/logging" - "github.com/spacemeshos/poet/shared" "github.com/stretchr/testify/require" - "go.uber.org/zap/zaptest" - "golang.org/x/sync/errgroup" - - "github.com/spacemeshos/go-spacemesh/common/types" - "github.com/spacemeshos/go-spacemesh/signing" ) -func TestHTTPPoet(t *testing.T) { - t.Parallel() - r := require.New(t) - - var eg errgroup.Group - t.Cleanup(func() { r.NoError(eg.Wait()) }) - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - c, err := NewHTTPPoetTestHarness(logging.NewContext(ctx, zaptest.NewLogger(t)), t.TempDir()) - r.NoError(err) - r.NotNil(c) - - eg.Go(func() error { - err := c.Service.Start(ctx) - return errors.Join(err, c.Service.Close()) - }) - - 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(), time.Time{}, prefix, ch.Bytes(), signature, signer.NodeID(), PoetPoW{ - Nonce: nonce, - Params: *resp, - }) - r.NoError(err) - r.NotNil(poetRound) -} - -func TestSumbmitTooLate(t *testing.T) { - t.Parallel() - r := require.New(t) - - var eg errgroup.Group - t.Cleanup(func() { r.NoError(eg.Wait()) }) - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - c, err := NewHTTPPoetTestHarness(logging.NewContext(ctx, zaptest.NewLogger(t)), t.TempDir()) - r.NoError(err) - r.NotNil(c) - - eg.Go(func() error { - err := c.Service.Start(ctx) - return errors.Join(err, c.Service.Close()) - }) - - 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) - - _, err = client.Submit(context.Background(), time.Now(), prefix, ch.Bytes(), signature, signer.NodeID(), PoetPoW{ - Nonce: nonce, - Params: *resp, - }) - r.ErrorIs(err, ErrInvalidRequest) -} - func TestCheckRetry(t *testing.T) { t.Parallel() t.Run("doesn't retry on context cancellation.", func(t *testing.T) { diff --git a/activation/poet_test_harness.go b/activation/poet_test_harness.go deleted file mode 100644 index 1351c37ab0..0000000000 --- a/activation/poet_test_harness.go +++ /dev/null @@ -1,71 +0,0 @@ -package activation - -import ( - "context" - "net/url" - "time" - - "github.com/spacemeshos/poet/server" -) - -// HTTPPoetTestHarness utilizes a local self-contained poet server instance -// targeted by an HTTP client. It is intended to be used in tests only. -type HTTPPoetTestHarness struct { - Service *server.Server -} - -func (h *HTTPPoetTestHarness) RestURL() *url.URL { - return &url.URL{ - Scheme: "http", - Host: h.Service.GrpcRestProxyAddr().String(), - } -} - -type HTTPPoetOpt func(*server.Config) - -func WithGenesis(genesis time.Time) HTTPPoetOpt { - return func(cfg *server.Config) { - cfg.Genesis = server.Genesis(genesis) - } -} - -func WithEpochDuration(epoch time.Duration) HTTPPoetOpt { - return func(cfg *server.Config) { - cfg.Round.EpochDuration = epoch - } -} - -func WithPhaseShift(phase time.Duration) HTTPPoetOpt { - return func(cfg *server.Config) { - cfg.Round.PhaseShift = phase - } -} - -func WithCycleGap(gap time.Duration) HTTPPoetOpt { - 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 := server.DefaultConfig() - cfg.PoetDir = poetdir - cfg.RawRESTListener = "localhost:0" - cfg.RawRPCListener = "localhost:0" - - for _, opt := range opts { - opt(cfg) - } - - server.SetupConfig(cfg) - - poet, err := server.New(ctx, *cfg) - if err != nil { - return nil, err - } - - return &HTTPPoetTestHarness{ - Service: poet, - }, nil -} diff --git a/activation/post_supervisor.go b/activation/post_supervisor.go index ac0e8f0ba4..f20393b95f 100644 --- a/activation/post_supervisor.go +++ b/activation/post_supervisor.go @@ -7,6 +7,7 @@ import ( "io" "os/exec" "path/filepath" + "strconv" "strings" "sync/atomic" @@ -46,12 +47,18 @@ func MainnetPostServiceConfig() PostSupervisorConfig { type PostSupervisorConfig struct { PostServiceCmd string `mapstructure:"post-opts-post-service"` - DataDir string `mapstructure:"post-opts-datadir"` - NodeAddress string `mapstructure:"post-opts-node-address"` - PowDifficulty PowDifficulty `mapstructure:"post-opts-pow-difficulty"` - PostServiceMode string `mapstructure:"post-opts-post-service-mode"` + DataDir string `mapstructure:"post-opts-datadir"` + NodeAddress string `mapstructure:"post-opts-node-address"` + PostServiceMode string `mapstructure:"post-opts-post-service-mode"` - N string `mapstructure:"post-opts-n"` + PowDifficulty PowDifficulty `mapstructure:"post-opts-pow-difficulty"` + K1 uint32 `mapstructure:"post-opts-k1"` + K2 uint32 `mapstructure:"post-opts-k2"` + K3 uint32 `mapstructure:"post-opts-k3"` + + N uint `mapstructure:"post-opts-n"` + R uint `mapstructure:"post-opts-r"` + P uint `mapstructure:"post-opts-p"` } // PostSupervisor manages a local post service. @@ -113,8 +120,23 @@ func (ps *PostSupervisor) runCmd(ctx context.Context, opts PostSupervisorConfig) "--pow-difficulty", opts.PowDifficulty.String(), "--randomx-mode", opts.PostServiceMode, } - if opts.N != "" { - args = append(args, "-n", opts.N) + if opts.K1 != 0 { + args = append(args, "--k1", strconv.FormatUint(uint64(opts.K1), 10)) + } + if opts.K2 != 0 { + args = append(args, "--k2", strconv.FormatUint(uint64(opts.K2), 10)) + } + if opts.K3 != 0 { + args = append(args, "--k3", strconv.FormatUint(uint64(opts.K3), 10)) + } + if opts.N != 0 { + args = append(args, "-n", strconv.FormatUint(uint64(opts.N), 10)) + } + if opts.R != 0 { + args = append(args, "-r", strconv.FormatUint(uint64(opts.R), 10)) + } + if opts.P != 0 { + args = append(args, "-p", strconv.FormatUint(uint64(opts.P), 10)) } cmd := exec.CommandContext( diff --git a/activation/post_test.go b/activation/post_test.go index fd64a1db0a..605c82fc32 100644 --- a/activation/post_test.go +++ b/activation/post_test.go @@ -408,29 +408,10 @@ type testPostManager struct { cdb *datastore.CachedDB } -type newPostSetupMgrOptions struct { - cfg PostConfig -} - -type newPostSetupMgrOptionFunc func(*newPostSetupMgrOptions) - -func withPostConfig(cfg PostConfig) newPostSetupMgrOptionFunc { - return func(o *newPostSetupMgrOptions) { - o.cfg = cfg - } -} - // TODO(mafa): start post service with supervisor. -func newTestPostManager(tb testing.TB, o ...newPostSetupMgrOptionFunc) *testPostManager { +func newTestPostManager(tb testing.TB) *testPostManager { tb.Helper() - options := newPostSetupMgrOptions{ - cfg: DefaultPostConfig(), - } - for _, opt := range o { - opt(&options) - } - sig, err := signing.NewEdSigner() require.NoError(tb, err) id := sig.NodeID() @@ -445,7 +426,7 @@ func newTestPostManager(tb testing.TB, o ...newPostSetupMgrOptionFunc) *testPost cdb := datastore.NewCachedDB(sql.InMemory(), logtest.New(tb)) provingOpts := DefaultPostProvingOpts() provingOpts.Flags = config.RecommendedPowFlags() - mgr, err := NewPostSetupManager(id, options.cfg, zaptest.NewLogger(tb), cdb, goldenATXID, provingOpts) + mgr, err := NewPostSetupManager(id, DefaultPostConfig(), zaptest.NewLogger(tb), cdb, goldenATXID, provingOpts) require.NoError(tb, err) return &testPostManager{ diff --git a/activation/validation_integration_test.go.bak b/activation/validation_integration_test.go.bak new file mode 100644 index 0000000000..030b24049a --- /dev/null +++ b/activation/validation_integration_test.go.bak @@ -0,0 +1,64 @@ +package activation_test + +import ( + "context" + "fmt" + "testing" + + "github.com/spacemeshos/go-spacemesh/activation" + "github.com/spacemeshos/go-spacemesh/common/types" + "github.com/spacemeshos/go-spacemesh/log/logtest" + "github.com/spacemeshos/go-spacemesh/sql" + "go.uber.org/zap/zaptest" + + "github.com/stretchr/testify/require" +) + +func TestValidator_Validate(t *testing.T) { + r := require.New(t) + + challenge := types.NIPostChallenge{ + PublishEpoch: postGenesisEpoch + 2, + } + challengeHash := challenge.Hash() + poetDb := activation.NewPoetDb(sql.InMemory(), logtest.New(t).WithName("poetDb")) + + log := zaptest.NewLogger(t) + postProvider := newTestPostManager(t) + verifier, err := activation.NewPostVerifier(postProvider.cfg, log.Named("verifier")) + r.NoError(err) + defer verifier.Close() + + v := activation.NewValidator(poetDb, postProvider.cfg, postProvider.opts.Scrypt, verifier) + + nipost := buildNIPost(t, postProvider, challenge, poetDb, v) + + _, 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) + 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) + r.Contains(err.Error(), "invalid Post") + + newPostCfg := postProvider.cfg + newPostCfg.MinNumUnits = postProvider.opts.NumUnits + 1 + v = activation.NewValidator(poetDb, newPostCfg, postProvider.opts.Scrypt, 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 = activation.NewValidator(poetDb, newPostCfg, postProvider.opts.Scrypt, 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 = activation.NewValidator(poetDb, newPostCfg, postProvider.opts.Scrypt, 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/activation/validation_test.go b/activation/validation_test.go index 13368d2a5c..abeb785acd 100644 --- a/activation/validation_test.go +++ b/activation/validation_test.go @@ -467,55 +467,6 @@ func Test_Validate_PostMetadata(t *testing.T) { }) } -func TestValidator_Validate(t *testing.T) { - r := require.New(t) - - challenge := types.NIPostChallenge{ - PublishEpoch: postGenesisEpoch + 2, - } - challengeHash := challenge.Hash() - poetDb := NewPoetDb(sql.InMemory(), logtest.New(t).WithName("poetDb")) - - logger := logtest.New(t).WithName("validator") - postProvider := newTestPostManager(t) - verifier, err := NewPostVerifier(postProvider.cfg, logger) - r.NoError(err) - defer verifier.Close() - - v := NewValidator(poetDb, postProvider.cfg, postProvider.opts.Scrypt, logger, verifier) - - nipost := buildNIPost(t, postProvider, challenge, poetDb, v) - - _, 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) - 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) - r.Contains(err.Error(), "invalid Post") - - newPostCfg := postProvider.cfg - newPostCfg.MinNumUnits = postProvider.opts.NumUnits + 1 - 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, 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, 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)) -} - func TestValidateMerkleProof(t *testing.T) { challenge := types.CalcHash32([]byte("challenge")) diff --git a/api/grpcserver/post_client.go b/api/grpcserver/post_client.go index a69b768653..1c35da9065 100644 --- a/api/grpcserver/post_client.go +++ b/api/grpcserver/post_client.go @@ -41,15 +41,17 @@ func (pc *postClient) Proof(ctx context.Context, challenge []byte) (*types.Post, resp: resp, } - select { - case <-pc.closed: - return nil, nil, fmt.Errorf("post client closed") - case <-ctx.Done(): - return nil, nil, ctx.Err() - case pc.con <- cmd: - } - for { + // send command + select { + case <-pc.closed: + return nil, nil, fmt.Errorf("post client closed") + case <-ctx.Done(): + return nil, nil, ctx.Err() + case pc.con <- cmd: + } + + // receive response select { case <-pc.closed: return nil, nil, fmt.Errorf("post client closed") @@ -67,6 +69,7 @@ func (pc *postClient) Proof(ctx context.Context, challenge []byte) (*types.Post, case <-ctx.Done(): return nil, nil, ctx.Err() case <-time.After(2 * time.Second): // TODO(mafa): make polling interval configurable + continue } } diff --git a/api/grpcserver/post_service_test.go b/api/grpcserver/post_service_test.go index b648540dd0..6c0061ac70 100644 --- a/api/grpcserver/post_service_test.go +++ b/api/grpcserver/post_service_test.go @@ -89,7 +89,7 @@ func launchPostSupervisor(tb testing.TB, log *zap.Logger, cfg Config, postDir st NodeAddress: fmt.Sprintf("http://%s", cfg.PublicListener), PowDifficulty: activation.DefaultPostConfig().PowDifficulty, PostServiceMode: "light", - N: "2", + N: 2, } ps, err := activation.NewPostSupervisor(log, opts) diff --git a/common/types/activation.go b/common/types/activation.go index fb2ffc9d87..dc9d43b9ae 100644 --- a/common/types/activation.go +++ b/common/types/activation.go @@ -16,6 +16,12 @@ import ( //go:generate scalegen +// BytesToATXID is a helper to copy buffer into a ATXID. +func BytesToATXID(buf []byte) (id ATXID) { + copy(id[:], buf) + return id +} + // ATXID is a 32-bit hash used to identify an activation transaction. type ATXID Hash32 diff --git a/common/types/nodeid.go b/common/types/nodeid.go index ff46b00f9c..ef9bc6f401 100644 --- a/common/types/nodeid.go +++ b/common/types/nodeid.go @@ -9,7 +9,7 @@ import ( "github.com/spacemeshos/go-spacemesh/log" ) -// BytesToNodeID is a helper to copy buffer into NodeID struct. +// BytesToNodeID is a helper to copy buffer into a NodeID. func BytesToNodeID(buf []byte) (id NodeID) { copy(id[:], buf) return id diff --git a/config/config.go b/config/config.go index f9829bdc1e..f2b0a028c8 100644 --- a/config/config.go +++ b/config/config.go @@ -137,7 +137,7 @@ type SmeshingConfig struct { Start bool `mapstructure:"smeshing-start"` CoinbaseAccount string `mapstructure:"smeshing-coinbase"` Opts activation.PostSetupOpts `mapstructure:"smeshing-opts"` - ProvingOpts activation.PostProvingOpts `mapstructure:"smeshing-proving-opts"` + ProvingOpts activation.PostProvingOpts `mapstructure:"smeshing-proving-opts"` // TODO(mafa): remove? VerifyingOpts activation.PostProofVerifyingOpts `mapstructure:"smeshing-verifying-opts"` } diff --git a/config/mainnet.go b/config/mainnet.go index 34b814727d..09e13acf11 100644 --- a/config/mainnet.go +++ b/config/mainnet.go @@ -144,12 +144,13 @@ func MainnetConfig() Config { DataDir: os.TempDir(), Interval: 30 * time.Second, }, - P2P: p2pconfig, - API: grpcserver.DefaultConfig(), - TIME: timeConfig.DefaultConfig(), - SMESHING: smeshing, - FETCH: fetch.DefaultConfig(), - LOGGING: logging, + P2P: p2pconfig, + API: grpcserver.DefaultConfig(), + TIME: timeConfig.DefaultConfig(), + SMESHING: smeshing, + POSTService: activation.MainnetPostServiceConfig(), + FETCH: fetch.DefaultConfig(), + LOGGING: logging, Sync: syncer.Config{ Interval: time.Minute, EpochEndFraction: 0.8, diff --git a/config/presets/fastnet.go b/config/presets/fastnet.go index 6e5e4f37a1..d6471f347b 100644 --- a/config/presets/fastnet.go +++ b/config/presets/fastnet.go @@ -97,5 +97,10 @@ func fastnet() config.Config { conf.POET.RequestRetryDelay = 1 * time.Second conf.POET.MaxRequestRetries = 3 + conf.POSTService.N = conf.SMESHING.Opts.Scrypt.N + + conf.POSTService.K1 = conf.POST.K1 + conf.POSTService.K2 = conf.POST.K2 + conf.POSTService.K3 = conf.POST.K3 return conf } diff --git a/config/presets/standalone.go b/config/presets/standalone.go index 50e0810072..5cd209c01e 100644 --- a/config/presets/standalone.go +++ b/config/presets/standalone.go @@ -1,6 +1,7 @@ package presets import ( + "fmt" "math/big" "os" "path/filepath" @@ -88,6 +89,11 @@ func standalone() config.Config { conf.API.PublicListener = "0.0.0.0:10092" conf.API.PrivateListener = "0.0.0.0:10093" - conf.POSTService.NodeAddress = "http://0.0.0.0:10093" + conf.POSTService.NodeAddress = fmt.Sprintf("http://%s", conf.API.PrivateListener) + conf.POSTService.DataDir = conf.SMESHING.Opts.DataDir + + conf.POSTService.K1 = conf.POST.K1 + conf.POSTService.K2 = conf.POST.K2 + conf.POSTService.K3 = conf.POST.K3 return conf } diff --git a/node/node.go b/node/node.go index 1c7416660c..9b2fa09c7a 100644 --- a/node/node.go +++ b/node/node.go @@ -351,7 +351,7 @@ type App struct { updater *bootstrap.Updater poetDb *activation.PoetDb postVerifier *activation.OffloadingPostVerifier - postService *activation.PostSupervisor + postSupervisor *activation.PostSupervisor preserve *checkpoint.PreservedData errCh chan error @@ -554,7 +554,7 @@ func (app *App) initServices(ctx context.Context) error { nipostValidatorLogger := app.addLogger(NipostValidatorLogger, lg) postVerifiers := make([]activation.PostVerifier, 0, app.Config.SMESHING.VerifyingOpts.Workers) lg.Debug("creating post verifier") - verifier, err := activation.NewPostVerifier(app.Config.POST, nipostValidatorLogger, verifying.WithPowFlags(app.Config.SMESHING.VerifyingOpts.Flags)) + verifier, err := activation.NewPostVerifier(app.Config.POST, nipostValidatorLogger.Zap(), verifying.WithPowFlags(app.Config.SMESHING.VerifyingOpts.Flags)) lg.With().Debug("created post verifier", log.Err(err)) if err != nil { return err @@ -565,13 +565,13 @@ func (app *App) initServices(ctx context.Context) error { app.postVerifier = activation.NewOffloadingPostVerifier(postVerifiers, nipostValidatorLogger) if app.Config.POSTService.PostServiceCmd != "" { - app.postService, err = activation.NewPostSupervisor(app.log.Zap(), app.Config.POSTService) + app.postSupervisor, err = activation.NewPostSupervisor(app.log.Zap(), app.Config.POSTService) if err != nil { return fmt.Errorf("start post service: %w", err) } } - validator := activation.NewValidator(poetDb, app.Config.POST, app.Config.SMESHING.Opts.Scrypt, nipostValidatorLogger, app.postVerifier) + validator := activation.NewValidator(poetDb, app.Config.POST, app.Config.SMESHING.Opts.Scrypt, app.postVerifier) app.validator = validator cfg := vm.DefaultConfig() @@ -1248,8 +1248,8 @@ func (app *App) stopServices(ctx context.Context) { app.syncer.Close() } - if app.postService != nil { - if err := app.postService.Close(); err != nil { + if app.postSupervisor != nil { + if err := app.postSupervisor.Close(); err != nil { app.log.With().Error("error stopping local post service", log.Err(err)) } } diff --git a/node/node_test.go b/node/node_test.go index 6a80f40109..4499959c95 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -420,6 +420,15 @@ func TestSpacemeshApp_NodeService(t *testing.T) { app.Config = getTestDefaultConfig(t) app.Config.SMESHING.CoinbaseAccount = types.GenerateAddress([]byte{1}).String() app.Config.SMESHING.Opts.DataDir = t.TempDir() + app.Config.SMESHING.Opts.Scrypt.N = 2 + + path, err := exec.Command("go", "env", "GOMOD").Output() + if err != nil { + panic(err) + } + app.Config.POSTService.PostServiceCmd = filepath.Join(filepath.Dir(string(path)), "build", "service") + app.Config.POSTService.DataDir = app.Config.SMESHING.Opts.DataDir + app.Config.POSTService.N = app.Config.SMESHING.Opts.Scrypt.N edSgn, err := signing.NewEdSigner() require.NoError(t, err) @@ -1089,18 +1098,22 @@ func TestAdminEvents(t *testing.T) { require.NoError(t, err) cfg.DataDirParent = t.TempDir() cfg.FileLock = filepath.Join(cfg.DataDirParent, "LOCK") - cfg.SMESHING.Opts.DataDir = t.TempDir() + cfg.SMESHING.Opts.DataDir = cfg.DataDirParent + cfg.SMESHING.Opts.Scrypt.N = 2 path, err := exec.Command("go", "env", "GOMOD").Output() if err != nil { panic(err) } cfg.POSTService.PostServiceCmd = filepath.Join(filepath.Dir(string(path)), "build", "service") + cfg.POSTService.DataDir = cfg.SMESHING.Opts.DataDir + cfg.POSTService.N = cfg.SMESHING.Opts.Scrypt.N cfg.Genesis.GenesisTime = time.Now().Add(5 * time.Second).Format(time.RFC3339) types.SetLayersPerEpoch(cfg.LayersPerEpoch) - app := New(WithConfig(&cfg), WithLog(logtest.New(t))) + logger := logtest.New(t, zapcore.DebugLevel) + app := New(WithConfig(&cfg), WithLog(logger)) signer, err := app.LoadOrCreateEdSigner() require.NoError(t, err) app.edSgn = signer // https://github.com/spacemeshos/go-spacemesh/issues/4653 @@ -1118,7 +1131,7 @@ func TestAdminEvents(t *testing.T) { }) t.Cleanup(func() { eg.Wait() }) - grpcCtx, cancel := context.WithTimeout(ctx, 5*time.Second) + grpcCtx, cancel := context.WithTimeout(ctx, 20*time.Second) defer cancel() conn, err := grpc.DialContext( grpcCtx, From 4ddcddcc7267bb80c1ee820e17235139e64507ee Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Thu, 5 Oct 2023 17:20:28 +0000 Subject: [PATCH 07/40] Increase timeouts --- api/grpcserver/post_service_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/grpcserver/post_service_test.go b/api/grpcserver/post_service_test.go index 6c0061ac70..c7c800220f 100644 --- a/api/grpcserver/post_service_test.go +++ b/api/grpcserver/post_service_test.go @@ -123,7 +123,7 @@ func Test_GenerateProof(t *testing.T) { select { case <-connected: - case <-time.After(5 * time.Second): + case <-time.After(10 * time.Second): require.Fail(t, "timed out waiting for connection") } @@ -173,7 +173,7 @@ func Test_Cancel_GenerateProof(t *testing.T) { select { case <-connected: - case <-time.After(5 * time.Second): + case <-time.After(10 * time.Second): require.Fail(t, "timed out waiting for connection") } @@ -225,7 +225,7 @@ func Test_GenerateProof_MultipleServices(t *testing.T) { select { case <-connected: - case <-time.After(5 * time.Second): + case <-time.After(10 * time.Second): require.Fail(t, "timed out waiting for connection") } From 75215ca034f7b51cba5a96d1f816e14dc8fdf937 Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Thu, 5 Oct 2023 19:26:51 +0000 Subject: [PATCH 08/40] Update e2e tests --- .../nipost_test.go} | 310 +++++++++++------- .../poet_test.go} | 0 .../validation_test.go.bak} | 0 api/grpcserver/post_client.go | 3 +- 4 files changed, 199 insertions(+), 114 deletions(-) rename activation/{nipost_integration_test.go.bak => e2e/nipost_test.go} (53%) rename activation/{poet_integration_test.go => e2e/poet_test.go} (100%) rename activation/{validation_integration_test.go.bak => e2e/validation_test.go.bak} (100%) diff --git a/activation/nipost_integration_test.go.bak b/activation/e2e/nipost_test.go similarity index 53% rename from activation/nipost_integration_test.go.bak rename to activation/e2e/nipost_test.go index 00ff706b5c..5ebdd18623 100644 --- a/activation/nipost_integration_test.go.bak +++ b/activation/e2e/nipost_test.go @@ -3,15 +3,18 @@ package activation_test import ( "context" "errors" + "fmt" "os" + "os/exec" + "path/filepath" "testing" "time" "github.com/spacemeshos/poet/logging" "github.com/spacemeshos/post/config" "github.com/spacemeshos/post/initialization" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/zeebo/assert" "go.uber.org/mock/gomock" "go.uber.org/zap" "go.uber.org/zap/zapcore" @@ -19,8 +22,10 @@ import ( "golang.org/x/sync/errgroup" "github.com/spacemeshos/go-spacemesh/activation" + "github.com/spacemeshos/go-spacemesh/api/grpcserver" "github.com/spacemeshos/go-spacemesh/common/types" "github.com/spacemeshos/go-spacemesh/datastore" + "github.com/spacemeshos/go-spacemesh/log" "github.com/spacemeshos/go-spacemesh/log/logtest" "github.com/spacemeshos/go-spacemesh/signing" "github.com/spacemeshos/go-spacemesh/sql" @@ -38,28 +43,68 @@ func TestMain(m *testing.M) { os.Exit(res) } -func initPost(tb testing.TB, log *zap.Logger, dir string) { +func spawnPoet(tb testing.TB, opts ...HTTPPoetOpt) *HTTPPoetTestHarness { tb.Helper() + ctx, cancel := context.WithCancel(logging.NewContext(context.Background(), zaptest.NewLogger(tb))) - cfg := activation.DefaultPostConfig() - - sig, err := signing.NewEdSigner() + poetProver, err := NewHTTPPoetTestHarness(ctx, tb.TempDir(), opts...) require.NoError(tb, err) - id := sig.NodeID() + require.NotNil(tb, poetProver) - opts := activation.DefaultPostSetupOpts() - opts.DataDir = dir - opts.ProviderID.SetInt64(int64(initialization.CPUProviderID())) - opts.Scrypt.N = 2 // Speedup initialization in tests. + var eg errgroup.Group + tb.Cleanup(func() { + cancel() + eg.Wait() + }) + eg.Go(func() error { + err := poetProver.Service.Start(ctx) + return errors.Join(err, poetProver.Service.Close()) + }) - goldenATXID := types.ATXID{2, 3, 4} + return poetProver +} - cdb := datastore.NewCachedDB(sql.InMemory(), logtest.New(tb)) - provingOpts := activation.DefaultPostProvingOpts() - provingOpts.Flags = config.RecommendedPowFlags() - mgr, err := activation.NewPostSetupManager(id, cfg, log.Named("manager"), cdb, goldenATXID, provingOpts) +func launchPostSupervisor(tb testing.TB, log *zap.Logger, cfg grpcserver.Config, postDir string) func() { + path, err := exec.Command("go", "env", "GOMOD").Output() require.NoError(tb, err) + opts := activation.PostSupervisorConfig{ + PostServiceCmd: filepath.Join(filepath.Dir(string(path)), "build", "service"), + DataDir: postDir, + NodeAddress: fmt.Sprintf("http://%s", cfg.PublicListener), + PowDifficulty: activation.DefaultPostConfig().PowDifficulty, + PostServiceMode: "light", + N: 2, + } + + ps, err := activation.NewPostSupervisor(log, opts) + require.NoError(tb, err) + require.NotNil(tb, ps) + return func() { assert.NoError(tb, ps.Close()) } +} + +func launchServer(tb testing.TB, services ...grpcserver.ServiceAPI) (grpcserver.Config, func()) { + cfg := grpcserver.DefaultTestConfig() + + // run on random ports + grpcService := grpcserver.New("127.0.0.1:0", logtest.New(tb).Named("grpc")) + + // attach services + for _, svc := range services { + svc.RegisterService(grpcService) + } + + require.NoError(tb, grpcService.Start()) + + // update config with bound addresses + cfg.PublicListener = grpcService.BoundAddress + + return cfg, func() { assert.NoError(tb, grpcService.Close()) } +} + +func initPost(tb testing.TB, logger *zap.Logger, mgr *activation.PostSetupManager, opts activation.PostSetupOpts) *activation.PostSetupManager { + tb.Helper() + ctx, cancel := context.WithCancel(context.Background()) tb.Cleanup(cancel) @@ -77,7 +122,7 @@ func initPost(tb testing.TB, log *zap.Logger, dir string) { status := mgr.Status() require.GreaterOrEqual(tb, status.NumLabelsWritten, lastStatus.NumLabelsWritten) - if status.NumLabelsWritten == uint64(opts.NumUnits)*cfg.LabelsPerUnit { + if status.NumLabelsWritten == uint64(mgr.LastOpts().NumUnits)*mgr.Config().LabelsPerUnit { return nil } require.Equal(tb, activation.PostSetupStateInProgress, status.State) @@ -90,41 +135,35 @@ func initPost(tb testing.TB, log *zap.Logger, dir string) { require.NoError(tb, mgr.StartSession(context.Background())) require.NoError(tb, eg.Wait()) require.Equal(tb, activation.PostSetupStateComplete, mgr.Status().State) + + return mgr } -func spawnPoet(tb testing.TB, opts ...HTTPPoetOpt) *HTTPPoetTestHarness { - tb.Helper() - ctx, cancel := context.WithCancel(logging.NewContext(context.Background(), zaptest.NewLogger(tb))) +func TestNIPostBuilderWithClients(t *testing.T) { + logger := zaptest.NewLogger(t) + ctrl := gomock.NewController(t) - poetProver, err := NewHTTPPoetTestHarness(ctx, tb.TempDir(), opts...) - require.NoError(tb, err) - require.NotNil(tb, poetProver) + sig, err := signing.NewEdSigner() + require.NoError(t, err) - var eg errgroup.Group - tb.Cleanup(func() { - cancel() - eg.Wait() - }) - eg.Go(func() error { - err := poetProver.Service.Start(ctx) - return errors.Join(err, poetProver.Service.Close()) - }) + postDir := t.TempDir() + goldenATX := types.ATXID{2, 3, 4} - return poetProver -} + cfg := activation.DefaultPostConfig() -// TODO(mafa): start post service with supervisor. -func buildNIPost(tb testing.TB, postProvider *testPostManager, nipostChallenge types.NIPostChallenge, poetDb poetDbAPI, validator nipostValidator) *types.NIPost { - require.NoError(tb, postProvider.PrepareInitializer(context.Background(), postProvider.opts)) - require.NoError(tb, postProvider.StartSession(context.Background())) - mclock := activation.NewMocklayerClock(gomock.NewController(tb)) - mclock.EXPECT().LayerToTime(gomock.Any()).AnyTimes().DoAndReturn( - func(got types.LayerID) time.Time { - // time.Now() ~= currentLayer - genesis := time.Now().Add(-time.Duration(postGenesisEpoch.FirstLayer()) * layerDuration) - return genesis.Add(layerDuration * time.Duration(got)) - }, - ) + cdb := datastore.NewCachedDB(sql.InMemory(), log.NewFromLog(logger)) + + provingOpts := activation.DefaultPostProvingOpts() + provingOpts.Flags = config.RecommendedPowFlags() + + mgr, err := activation.NewPostSetupManager(sig.NodeID(), cfg, logger, cdb, goldenATX, provingOpts) + require.NoError(t, err) + + opts := activation.DefaultPostSetupOpts() + opts.DataDir = postDir + opts.ProviderID.SetInt64(int64(initialization.CPUProviderID())) + opts.Scrypt.N = 2 // Speedup initialization in tests. + initPost(t, logger.Named("manager"), mgr, opts) epoch := layersPerEpoch * layerDuration poetCfg := activation.PoetConfig{ @@ -135,56 +174,76 @@ func buildNIPost(tb testing.TB, postProvider *testPostManager, nipostChallenge t RequestRetryDelay: epoch / 50, MaxRequestRetries: 10, } + poetProver := spawnPoet(t, WithGenesis(time.Now()), WithEpochDuration(epoch), WithPhaseShift(poetCfg.PhaseShift), WithCycleGap(poetCfg.CycleGap)) - poetProver := spawnPoet(tb, WithGenesis(time.Now()), WithEpochDuration(epoch), WithPhaseShift(poetCfg.PhaseShift), WithCycleGap(poetCfg.CycleGap)) + mclock := activation.NewMocklayerClock(ctrl) + mclock.EXPECT().LayerToTime(gomock.Any()).AnyTimes().DoAndReturn( + func(got types.LayerID) time.Time { + // time.Now() ~= currentLayer + genesis := time.Now().Add(-time.Duration(postGenesisEpoch.FirstLayer()) * layerDuration) + return genesis.Add(layerDuration * time.Duration(got)) + }, + ) + + poetDb := activation.NewPoetDb(sql.InMemory(), log.NewFromLog(logger).Named("poetDb")) + + verifier, err := activation.NewPostVerifier(mgr.Config(), logger.Named("verifier")) + require.NoError(t, err) + t.Cleanup(func() { assert.NoError(t, verifier.Close()) }) + + v := activation.NewValidator(poetDb, mgr.Config(), mgr.LastOpts().Scrypt, verifier) - signer, err := signing.NewEdSigner() - require.NoError(tb, err) nb, err := activation.NewNIPostBuilder( - postProvider.id, - postProvider, + sig.NodeID(), + mgr, poetDb, []string{poetProver.RestURL().String()}, - tb.TempDir(), - logtest.New(tb, zapcore.DebugLevel), - signer, + t.TempDir(), + logtest.New(t, zapcore.DebugLevel), + sig, poetCfg, mclock, - activation.WithNipostValidator(validator), + activation.WithNipostValidator(v), ) - require.NoError(tb, err) - nipost, err := nb.BuildNIPost(context.Background(), &nipostChallenge) - require.NoError(tb, err) - return nipost -} + require.NoError(t, err) + + connected := make(chan struct{}) + con := grpcserver.NewMockpostConnectionListener(ctrl) + con.EXPECT().Connected(gomock.Any()).DoAndReturn(func(c activation.PostClient) { + close(connected) + }).Times(1) + con.EXPECT().Disconnected(gomock.Any()).Times(1) + + svc := grpcserver.NewPostService(logger, nb, con) + grpcCfg, cleanup := launchServer(t, svc) + t.Cleanup(cleanup) + + t.Cleanup(launchPostSupervisor(t, logger, grpcCfg, postDir)) + + select { + case <-connected: + case <-time.After(10 * time.Second): + require.Fail(t, "timed out waiting for connection") + } -func TestNIPostBuilderWithClients(t *testing.T) { challenge := types.NIPostChallenge{ PublishEpoch: postGenesisEpoch + 2, } - poetDb := activation.NewPoetDb(sql.InMemory(), logtest.New(t).WithName("poetDb")) - postCfg := activation.DefaultPostConfig() - postCfg.PowDifficulty[0] = 1 - postProvider := newTestPostManager(t, withPostConfig(postCfg)) - verifier, err := activation.NewPostVerifier(postProvider.Config(), zaptest.NewLogger(t).Named("verifier")) - require.NoError(t, err) - defer verifier.Close() - v := activation.NewValidator(poetDb, postProvider.Config(), postProvider.opts.Scrypt, verifier) - nipost := buildNIPost(t, postProvider, challenge, poetDb, v) + nipost, err := nb.BuildNIPost(context.Background(), &challenge) + require.NoError(t, err) _, err = v.NIPost( context.Background(), - postProvider.id, - postProvider.commitmentAtxId, + sig.NodeID(), + goldenATX, nipost, challenge.Hash(), - postProvider.opts.NumUnits, + mgr.LastOpts().NumUnits, ) require.NoError(t, err) } func TestNIPostBuilder_Close(t *testing.T) { - t.Parallel() r := require.New(t) ctrl := gomock.NewController(t) @@ -195,7 +254,7 @@ func TestNIPostBuilder_Close(t *testing.T) { challenge := types.NIPostChallenge{ PublishEpoch: postGenesisEpoch + 2, } - mclock := activation.NewMocklayerClock(gomock.NewController(t)) + mclock := activation.NewMocklayerClock(ctrl) mclock.EXPECT().LayerToTime(gomock.Any()).AnyTimes().DoAndReturn( func(got types.LayerID) time.Time { // time.Now() ~= currentLayer @@ -227,14 +286,24 @@ func TestNIPostBuilder_Close(t *testing.T) { } func TestNewNIPostBuilderNotInitialized(t *testing.T) { - r := require.New(t) + logger := zaptest.NewLogger(t) + ctrl := gomock.NewController(t) - challenge := types.NIPostChallenge{ - PublishEpoch: postGenesisEpoch + 2, - } - challengeHash := challenge.Hash() + sig, err := signing.NewEdSigner() + require.NoError(t, err) + + postDir := t.TempDir() + goldenATX := types.ATXID{2, 3, 4} + + cfg := activation.DefaultPostConfig() + + cdb := datastore.NewCachedDB(sql.InMemory(), log.NewFromLog(logger)) + + provingOpts := activation.DefaultPostProvingOpts() + provingOpts.Flags = config.RecommendedPowFlags() - postProvider := newTestPostManager(t) + mgr, err := activation.NewPostSetupManager(sig.NodeID(), cfg, logger, cdb, goldenATX, provingOpts) + require.NoError(t, err) epoch := layersPerEpoch * layerDuration poetCfg := activation.PoetConfig{ @@ -246,22 +315,9 @@ func TestNewNIPostBuilderNotInitialized(t *testing.T) { MaxRequestRetries: 10, } - poetClient := activation.NewMockPoetProvingServiceClient(gomock.NewController(t)) - poetClient.EXPECT().Submit(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(&types.PoetRound{}, nil) - poetClient.EXPECT().PoetServiceID(gomock.Any()).Return(types.PoetServiceID{ServiceID: []byte("poet")}, nil) - poetClient.EXPECT().PowParams(gomock.Any()).Return(&activation.PoetPowParams{}, nil) - poetClient.EXPECT().Address().Return("http://localhost:9999") - poetClient.EXPECT().Proof(gomock.Any(), "").Return(&types.PoetProofMessage{ - PoetProof: types.PoetProof{}, - }, []types.Member{types.Member(challenge.Hash())}, nil) + poetProver := spawnPoet(t, WithGenesis(time.Now()), WithEpochDuration(epoch), WithPhaseShift(poetCfg.PhaseShift), WithCycleGap(poetCfg.CycleGap)) - ctrl := gomock.NewController(t) - poetDb := activation.NewMockpoetDbAPI(ctrl) - poetDb.EXPECT().GetProof(gomock.Any()).Return( - &types.PoetProof{}, &challengeHash, nil, - ) - poetDb.EXPECT().ValidateAndStore(gomock.Any(), gomock.Any()).Return(nil) - mclock := activation.NewMocklayerClock(gomock.NewController(t)) + mclock := activation.NewMocklayerClock(ctrl) mclock.EXPECT().LayerToTime(gomock.Any()).AnyTimes().DoAndReturn( func(got types.LayerID) time.Time { // time.Now() ~= currentLayer @@ -270,46 +326,74 @@ func TestNewNIPostBuilderNotInitialized(t *testing.T) { }, ) + poetDb := activation.NewPoetDb(sql.InMemory(), log.NewFromLog(logger).Named("poetDb")) + nipostValidator := activation.NewMocknipostValidator(ctrl) nipostValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(1).Return(nil) nb, err := activation.NewNIPostBuilder( - postProvider.id, - postProvider, + sig.NodeID(), + mgr, poetDb, - []string{}, + []string{poetProver.RestURL().String()}, t.TempDir(), logtest.New(t), - postProvider.signer, + sig, poetCfg, mclock, activation.WithNipostValidator(nipostValidator), - withPoetClients([]activation.PoetProvingServiceClient{poetProvider}), ) require.NoError(t, err) + connected := make(chan struct{}) + con := grpcserver.NewMockpostConnectionListener(ctrl) + con.EXPECT().Connected(gomock.Any()).DoAndReturn(func(c activation.PostClient) { + close(connected) + }).Times(1) + con.EXPECT().Disconnected(gomock.Any()).Times(1) + + svc := grpcserver.NewPostService(logger, nb, con) + grpcCfg, cleanup := launchServer(t, svc) + t.Cleanup(cleanup) + + t.Cleanup(launchPostSupervisor(t, logger, grpcCfg, postDir)) + + select { + case <-connected: + case <-time.After(10 * time.Second): + require.Fail(t, "timed out waiting for connection") + } + + challenge := types.NIPostChallenge{ + PublishEpoch: postGenesisEpoch + 2, + } + nipost, err := nb.BuildNIPost(context.Background(), &challenge) - r.EqualError(err, "post setup not complete") - r.Nil(nipost) + require.EqualError(t, err, "post setup not complete") + require.Nil(t, nipost) - r.NoError(postProvider.PrepareInitializer(context.Background(), postProvider.opts)) - r.NoError(postProvider.StartSession(context.Background())) + opts := activation.DefaultPostSetupOpts() + opts.DataDir = postDir + opts.ProviderID.SetInt64(int64(initialization.CPUProviderID())) + opts.Scrypt.N = 2 // Speedup initialization in tests. + initPost(t, logger.Named("manager"), mgr, opts) nipost, err = nb.BuildNIPost(context.Background(), &challenge) - r.NoError(err) - r.NotNil(nipost) + require.NoError(t, err) + require.NotNil(t, nipost) - verifier, err := activation.NewPostVerifier(postProvider.cfg, zaptest.NewLogger(t).Named("verifier")) - r.NoError(err) + verifier, err := activation.NewPostVerifier(mgr.Config(), zaptest.NewLogger(t).Named("verifier")) + require.NoError(t, err) t.Cleanup(func() { assert.NoError(t, verifier.Close()) }) - v := activation.NewValidator(poetDb, postProvider.cfg, postProvider.opts.Scrypt, verifier) + + v := activation.NewValidator(poetDb, mgr.Config(), mgr.LastOpts().Scrypt, verifier) _, err = v.NIPost( context.Background(), - postProvider.id, - postProvider.goldenATXID, + sig.NodeID(), + goldenATX, nipost, challenge.Hash(), - postProvider.opts.NumUnits, + mgr.LastOpts().NumUnits, ) - r.NoError(err) + require.NoError(t, err) } diff --git a/activation/poet_integration_test.go b/activation/e2e/poet_test.go similarity index 100% rename from activation/poet_integration_test.go rename to activation/e2e/poet_test.go diff --git a/activation/validation_integration_test.go.bak b/activation/e2e/validation_test.go.bak similarity index 100% rename from activation/validation_integration_test.go.bak rename to activation/e2e/validation_test.go.bak diff --git a/api/grpcserver/post_client.go b/api/grpcserver/post_client.go index 1c35da9065..f95584d8e2 100644 --- a/api/grpcserver/post_client.go +++ b/api/grpcserver/post_client.go @@ -68,7 +68,8 @@ func (pc *postClient) Proof(ctx context.Context, challenge []byte) (*types.Post, select { case <-ctx.Done(): return nil, nil, ctx.Err() - case <-time.After(2 * time.Second): // TODO(mafa): make polling interval configurable + case <-time.After(2 * time.Second): + // TODO(mafa): make polling interval configurable continue } } From ddb939d6e954ee62bc4ce3624b1da29ba9cba3f0 Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Fri, 6 Oct 2023 15:20:01 +0000 Subject: [PATCH 09/40] Fix tests --- activation/e2e/poet_test.go | 54 +++++++++++++++-- activation/nipost_test.go | 115 ------------------------------------ activation/post_test.go | 49 ++++++++++++++- 3 files changed, 97 insertions(+), 121 deletions(-) diff --git a/activation/e2e/poet_test.go b/activation/e2e/poet_test.go index 9d8376c285..2881f40be3 100644 --- a/activation/e2e/poet_test.go +++ b/activation/e2e/poet_test.go @@ -82,14 +82,10 @@ func NewHTTPPoetTestHarness(ctx context.Context, poetdir string, opts ...HTTPPoe } func TestHTTPPoet(t *testing.T) { - if testing.Short() { - t.Skip() - } t.Parallel() r := require.New(t) var eg errgroup.Group - poetDir := t.TempDir() t.Cleanup(func() { r.NoError(eg.Wait()) }) @@ -126,10 +122,58 @@ func TestHTTPPoet(t *testing.T) { 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(), activation.PoetPoW{ + poetRound, err := client.Submit(context.Background(), time.Time{}, prefix, ch.Bytes(), signature, signer.NodeID(), activation.PoetPoW{ Nonce: nonce, Params: *resp, }) r.NoError(err) r.NotNil(poetRound) } + +func TestSubmitTooLate(t *testing.T) { + t.Parallel() + r := require.New(t) + + var eg errgroup.Group + poetDir := t.TempDir() + t.Cleanup(func() { r.NoError(eg.Wait()) }) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + c, err := NewHTTPPoetTestHarness(ctx, poetDir) + r.NoError(err) + r.NotNil(c) + + eg.Go(func() error { + err := c.Service.Start(ctx) + return errors.Join(err, c.Service.Close()) + }) + + client, err := activation.NewHTTPPoetClient(c.RestURL().String(), activation.DefaultPoetConfig(), activation.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) + + _, err = client.Submit(context.Background(), time.Now(), prefix, ch.Bytes(), signature, signer.NodeID(), activation.PoetPoW{ + Nonce: nonce, + Params: *resp, + }) + r.ErrorIs(err, activation.ErrInvalidRequest) +} diff --git a/activation/nipost_test.go b/activation/nipost_test.go index ad545c5940..b9c76fd467 100644 --- a/activation/nipost_test.go +++ b/activation/nipost_test.go @@ -355,121 +355,6 @@ func TestNIPostBuilder_ManyPoETs_SubmittingChallenge_DeadlineReached(t *testing. req.EqualValues(ref[:], nipost.PostMetadata.Challenge) } -func TestNIPostBuilder_PoetInvalidRequest(t *testing.T) { - t.Parallel() - // Arrange - req := require.New(t) - challenge := types.NIPostChallenge{ - PublishEpoch: postGenesisEpoch + 1, - } - - ctrl := gomock.NewController(t) - - poet := NewMockPoetProvingServiceClient(ctrl) - poet.EXPECT().PoetServiceID(gomock.Any()).AnyTimes().Return(types.PoetServiceID{ServiceID: []byte("poet0")}, nil) - poet.EXPECT().Submit(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(&types.PoetRound{}, ErrInvalidRequest) - poet.EXPECT().PowParams(gomock.Any()).Return(&PoetPowParams{}, nil) - poet.EXPECT().Address().Return("http://localhost:9999") - - sig, err := signing.NewEdSigner() - req.NoError(err) - postProvider := NewMockpostSetupProvider(ctrl) - postProvider.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) - postProvider.EXPECT().CommitmentAtx().Return(types.EmptyATXID, nil).AnyTimes() - postProvider.EXPECT().LastOpts().Return(&PostSetupOpts{}).AnyTimes() - - nb, err := NewNIPostBuilder( - types.NodeID{1}, - postProvider, - NewMockpoetDbAPI(ctrl), - []string{}, - t.TempDir(), - logtest.New(t), - sig, - PoetConfig{PhaseShift: layerDuration * layersPerEpoch / 2}, - defaultLayerClockMock(t), - WithNipostValidator(NewMocknipostValidator(ctrl)), - withPoetClients([]PoetProvingServiceClient{poet}), - ) - req.NoError(err) - - // Act - _, err = nb.BuildNIPost(context.Background(), &challenge) - req.ErrorIs(err, ErrATXChallengeExpired) -} - -func TestNIPostBuilder_OnePoetInvalidRequest(t *testing.T) { - t.Parallel() - // Arrange - req := require.New(t) - challenge := types.NIPostChallenge{ - PublishEpoch: postGenesisEpoch + 1, - } - - proof := &types.PoetProofMessage{PoetProof: types.PoetProof{}} - - ctrl := gomock.NewController(t) - nipostValidator := NewMocknipostValidator(ctrl) - poetDb := NewMockpoetDbAPI(ctrl) - poetDb.EXPECT().ValidateAndStore(gomock.Any(), gomock.Any()).Return(nil) - - poets := make([]PoetProvingServiceClient, 0, 2) - { - poet := NewMockPoetProvingServiceClient(ctrl) - poet.EXPECT().PoetServiceID(gomock.Any()).AnyTimes().Return(types.PoetServiceID{ServiceID: []byte("poet0")}, nil) - poet.EXPECT().Submit(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(&types.PoetRound{}, ErrInvalidRequest) - poet.EXPECT().PowParams(gomock.Any()).Return(&PoetPowParams{}, nil) - poet.EXPECT().Address().Return("http://localhost:9999") - poets = append(poets, poet) - } - { - poet := NewMockPoetProvingServiceClient(ctrl) - poet.EXPECT().PoetServiceID(gomock.Any()).AnyTimes().Return(types.PoetServiceID{ServiceID: []byte("poet1")}, nil) - poet.EXPECT().Submit(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(&types.PoetRound{}, nil) - poet.EXPECT().Proof(gomock.Any(), gomock.Any()).Return(proof, []types.Member{types.Member(challenge.Hash())}, nil) - poet.EXPECT().PowParams(gomock.Any()).Return(&PoetPowParams{}, nil) - poet.EXPECT().Address().Return("http://localhost:9998") - poets = append(poets, poet) - } - - sig, err := signing.NewEdSigner() - req.NoError(err) - 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()).DoAndReturn( - func(ctx context.Context, challenge []byte, _ ...proving.OptionFunc) (*types.Post, *types.PostMetadata, error) { - return &types.Post{}, &types.PostMetadata{ - Challenge: challenge, - }, 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, - poetDb, - []string{}, - t.TempDir(), - logtest.New(t), - sig, - PoetConfig{PhaseShift: layerDuration * layersPerEpoch / 2}, - defaultLayerClockMock(t), - WithNipostValidator(nipostValidator), - withPoetClients(poets), - ) - req.NoError(err) - - // Act - nipost, err := nb.BuildNIPost(context.Background(), &challenge) - req.NoError(err) - - // Verify - ref, _ := proof.Ref() - req.EqualValues(ref[:], nipost.PostMetadata.Challenge) -} - func TestNIPostBuilder_ManyPoETs_AllFinished(t *testing.T) { t.Parallel() // Arrange diff --git a/activation/post_test.go b/activation/post_test.go index 605c82fc32..7820751dee 100644 --- a/activation/post_test.go +++ b/activation/post_test.go @@ -10,6 +10,7 @@ import ( "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/zap/zaptest" "golang.org/x/sync/errgroup" @@ -220,6 +221,53 @@ func TestPostSetupManager_InitialStatus(t *testing.T) { req.Zero(status.NumLabelsWritten) } +func TestPostSetupManager_GenerateProof(t *testing.T) { + req := require.New(t) + ch := make([]byte, 32) + + mgr := newTestPostManager(t) + + // Attempt to generate proof. + _, _, err := mgr.GenerateProof(context.Background(), ch) + req.EqualError(err, errNotComplete.Error()) + + // Create data. + req.NoError(mgr.PrepareInitializer(context.Background(), mgr.opts)) + req.NoError(mgr.StartSession(context.Background())) + + // Generate proof. + p, m, err := mgr.GenerateProof(context.Background(), ch) + req.NoError(err) + + // Verify the proof + verifier, err := verifying.NewProofVerifier() + req.NoError(err) + defer verifier.Close() + err = verifier.Verify(&shared.Proof{ + Nonce: p.Nonce, + Indices: p.Indices, + Pow: p.Pow, + }, &shared.ProofMetadata{ + NodeId: mgr.id.Bytes(), + CommitmentAtxId: mgr.goldenATXID.Bytes(), + Challenge: ch, + NumUnits: mgr.opts.NumUnits, + LabelsPerUnit: m.LabelsPerUnit, + }, + config.DefaultConfig(), + logtest.New(t).WithName("verifying").Zap(), + verifying.WithLabelScryptParams(mgr.opts.Scrypt), + ) + req.NoError(err) + + // Re-instantiate `PostSetupManager`. + mgr = newTestPostManager(t) + + // Attempt to generate proof. + _, _, err = mgr.GenerateProof(context.Background(), ch) + req.ErrorIs(err, errNotComplete) +} + func TestPostSetupManager_VRFNonce(t *testing.T) { req := require.New(t) @@ -408,7 +456,6 @@ type testPostManager struct { cdb *datastore.CachedDB } -// TODO(mafa): start post service with supervisor. func newTestPostManager(tb testing.TB) *testPostManager { tb.Helper() From 80da2cc5ebe62a0c3bd3c9caa1d1a44991650458 Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Fri, 6 Oct 2023 15:53:36 +0000 Subject: [PATCH 10/40] Fix e2e tests --- activation/e2e/nipost_test.go | 50 ++++----- activation/e2e/validation_test.go | 147 ++++++++++++++++++++++++++ activation/e2e/validation_test.go.bak | 64 ----------- 3 files changed, 170 insertions(+), 91 deletions(-) create mode 100644 activation/e2e/validation_test.go delete mode 100644 activation/e2e/validation_test.go.bak diff --git a/activation/e2e/nipost_test.go b/activation/e2e/nipost_test.go index 5ebdd18623..0882ab2b85 100644 --- a/activation/e2e/nipost_test.go +++ b/activation/e2e/nipost_test.go @@ -17,7 +17,6 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/mock/gomock" "go.uber.org/zap" - "go.uber.org/zap/zapcore" "go.uber.org/zap/zaptest" "golang.org/x/sync/errgroup" @@ -140,17 +139,14 @@ func initPost(tb testing.TB, logger *zap.Logger, mgr *activation.PostSetupManage } func TestNIPostBuilderWithClients(t *testing.T) { - logger := zaptest.NewLogger(t) ctrl := gomock.NewController(t) sig, err := signing.NewEdSigner() require.NoError(t, err) - postDir := t.TempDir() + logger := zaptest.NewLogger(t) goldenATX := types.ATXID{2, 3, 4} - cfg := activation.DefaultPostConfig() - cdb := datastore.NewCachedDB(sql.InMemory(), log.NewFromLog(logger)) provingOpts := activation.DefaultPostProvingOpts() @@ -159,6 +155,7 @@ func TestNIPostBuilderWithClients(t *testing.T) { mgr, err := activation.NewPostSetupManager(sig.NodeID(), cfg, logger, cdb, goldenATX, provingOpts) require.NoError(t, err) + postDir := t.TempDir() opts := activation.DefaultPostSetupOpts() opts.DataDir = postDir opts.ProviderID.SetInt64(int64(initialization.CPUProviderID())) @@ -185,12 +182,11 @@ func TestNIPostBuilderWithClients(t *testing.T) { }, ) - poetDb := activation.NewPoetDb(sql.InMemory(), log.NewFromLog(logger).Named("poetDb")) - verifier, err := activation.NewPostVerifier(mgr.Config(), logger.Named("verifier")) require.NoError(t, err) t.Cleanup(func() { assert.NoError(t, verifier.Close()) }) + poetDb := activation.NewPoetDb(sql.InMemory(), log.NewFromLog(logger).Named("poetDb")) v := activation.NewValidator(poetDb, mgr.Config(), mgr.LastOpts().Scrypt, verifier) nb, err := activation.NewNIPostBuilder( @@ -199,7 +195,7 @@ func TestNIPostBuilderWithClients(t *testing.T) { poetDb, []string{poetProver.RestURL().String()}, t.TempDir(), - logtest.New(t, zapcore.DebugLevel), + log.NewFromLog(logger), sig, poetCfg, mclock, @@ -244,16 +240,19 @@ func TestNIPostBuilderWithClients(t *testing.T) { } func TestNIPostBuilder_Close(t *testing.T) { - r := require.New(t) - ctrl := gomock.NewController(t) + + sig, err := signing.NewEdSigner() + require.NoError(t, err) + + logger := zaptest.NewLogger(t) + nipostClient := activation.NewMocknipostClient(ctrl) nipostClient.EXPECT().Status().Return(&activation.PostSetupStatus{State: activation.PostSetupStateComplete}) poetProver := spawnPoet(t, WithGenesis(time.Now()), WithEpochDuration(time.Second)) + poetDb := activation.NewMockpoetDbAPI(ctrl) - challenge := types.NIPostChallenge{ - PublishEpoch: postGenesisEpoch + 2, - } + mclock := activation.NewMocklayerClock(ctrl) mclock.EXPECT().LayerToTime(gomock.Any()).AnyTimes().DoAndReturn( func(got types.LayerID) time.Time { @@ -263,40 +262,38 @@ func TestNIPostBuilder_Close(t *testing.T) { }, ) - sig, err := signing.NewEdSigner() - r.NoError(err) nb, err := activation.NewNIPostBuilder( - types.NodeID{1}, + sig.NodeID(), nipostClient, poetDb, []string{poetProver.RestURL().String()}, t.TempDir(), - logtest.New(t), + log.NewFromLog(logger), sig, activation.PoetConfig{}, mclock, ) - r.NoError(err) + require.NoError(t, err) ctx, cancel := context.WithCancel(context.Background()) cancel() + challenge := types.NIPostChallenge{ + PublishEpoch: postGenesisEpoch + 2, + } nipost, err := nb.BuildNIPost(ctx, &challenge) - r.ErrorIs(err, context.Canceled) - r.Nil(nipost) + require.ErrorIs(t, err, context.Canceled) + require.Nil(t, nipost) } func TestNewNIPostBuilderNotInitialized(t *testing.T) { - logger := zaptest.NewLogger(t) ctrl := gomock.NewController(t) sig, err := signing.NewEdSigner() require.NoError(t, err) - postDir := t.TempDir() + logger := zaptest.NewLogger(t) goldenATX := types.ATXID{2, 3, 4} - cfg := activation.DefaultPostConfig() - cdb := datastore.NewCachedDB(sql.InMemory(), log.NewFromLog(logger)) provingOpts := activation.DefaultPostProvingOpts() @@ -314,7 +311,6 @@ func TestNewNIPostBuilderNotInitialized(t *testing.T) { RequestRetryDelay: epoch / 100, MaxRequestRetries: 10, } - poetProver := spawnPoet(t, WithGenesis(time.Now()), WithEpochDuration(epoch), WithPhaseShift(poetCfg.PhaseShift), WithCycleGap(poetCfg.CycleGap)) mclock := activation.NewMocklayerClock(ctrl) @@ -327,7 +323,6 @@ func TestNewNIPostBuilderNotInitialized(t *testing.T) { ) poetDb := activation.NewPoetDb(sql.InMemory(), log.NewFromLog(logger).Named("poetDb")) - nipostValidator := activation.NewMocknipostValidator(ctrl) nipostValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(1).Return(nil) @@ -356,6 +351,7 @@ func TestNewNIPostBuilderNotInitialized(t *testing.T) { grpcCfg, cleanup := launchServer(t, svc) t.Cleanup(cleanup) + postDir := t.TempDir() t.Cleanup(launchPostSupervisor(t, logger, grpcCfg, postDir)) select { @@ -382,7 +378,7 @@ func TestNewNIPostBuilderNotInitialized(t *testing.T) { require.NoError(t, err) require.NotNil(t, nipost) - verifier, err := activation.NewPostVerifier(mgr.Config(), zaptest.NewLogger(t).Named("verifier")) + verifier, err := activation.NewPostVerifier(mgr.Config(), logger.Named("verifier")) require.NoError(t, err) t.Cleanup(func() { assert.NoError(t, verifier.Close()) }) diff --git a/activation/e2e/validation_test.go b/activation/e2e/validation_test.go new file mode 100644 index 0000000000..4bdfa5f16b --- /dev/null +++ b/activation/e2e/validation_test.go @@ -0,0 +1,147 @@ +package activation_test + +import ( + "context" + "fmt" + "testing" + "time" + + "github.com/spacemeshos/post/config" + "github.com/spacemeshos/post/initialization" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/mock/gomock" + "go.uber.org/zap/zapcore" + "go.uber.org/zap/zaptest" + + "github.com/spacemeshos/go-spacemesh/activation" + "github.com/spacemeshos/go-spacemesh/api/grpcserver" + "github.com/spacemeshos/go-spacemesh/common/types" + "github.com/spacemeshos/go-spacemesh/datastore" + "github.com/spacemeshos/go-spacemesh/log" + "github.com/spacemeshos/go-spacemesh/log/logtest" + "github.com/spacemeshos/go-spacemesh/signing" + "github.com/spacemeshos/go-spacemesh/sql" +) + +func TestValidator_Validate(t *testing.T) { + ctrl := gomock.NewController(t) + + sig, err := signing.NewEdSigner() + require.NoError(t, err) + + logger := zaptest.NewLogger(t) + goldenATX := types.ATXID{2, 3, 4} + cfg := activation.DefaultPostConfig() + cdb := datastore.NewCachedDB(sql.InMemory(), log.NewFromLog(logger)) + + provingOpts := activation.DefaultPostProvingOpts() + provingOpts.Flags = config.RecommendedPowFlags() + + mgr, err := activation.NewPostSetupManager(sig.NodeID(), cfg, logger, cdb, goldenATX, provingOpts) + require.NoError(t, err) + + postDir := t.TempDir() + opts := activation.DefaultPostSetupOpts() + opts.DataDir = postDir + opts.ProviderID.SetInt64(int64(initialization.CPUProviderID())) + opts.Scrypt.N = 2 // Speedup initialization in tests. + initPost(t, logger.Named("manager"), mgr, opts) + + epoch := layersPerEpoch * layerDuration + poetCfg := activation.PoetConfig{ + PhaseShift: epoch / 2, + CycleGap: epoch / 5, + GracePeriod: epoch / 5, + RequestTimeout: epoch / 5, + RequestRetryDelay: epoch / 50, + MaxRequestRetries: 10, + } + poetProver := spawnPoet(t, WithGenesis(time.Now()), WithEpochDuration(epoch), WithPhaseShift(poetCfg.PhaseShift), WithCycleGap(poetCfg.CycleGap)) + + mclock := activation.NewMocklayerClock(ctrl) + mclock.EXPECT().LayerToTime(gomock.Any()).AnyTimes().DoAndReturn( + func(got types.LayerID) time.Time { + // time.Now() ~= currentLayer + genesis := time.Now().Add(-time.Duration(postGenesisEpoch.FirstLayer()) * layerDuration) + return genesis.Add(layerDuration * time.Duration(got)) + }, + ) + + verifier, err := activation.NewPostVerifier(mgr.Config(), logger.Named("verifier")) + require.NoError(t, err) + t.Cleanup(func() { assert.NoError(t, verifier.Close()) }) + + poetDb := activation.NewPoetDb(sql.InMemory(), log.NewFromLog(logger).Named("poetDb")) + v := activation.NewValidator(poetDb, mgr.Config(), mgr.LastOpts().Scrypt, verifier) + + nb, err := activation.NewNIPostBuilder( + sig.NodeID(), + mgr, + poetDb, + []string{poetProver.RestURL().String()}, + t.TempDir(), + logtest.New(t, zapcore.DebugLevel), + sig, + poetCfg, + mclock, + activation.WithNipostValidator(v), + ) + require.NoError(t, err) + + connected := make(chan struct{}) + con := grpcserver.NewMockpostConnectionListener(ctrl) + con.EXPECT().Connected(gomock.Any()).DoAndReturn(func(c activation.PostClient) { + close(connected) + }).Times(1) + con.EXPECT().Disconnected(gomock.Any()).Times(1) + + svc := grpcserver.NewPostService(logger, nb, con) + grpcCfg, cleanup := launchServer(t, svc) + t.Cleanup(cleanup) + + t.Cleanup(launchPostSupervisor(t, logger, grpcCfg, postDir)) + + select { + case <-connected: + case <-time.After(10 * time.Second): + require.Fail(t, "timed out waiting for connection") + } + + challenge := types.NIPostChallenge{ + PublishEpoch: postGenesisEpoch + 2, + } + challengeHash := challenge.Hash() + + nipost, err := nb.BuildNIPost(context.Background(), &challenge) + require.NoError(t, err) + + _, err = v.NIPost(context.Background(), sig.NodeID(), goldenATX, nipost, challengeHash, mgr.LastOpts().NumUnits) + require.NoError(t, err) + + _, err = v.NIPost(context.Background(), sig.NodeID(), goldenATX, nipost, types.BytesToHash([]byte("lerner")), mgr.LastOpts().NumUnits) + require.ErrorContains(t, err, "invalid membership proof") + + newNIPost := *nipost + newNIPost.Post = &types.Post{} + _, err = v.NIPost(context.Background(), sig.NodeID(), goldenATX, &newNIPost, challengeHash, mgr.LastOpts().NumUnits) + require.ErrorContains(t, err, "invalid Post") + + newPostCfg := mgr.Config() + newPostCfg.MinNumUnits = mgr.LastOpts().NumUnits + 1 + v = activation.NewValidator(poetDb, newPostCfg, mgr.LastOpts().Scrypt, nil) + _, err = v.NIPost(context.Background(), sig.NodeID(), goldenATX, nipost, challengeHash, mgr.LastOpts().NumUnits) + require.EqualError(t, err, fmt.Sprintf("invalid `numUnits`; expected: >=%d, given: %d", newPostCfg.MinNumUnits, mgr.LastOpts().NumUnits)) + + newPostCfg = mgr.Config() + newPostCfg.MaxNumUnits = mgr.LastOpts().NumUnits - 1 + v = activation.NewValidator(poetDb, newPostCfg, mgr.LastOpts().Scrypt, nil) + _, err = v.NIPost(context.Background(), sig.NodeID(), goldenATX, nipost, challengeHash, mgr.LastOpts().NumUnits) + require.EqualError(t, err, fmt.Sprintf("invalid `numUnits`; expected: <=%d, given: %d", newPostCfg.MaxNumUnits, mgr.LastOpts().NumUnits)) + + newPostCfg = mgr.Config() + newPostCfg.LabelsPerUnit = nipost.PostMetadata.LabelsPerUnit + 1 + v = activation.NewValidator(poetDb, newPostCfg, mgr.LastOpts().Scrypt, nil) + _, err = v.NIPost(context.Background(), sig.NodeID(), goldenATX, nipost, challengeHash, mgr.LastOpts().NumUnits) + require.EqualError(t, err, fmt.Sprintf("invalid `LabelsPerUnit`; expected: >=%d, given: %d", newPostCfg.LabelsPerUnit, nipost.PostMetadata.LabelsPerUnit)) +} diff --git a/activation/e2e/validation_test.go.bak b/activation/e2e/validation_test.go.bak deleted file mode 100644 index 030b24049a..0000000000 --- a/activation/e2e/validation_test.go.bak +++ /dev/null @@ -1,64 +0,0 @@ -package activation_test - -import ( - "context" - "fmt" - "testing" - - "github.com/spacemeshos/go-spacemesh/activation" - "github.com/spacemeshos/go-spacemesh/common/types" - "github.com/spacemeshos/go-spacemesh/log/logtest" - "github.com/spacemeshos/go-spacemesh/sql" - "go.uber.org/zap/zaptest" - - "github.com/stretchr/testify/require" -) - -func TestValidator_Validate(t *testing.T) { - r := require.New(t) - - challenge := types.NIPostChallenge{ - PublishEpoch: postGenesisEpoch + 2, - } - challengeHash := challenge.Hash() - poetDb := activation.NewPoetDb(sql.InMemory(), logtest.New(t).WithName("poetDb")) - - log := zaptest.NewLogger(t) - postProvider := newTestPostManager(t) - verifier, err := activation.NewPostVerifier(postProvider.cfg, log.Named("verifier")) - r.NoError(err) - defer verifier.Close() - - v := activation.NewValidator(poetDb, postProvider.cfg, postProvider.opts.Scrypt, verifier) - - nipost := buildNIPost(t, postProvider, challenge, poetDb, v) - - _, 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) - 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) - r.Contains(err.Error(), "invalid Post") - - newPostCfg := postProvider.cfg - newPostCfg.MinNumUnits = postProvider.opts.NumUnits + 1 - v = activation.NewValidator(poetDb, newPostCfg, postProvider.opts.Scrypt, 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 = activation.NewValidator(poetDb, newPostCfg, postProvider.opts.Scrypt, 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 = activation.NewValidator(poetDb, newPostCfg, postProvider.opts.Scrypt, 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)) -} From 455db7f66ed08979ae535a1381a89c9194759822 Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Fri, 6 Oct 2023 16:59:08 +0000 Subject: [PATCH 11/40] Update changelog --- CHANGELOG.md | 7 +++++-- activation/post.go | 6 +++--- activation/post_test.go | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6cb5361ce7..447b1dd093 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,11 +14,14 @@ See [RELEASE](./RELEASE.md) for workflow instructions. * [#5118](https://github.com/spacemeshos/go-spacemesh/pull/5118) reduce number of tortoise results returned after recovery. -this is hotfix for a bug introduced in v1.2.0. in rare conditions node may loop with the following warning: + this is hotfix for a bug introduced in v1.2.0. in rare conditions node may loop with the following warning: -> 2023-10-02T15:28:14.002+0200 WARN fd68b.sync mesh failed to process layer from sync {"node_id": "fd68b9397572556c2f329f3e5af2faf23aef85dbbbb7e38447fae2f4ef38899f", "module": "sync", "sessionId": "29422935-68d6-47d1-87a8-02293aa181f3", "layer_id": 23104, "errmsg": "requested layer 8063 is before evicted 13102", "name": "sync"} + > 2023-10-02T15:28:14.002+0200 WARN fd68b.sync mesh failed to process layer from sync {"node_id": "fd68b9397572556c2f329f3e5af2faf23aef85dbbbb7e38447fae2f4ef38899f", "module": "sync", "sessionId": "29422935-68d6-47d1-87a8-02293aa181f3", "layer_id": 23104, "errmsg": "requested layer 8063 is before evicted 13102", "name": "sync"} * [#5091](https://github.com/spacemeshos/go-spacemesh/pull/5091) First stage of separating PoST from the node into its own service. +* [#5061](https://github.com/spacemeshos/go-spacemesh/pull/5061) Proof generation is now done via a dedicated service instead of the node. + + Usage is unchanged for now, the service runs within the container and is started automatically when deployed via docker. When used via smapp the node starts the service automatically. * [#5138](https://github.com/spacemeshos/go-spacemesh/pull/5138) Bump poet to v0.9.7 diff --git a/activation/post.go b/activation/post.go index 22a0353102..22698a3e46 100644 --- a/activation/post.go +++ b/activation/post.go @@ -278,8 +278,8 @@ func (*PostSetupManager) Providers() ([]PostSetupProvider, error) { return providersAlias, nil } -// BestProvider returns the most performant compute provider based on a short benchmarking session. -func (mgr *PostSetupManager) BestProvider() (*PostSetupProvider, error) { +// bestProvider returns the most performant compute provider based on a short benchmarking session. +func (mgr *PostSetupManager) bestProvider() (*PostSetupProvider, error) { providers, err := mgr.Providers() if err != nil { return nil, fmt.Errorf("fetch best provider: %w", err) @@ -392,7 +392,7 @@ func (mgr *PostSetupManager) PrepareInitializer(ctx context.Context, opts PostSe if opts.ProviderID.Value() != nil && *opts.ProviderID.Value() == -1 { mgr.logger.Warn("DEPRECATED: auto-determining compute provider is deprecated, please specify a valid provider ID in the config file") - p, err := mgr.BestProvider() + p, err := mgr.bestProvider() if err != nil { return err } diff --git a/activation/post_test.go b/activation/post_test.go index 7820751dee..30cd36d2f5 100644 --- a/activation/post_test.go +++ b/activation/post_test.go @@ -399,7 +399,7 @@ func TestPostSetupManager_Providers_includesCPU(t *testing.T) { func TestPostSetupManager_BestProvider(t *testing.T) { mgr := newTestPostManager(t) - providers, err := mgr.BestProvider() + providers, err := mgr.bestProvider() require.NoError(t, err) require.NotNil(t, providers) } From f70c9721f192975badfb50234bdddb16f09ce560 Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Fri, 6 Oct 2023 17:55:59 +0000 Subject: [PATCH 12/40] Try fixing flaky tests on macos --- api/grpcserver/post_service_test.go | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/api/grpcserver/post_service_test.go b/api/grpcserver/post_service_test.go index c7c800220f..11cdb71fa4 100644 --- a/api/grpcserver/post_service_test.go +++ b/api/grpcserver/post_service_test.go @@ -99,8 +99,6 @@ func launchPostSupervisor(tb testing.TB, log *zap.Logger, cfg Config, postDir st } func Test_GenerateProof(t *testing.T) { - t.Parallel() - log := zaptest.NewLogger(t) ctrl := gomock.NewController(t) con := NewMockpostConnectionListener(ctrl) @@ -123,7 +121,7 @@ func Test_GenerateProof(t *testing.T) { select { case <-connected: - case <-time.After(10 * time.Second): + case <-time.After(5 * time.Second): require.Fail(t, "timed out waiting for connection") } @@ -150,8 +148,6 @@ func Test_GenerateProof(t *testing.T) { } func Test_Cancel_GenerateProof(t *testing.T) { - t.Parallel() - log := zaptest.NewLogger(t) ctrl := gomock.NewController(t) con := NewMockpostConnectionListener(ctrl) @@ -173,7 +169,7 @@ func Test_Cancel_GenerateProof(t *testing.T) { select { case <-connected: - case <-time.After(10 * time.Second): + case <-time.After(5 * time.Second): require.Fail(t, "timed out waiting for connection") } @@ -193,8 +189,6 @@ func Test_Cancel_GenerateProof(t *testing.T) { } func Test_GenerateProof_MultipleServices(t *testing.T) { - t.Parallel() - log := zaptest.NewLogger(t) ctrl := gomock.NewController(t) con := NewMockpostConnectionListener(ctrl) @@ -225,7 +219,7 @@ func Test_GenerateProof_MultipleServices(t *testing.T) { select { case <-connected: - case <-time.After(10 * time.Second): + case <-time.After(5 * time.Second): require.Fail(t, "timed out waiting for connection") } From 7d74bd00a687054889ba335a233ea29d44d044bf Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Fri, 6 Oct 2023 18:25:12 +0000 Subject: [PATCH 13/40] Start nodes with private post service --- systest/parameters/fastnet/smesher.json | 4 +++- systest/systest_job.yml.tmpl | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/systest/parameters/fastnet/smesher.json b/systest/parameters/fastnet/smesher.json index 73c20742c6..e30df571c0 100644 --- a/systest/parameters/fastnet/smesher.json +++ b/systest/parameters/fastnet/smesher.json @@ -13,7 +13,9 @@ "debug", "global", "mesh", "node", "transaction", "activation", "admin", "smesher" ], - "grpc-private-services": [] + "grpc-private-services": [ + "post" + ] }, "logging": { "hare": "debug" diff --git a/systest/systest_job.yml.tmpl b/systest/systest_job.yml.tmpl index 63a87904de..32ef4a50ff 100644 --- a/systest/systest_job.yml.tmpl +++ b/systest/systest_job.yml.tmpl @@ -5,7 +5,7 @@ apiVersion: batch/v1 kind: Job metadata: - name: {{ .Env.job_name}} + name: {{ .Env.job_name }} labels: testid: {{ .Env.testid }} spec: From f6bc1c70742d0c97b644bcf3e9e45cc0dd33b489 Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Fri, 6 Oct 2023 19:58:37 +0000 Subject: [PATCH 14/40] Start PoST service with right data dir --- systest/cluster/nodes.go | 1 + 1 file changed, 1 insertion(+) diff --git a/systest/cluster/nodes.go b/systest/cluster/nodes.go index edaec3347f..19836f591b 100644 --- a/systest/cluster/nodes.go +++ b/systest/cluster/nodes.go @@ -473,6 +473,7 @@ func deployNode(ctx *testcontext.Context, id string, labels map[string]string, f "-c=" + configDir + attachedSmesherConfig, "--pprof-server", "--smeshing-opts-datadir=/data/post", + "--post-opts-datadir=/data/post", "-d=/data/state", "--log-encoder=json", "--metrics", From f8aa06f9d9ffa54b31d34f7531f4af757c4d9055 Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Fri, 6 Oct 2023 20:08:05 +0000 Subject: [PATCH 15/40] Use higher tick interval to reduce load --- activation/e2e/nipost_test.go | 8 +++----- activation/post_test.go | 4 +--- api/grpcserver/post_service_test.go | 4 ++-- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/activation/e2e/nipost_test.go b/activation/e2e/nipost_test.go index 0882ab2b85..d3910e5fe4 100644 --- a/activation/e2e/nipost_test.go +++ b/activation/e2e/nipost_test.go @@ -101,16 +101,16 @@ func launchServer(tb testing.TB, services ...grpcserver.ServiceAPI) (grpcserver. return cfg, func() { assert.NoError(tb, grpcService.Close()) } } -func initPost(tb testing.TB, logger *zap.Logger, mgr *activation.PostSetupManager, opts activation.PostSetupOpts) *activation.PostSetupManager { +func initPost(tb testing.TB, logger *zap.Logger, mgr *activation.PostSetupManager, opts activation.PostSetupOpts) { tb.Helper() ctx, cancel := context.WithCancel(context.Background()) - tb.Cleanup(cancel) + defer cancel() var eg errgroup.Group lastStatus := &activation.PostSetupStatus{} eg.Go(func() error { - timer := time.NewTicker(50 * time.Millisecond) + timer := time.NewTicker(100 * time.Millisecond) defer timer.Stop() for { @@ -134,8 +134,6 @@ func initPost(tb testing.TB, logger *zap.Logger, mgr *activation.PostSetupManage require.NoError(tb, mgr.StartSession(context.Background())) require.NoError(tb, eg.Wait()) require.Equal(tb, activation.PostSetupStateComplete, mgr.Status().State) - - return mgr } func TestNIPostBuilderWithClients(t *testing.T) { diff --git a/activation/post_test.go b/activation/post_test.go index 30cd36d2f5..fcada3d6c7 100644 --- a/activation/post_test.go +++ b/activation/post_test.go @@ -33,7 +33,7 @@ func TestPostSetupManager(t *testing.T) { var eg errgroup.Group lastStatus := &PostSetupStatus{} eg.Go(func() error { - timer := time.NewTicker(50 * time.Millisecond) + timer := time.NewTicker(100 * time.Millisecond) defer timer.Stop() for { @@ -55,9 +55,7 @@ func TestPostSetupManager(t *testing.T) { // Create data. req.NoError(mgr.PrepareInitializer(context.Background(), mgr.opts)) req.NoError(mgr.StartSession(context.Background())) - cancel() require.NoError(t, eg.Wait()) - req.Equal(PostSetupStateComplete, mgr.Status().State) // Create data (same opts). diff --git a/api/grpcserver/post_service_test.go b/api/grpcserver/post_service_test.go index 11cdb71fa4..fde9c49f44 100644 --- a/api/grpcserver/post_service_test.go +++ b/api/grpcserver/post_service_test.go @@ -48,12 +48,12 @@ func initPost(tb testing.TB, log *zap.Logger, dir string) { require.NoError(tb, err) ctx, cancel := context.WithCancel(context.Background()) - tb.Cleanup(cancel) + defer cancel() var eg errgroup.Group lastStatus := &activation.PostSetupStatus{} eg.Go(func() error { - timer := time.NewTicker(50 * time.Millisecond) + timer := time.NewTicker(100 * time.Millisecond) defer timer.Stop() for { From fa87e2fb88a96a0fff094f3241884b2f4cf2180c Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Fri, 6 Oct 2023 20:09:39 +0000 Subject: [PATCH 16/40] Increase timeout --- node/node_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node/node_test.go b/node/node_test.go index 4499959c95..2c184f4c7c 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -1143,7 +1143,7 @@ func TestAdminEvents(t *testing.T) { t.Cleanup(func() { assert.NoError(t, conn.Close()) }) client := pb.NewAdminServiceClient(conn) - tctx, cancel := context.WithTimeout(ctx, 2*time.Minute) + tctx, cancel := context.WithTimeout(ctx, 3*time.Minute) defer cancel() // 4 is arbitrary, if we received events once, they must be From 6bc842fcac3c530696f08a42b8fa7ac43b00d99f Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Sat, 7 Oct 2023 09:14:18 +0000 Subject: [PATCH 17/40] Add cmd parameters --- activation/post_test.go | 2 +- cmd/root.go | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/activation/post_test.go b/activation/post_test.go index fcada3d6c7..55bcf833bf 100644 --- a/activation/post_test.go +++ b/activation/post_test.go @@ -39,7 +39,7 @@ func TestPostSetupManager(t *testing.T) { for { select { case <-ctx.Done(): - return nil + return ctx.Err() case <-timer.C: status := mgr.Status() req.GreaterOrEqual(status.NumLabelsWritten, lastStatus.NumLabelsWritten) diff --git a/cmd/root.go b/cmd/root.go index 8c7142a4ab..d8b4f666ca 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -245,6 +245,31 @@ func AddCommands(cmd *cobra.Command) { cmd.PersistentFlags().BoolVar(&cfg.SMESHING.Opts.Throttle, "smeshing-opts-throttle", cfg.SMESHING.Opts.Throttle, "") + /**======================== PoST service Flags ========================== **/ + + cmd.PersistentFlags().StringVar(&cfg.POSTService.PostServiceCmd, "post-opts-post-service", + cfg.POSTService.PostServiceCmd, "") + cmd.PersistentFlags().StringVar(&cfg.POSTService.DataDir, "post-opts-datadir", + cfg.POSTService.DataDir, "") + cmd.PersistentFlags().StringVar(&cfg.POSTService.NodeAddress, "post-opts-node-address", + cfg.POSTService.NodeAddress, "") + cmd.PersistentFlags().StringVar(&cfg.POSTService.PostServiceMode, "post-opts-post-service-mode", + cfg.POSTService.PostServiceMode, "") + cmd.PersistentFlags().VarP(&cfg.POSTService.PowDifficulty, "post-opts-pow-difficulty", + "", "") + cmd.PersistentFlags().Uint32Var(&cfg.POSTService.K1, "post-opts-k1", + cfg.POSTService.K1, "") + cmd.PersistentFlags().Uint32Var(&cfg.POSTService.K2, "post-opts-k2", + cfg.POSTService.K2, "") + cmd.PersistentFlags().Uint32Var(&cfg.POSTService.K3, "post-opts-k3", + cfg.POSTService.K3, "") + cmd.PersistentFlags().UintVar(&cfg.POSTService.N, "post-opts-n", + cfg.POSTService.N, "") + cmd.PersistentFlags().UintVar(&cfg.POSTService.R, "post-opts-r", + cfg.POSTService.R, "") + cmd.PersistentFlags().UintVar(&cfg.POSTService.P, "post-opts-p", + cfg.POSTService.P, "") + /**======================== Consensus Flags ========================== **/ cmd.PersistentFlags().Uint32Var(&cfg.LayersPerEpoch, "layers-per-epoch", From a22c2a58f8756cfc8cd204db39c60109856a7839 Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Sat, 7 Oct 2023 09:44:32 +0000 Subject: [PATCH 18/40] Add logging to post supervisor --- activation/post_supervisor.go | 1 + 1 file changed, 1 insertion(+) diff --git a/activation/post_supervisor.go b/activation/post_supervisor.go index f20393b95f..d68008443c 100644 --- a/activation/post_supervisor.go +++ b/activation/post_supervisor.go @@ -157,6 +157,7 @@ func (ps *PostSupervisor) runCmd(ctx context.Context, opts PostSupervisorConfig) return fmt.Errorf("start post service: %w", err) } ps.pid.Store(int64(cmd.Process.Pid)) + ps.logger.Info("post service started", zap.Int("pid", cmd.Process.Pid), zap.String("cmd", cmd.String())) events.EmitPostServiceStarted() err = cmd.Wait() if err := ctx.Err(); err != nil { From e8b25333df981e888681b6fc28f25e4bd5fe1766 Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Sat, 7 Oct 2023 09:59:10 +0000 Subject: [PATCH 19/40] Fix TestAdmin failing on windows --- config/presets/standalone.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/config/presets/standalone.go b/config/presets/standalone.go index 5cd209c01e..9ff1012261 100644 --- a/config/presets/standalone.go +++ b/config/presets/standalone.go @@ -1,7 +1,6 @@ package presets import ( - "fmt" "math/big" "os" "path/filepath" @@ -89,7 +88,7 @@ func standalone() config.Config { conf.API.PublicListener = "0.0.0.0:10092" conf.API.PrivateListener = "0.0.0.0:10093" - conf.POSTService.NodeAddress = fmt.Sprintf("http://%s", conf.API.PrivateListener) + conf.POSTService.NodeAddress = "http://127.0.0.1:10093" conf.POSTService.DataDir = conf.SMESHING.Opts.DataDir conf.POSTService.K1 = conf.POST.K1 From 2f288a9b52566b8027d2573569fcd7f212d1c96b Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Sat, 7 Oct 2023 10:59:55 +0000 Subject: [PATCH 20/40] Fix cmd options for post service not used --- activation/post_supervisor.go | 2 +- cmd/base.go | 4 ++++ cmd/root.go | 7 +++++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/activation/post_supervisor.go b/activation/post_supervisor.go index d68008443c..fec62195e1 100644 --- a/activation/post_supervisor.go +++ b/activation/post_supervisor.go @@ -156,8 +156,8 @@ func (ps *PostSupervisor) runCmd(ctx context.Context, opts PostSupervisorConfig) pipe.Close() return fmt.Errorf("start post service: %w", err) } - ps.pid.Store(int64(cmd.Process.Pid)) ps.logger.Info("post service started", zap.Int("pid", cmd.Process.Pid), zap.String("cmd", cmd.String())) + ps.pid.Store(int64(cmd.Process.Pid)) events.EmitPostServiceStarted() err = cmd.Wait() if err := ctx.Err(); err != nil { diff --git a/cmd/base.go b/cmd/base.go index ecd266b76b..f33bef8597 100644 --- a/cmd/base.go +++ b/cmd/base.go @@ -148,6 +148,10 @@ func EnsureCLIFlags(cmd *cobra.Command, appCFG *config.Config) error { elem = reflect.ValueOf(&appCFG.POST).Elem() assignFields(ff, elem, name) + ff = reflect.TypeOf(appCFG.POSTService) + elem = reflect.ValueOf(&appCFG.POSTService).Elem() + assignFields(ff, elem, name) + ff = reflect.TypeOf(appCFG.SMESHING) elem = reflect.ValueOf(&appCFG.SMESHING).Elem() assignFields(ff, elem, name) diff --git a/cmd/root.go b/cmd/root.go index d8b4f666ca..38a444f9c8 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -72,7 +72,7 @@ func AddCommands(cmd *cobra.Command) { cfg.OptFilterThreshold, "threshold for optimistic filtering in percentage") cmd.PersistentFlags().VarP(flags.NewStringToUint64Value(map[string]uint64{}), "accounts", "a", - "List of prefunded accounts") + "List of pre-funded accounts") cmd.PersistentFlags().IntVar(&cfg.DatabaseConnections, "db-connections", cfg.DatabaseConnections, "configure number of active connections to enable parallel read requests") @@ -118,6 +118,7 @@ func AddCommands(cmd *cobra.Command) { 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.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 ========================== **/ cmd.PersistentFlags().BoolVar(&cfg.TIME.Peersync.Disable, "peersync-disable", cfg.TIME.Peersync.Disable, @@ -134,6 +135,7 @@ func AddCommands(cmd *cobra.Command) { cfg.TIME.Peersync.MaxOffsetErrors, "the node will exit when max number of consecutive offset errors will be reached") cmd.PersistentFlags().IntVar(&cfg.TIME.Peersync.RequiredResponses, "peersync-required-responses", cfg.TIME.Peersync.RequiredResponses, "min number of clock samples from other that need to be collected to verify time") + /** ======================== API Flags ========================== **/ cmd.PersistentFlags().StringSliceVar(&cfg.API.PublicServices, "grpc-public-services", @@ -209,7 +211,7 @@ func AddCommands(cmd *cobra.Command) { cmd.PersistentFlags().Uint32Var(&cfg.Tortoise.BadBeaconVoteDelayLayers, "tortoise-delay-layers", cfg.Tortoise.BadBeaconVoteDelayLayers, "number of layers to ignore a ballot with a different beacon") cmd.PersistentFlags().BoolVar(&cfg.Tortoise.EnableTracer, "tortoise-enable-tracer", - cfg.Tortoise.EnableTracer, "recovrd every tortoise input/output into the loggin output") + cfg.Tortoise.EnableTracer, "record every tortoise input/output to the logging output") // TODO(moshababo): add usage desc cmd.PersistentFlags().Uint64Var(&cfg.POST.LabelsPerUnit, "post-labels-per-unit", @@ -287,6 +289,7 @@ func AddCommands(cmd *cobra.Command) { cfg.POET.RequestTimeout, "timeout for poet requests") /**======================== bootstrap data updater Flags ========================== **/ + cmd.PersistentFlags().StringVar(&cfg.Bootstrap.URL, "bootstrap-url", cfg.Bootstrap.URL, "the url to query bootstrap data update") cmd.PersistentFlags().StringVar(&cfg.Bootstrap.Version, "bootstrap-version", From 9fa16f635f46d67daa0e7eaed935a20d38fd55c2 Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Sat, 7 Oct 2023 11:42:32 +0000 Subject: [PATCH 21/40] Deflaking tests --- activation/e2e/nipost_test.go | 7 +++--- activation/post_test.go | 33 +++++++++++++---------------- api/grpcserver/post_service_test.go | 7 +++--- 3 files changed, 23 insertions(+), 24 deletions(-) diff --git a/activation/e2e/nipost_test.go b/activation/e2e/nipost_test.go index d3910e5fe4..e47606ea65 100644 --- a/activation/e2e/nipost_test.go +++ b/activation/e2e/nipost_test.go @@ -108,11 +108,11 @@ func initPost(tb testing.TB, logger *zap.Logger, mgr *activation.PostSetupManage defer cancel() var eg errgroup.Group - lastStatus := &activation.PostSetupStatus{} eg.Go(func() error { - timer := time.NewTicker(100 * time.Millisecond) + timer := time.NewTicker(50 * time.Millisecond) defer timer.Stop() + lastStatus := &activation.PostSetupStatus{} for { select { case <-ctx.Done(): @@ -124,7 +124,8 @@ func initPost(tb testing.TB, logger *zap.Logger, mgr *activation.PostSetupManage if status.NumLabelsWritten == uint64(mgr.LastOpts().NumUnits)*mgr.Config().LabelsPerUnit { return nil } - require.Equal(tb, activation.PostSetupStateInProgress, status.State) + require.Contains(tb, []activation.PostSetupState{activation.PostSetupStatePrepared, activation.PostSetupStateInProgress}, status.State) + lastStatus = status } } }) diff --git a/activation/post_test.go b/activation/post_test.go index 55bcf833bf..073a835d88 100644 --- a/activation/post_test.go +++ b/activation/post_test.go @@ -23,52 +23,51 @@ import ( ) func TestPostSetupManager(t *testing.T) { - req := require.New(t) - mgr := newTestPostManager(t) ctx, cancel := context.WithCancel(context.Background()) defer cancel() var eg errgroup.Group - lastStatus := &PostSetupStatus{} eg.Go(func() error { - timer := time.NewTicker(100 * time.Millisecond) + timer := time.NewTicker(50 * time.Millisecond) defer timer.Stop() + lastStatus := &PostSetupStatus{} for { select { case <-ctx.Done(): return ctx.Err() case <-timer.C: status := mgr.Status() - req.GreaterOrEqual(status.NumLabelsWritten, lastStatus.NumLabelsWritten) + require.GreaterOrEqual(t, status.NumLabelsWritten, lastStatus.NumLabelsWritten) if status.NumLabelsWritten == uint64(mgr.opts.NumUnits)*mgr.cfg.LabelsPerUnit { return nil } - req.Equal(PostSetupStateInProgress, status.State) + require.Contains(t, []PostSetupState{PostSetupStatePrepared, PostSetupStateInProgress}, status.State) + lastStatus = status } } }) // Create data. - req.NoError(mgr.PrepareInitializer(context.Background(), mgr.opts)) - req.NoError(mgr.StartSession(context.Background())) + require.NoError(t, mgr.PrepareInitializer(context.Background(), mgr.opts)) + require.NoError(t, mgr.StartSession(context.Background())) require.NoError(t, eg.Wait()) - req.Equal(PostSetupStateComplete, mgr.Status().State) + require.Equal(t, PostSetupStateComplete, mgr.Status().State) // Create data (same opts). - req.NoError(mgr.PrepareInitializer(context.Background(), mgr.opts)) - req.NoError(mgr.StartSession(context.Background())) + require.NoError(t, mgr.PrepareInitializer(context.Background(), mgr.opts)) + require.NoError(t, mgr.StartSession(context.Background())) // Cleanup. - req.NoError(mgr.Reset()) + require.NoError(t, mgr.Reset()) // Create data (same opts, after deletion). - req.NoError(mgr.PrepareInitializer(context.Background(), mgr.opts)) - req.NoError(mgr.StartSession(context.Background())) - req.Equal(PostSetupStateComplete, mgr.Status().State) + require.NoError(t, mgr.PrepareInitializer(context.Background(), mgr.opts)) + require.NoError(t, mgr.StartSession(context.Background())) + require.Equal(t, PostSetupStateComplete, mgr.Status().State) } // Checks that PrepareInitializer returns an error when invalid opts are given. @@ -109,15 +108,13 @@ func TestPostSetupManager_PrepareInitializer(t *testing.T) { // TODO(mafa): remove, see https://github.com/spacemeshos/go-spacemesh/issues/4801 func TestPostSetupManager_PrepareInitializer_BestProvider(t *testing.T) { - req := require.New(t) - mgr := newTestPostManager(t) ctx, cancel := context.WithTimeout(context.Background(), time.Second*30) defer cancel() mgr.opts.ProviderID.SetInt64(-1) - req.NoError(mgr.PrepareInitializer(ctx, mgr.opts)) + require.NoError(t, mgr.PrepareInitializer(ctx, mgr.opts)) } func TestPostSetupManager_StartSession_WithoutProvider_Error(t *testing.T) { diff --git a/api/grpcserver/post_service_test.go b/api/grpcserver/post_service_test.go index fde9c49f44..37120813b3 100644 --- a/api/grpcserver/post_service_test.go +++ b/api/grpcserver/post_service_test.go @@ -51,11 +51,11 @@ func initPost(tb testing.TB, log *zap.Logger, dir string) { defer cancel() var eg errgroup.Group - lastStatus := &activation.PostSetupStatus{} eg.Go(func() error { - timer := time.NewTicker(100 * time.Millisecond) + timer := time.NewTicker(50 * time.Millisecond) defer timer.Stop() + lastStatus := &activation.PostSetupStatus{} for { select { case <-ctx.Done(): @@ -67,7 +67,8 @@ func initPost(tb testing.TB, log *zap.Logger, dir string) { if status.NumLabelsWritten == uint64(opts.NumUnits)*cfg.LabelsPerUnit { return nil } - require.Equal(tb, activation.PostSetupStateInProgress, status.State) + require.Contains(tb, []activation.PostSetupState{activation.PostSetupStatePrepared, activation.PostSetupStateInProgress}, status.State) + lastStatus = status } } }) From f13dffb04363fa9019f070347e2513e09c5c252a Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Mon, 9 Oct 2023 10:13:11 +0000 Subject: [PATCH 22/40] Add deprecated to GenerateProof --- activation/post.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/activation/post.go b/activation/post.go index 22698a3e46..ecf04424e5 100644 --- a/activation/post.go +++ b/activation/post.go @@ -496,7 +496,7 @@ func (mgr *PostSetupManager) Reset() error { return nil } -// GenerateProof generates a new Post. +// Deprecated: GenerateProof generates a new Post. func (mgr *PostSetupManager) GenerateProof(ctx context.Context, challenge []byte, options ...proving.OptionFunc) (*types.Post, *types.PostMetadata, error) { mgr.mu.Lock() From 83c1577e2ec2722983f302915ef4b430aa219c30 Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Mon, 9 Oct 2023 15:36:45 +0000 Subject: [PATCH 23/40] Update CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 447b1dd093..e0d513be46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,7 +21,7 @@ See [RELEASE](./RELEASE.md) for workflow instructions. * [#5091](https://github.com/spacemeshos/go-spacemesh/pull/5091) First stage of separating PoST from the node into its own service. * [#5061](https://github.com/spacemeshos/go-spacemesh/pull/5061) Proof generation is now done via a dedicated service instead of the node. - Usage is unchanged for now, the service runs within the container and is started automatically when deployed via docker. When used via smapp the node starts the service automatically. + Operating a node doesn't require any changes at the moment. The service will be automatically started by the node if needed and will be stopped when the node is stopped. * [#5138](https://github.com/spacemeshos/go-spacemesh/pull/5138) Bump poet to v0.9.7 From ab17f5a6a8d72bf7621fa4f210068e6e7bbc3e5c Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Mon, 9 Oct 2023 15:42:02 +0000 Subject: [PATCH 24/40] Remove post proof validation from nipost builder --- activation/interface.go | 8 -- activation/nipost.go | 65 +++------- activation/nipost_test.go | 255 ++++++++++++-------------------------- node/node.go | 2 - 4 files changed, 96 insertions(+), 234 deletions(-) diff --git a/activation/interface.go b/activation/interface.go index da320fe59a..99ecd551bf 100644 --- a/activation/interface.go +++ b/activation/interface.go @@ -67,14 +67,6 @@ type postSetupProvider interface { Config() PostConfig } -// nipostClient is a temporary interface for the NIPostBuilder. -// it is implemented by the PostSetupManager but will eventually merge with the PoSTClient. -type nipostClient interface { - Status() *PostSetupStatus - CommitmentAtx() (types.ATXID, error) - LastOpts() *PostSetupOpts -} - // SmeshingProvider defines the functionality required for the node's Smesher API. type SmeshingProvider interface { Smeshing() bool diff --git a/activation/nipost.go b/activation/nipost.go index 9d661ab81f..2b3f0c12c7 100644 --- a/activation/nipost.go +++ b/activation/nipost.go @@ -83,17 +83,15 @@ func (nb *NIPostBuilder) persistState() { // NIPostBuilder holds the required state and dependencies to create Non-Interactive Proofs of Space-Time (NIPost). type NIPostBuilder struct { - nodeID types.NodeID - dataDir string - nipostClient nipostClient - poetProvers map[string]PoetProvingServiceClient - poetDB poetDbAPI - state *types.NIPostBuilderState - log log.Log - signer *signing.EdSigner - layerClock layerClock - poetCfg PoetConfig - validator nipostValidator + nodeID types.NodeID + dataDir string + poetProvers map[string]PoetProvingServiceClient + poetDB poetDbAPI + state *types.NIPostBuilderState + log log.Log + signer *signing.EdSigner + layerClock layerClock + poetCfg PoetConfig postMux sync.Mutex postClient PostClient @@ -101,12 +99,6 @@ type NIPostBuilder struct { type NIPostBuilderOption func(*NIPostBuilder) -func WithNipostValidator(v nipostValidator) NIPostBuilderOption { - return func(nb *NIPostBuilder) { - nb.validator = v - } -} - // withPoetClients allows to pass in clients directly (for testing purposes). func withPoetClients(clients []PoetProvingServiceClient) NIPostBuilderOption { return func(nb *NIPostBuilder) { @@ -125,7 +117,6 @@ type poetDbAPI interface { // NewNIPostBuilder returns a NIPostBuilder. func NewNIPostBuilder( nodeID types.NodeID, - nipostClient nipostClient, poetDB poetDbAPI, poetServers []string, dataDir string, @@ -145,16 +136,15 @@ func NewNIPostBuilder( } b := &NIPostBuilder{ - nodeID: nodeID, - nipostClient: nipostClient, - poetProvers: poetClients, - poetDB: poetDB, - state: &types.NIPostBuilderState{NIPost: &types.NIPost{}}, - dataDir: dataDir, - log: lg, - signer: signer, - poetCfg: poetCfg, - layerClock: layerClock, + nodeID: nodeID, + poetProvers: poetClients, + poetDB: poetDB, + state: &types.NIPostBuilderState{NIPost: &types.NIPost{}}, + dataDir: dataDir, + log: lg, + signer: signer, + poetCfg: poetCfg, + layerClock: layerClock, } for _, opt := range opts { @@ -259,10 +249,6 @@ func (nb *NIPostBuilder) BuildNIPost(ctx context.Context, challenge *types.NIPos challengeHash := challenge.Hash() nb.loadState(challengeHash) - if s := nb.nipostClient.Status(); s.State != PostSetupStateComplete { - return nil, errors.New("post setup not complete") - } - // Phase 0: Submit challenge to PoET services. if len(nb.state.PoetRequests) == 0 { now := time.Now() @@ -330,21 +316,6 @@ func (nb *NIPostBuilder) BuildNIPost(ctx context.Context, challenge *types.NIPos events.EmitPostFailure() return nil, fmt.Errorf("failed to generate Post: %w", err) } - commitmentAtxId, err := nb.nipostClient.CommitmentAtx() - if err != nil { - return nil, fmt.Errorf("failed to get commitment ATX: %w", err) - } - if err := nb.validator.Post( - postCtx, - nb.nodeID, - commitmentAtxId, - proof, - proofMetadata, - nb.nipostClient.LastOpts().NumUnits, - ); err != nil { - events.EmitInvalidPostProof() - return nil, fmt.Errorf("failed to verify Post: %w", err) - } events.EmitPostComplete(nb.state.PoetProofRef[:]) postGenDuration := time.Since(startTime) nb.log.With().Info("finished post execution", log.Duration("duration", postGenDuration)) diff --git a/activation/nipost_test.go b/activation/nipost_test.go index b9c76fd467..dd9fb3264f 100644 --- a/activation/nipost_test.go +++ b/activation/nipost_test.go @@ -18,9 +18,8 @@ import ( "github.com/spacemeshos/go-spacemesh/signing" ) -func defaultPoetServiceMock(tb testing.TB, id []byte, address string) *MockPoetProvingServiceClient { - tb.Helper() - poetClient := NewMockPoetProvingServiceClient(gomock.NewController(tb)) +func defaultPoetServiceMock(ctrl *gomock.Controller, id []byte, address string) *MockPoetProvingServiceClient { + poetClient := NewMockPoetProvingServiceClient(ctrl) poetClient.EXPECT().Submit(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(&types.PoetRound{}, nil) poetClient.EXPECT().PoetServiceID(gomock.Any()).AnyTimes().Return(types.PoetServiceID{ServiceID: id}, nil) poetClient.EXPECT().PowParams(gomock.Any()).AnyTimes().Return(&PoetPowParams{}, nil) @@ -28,8 +27,8 @@ func defaultPoetServiceMock(tb testing.TB, id []byte, address string) *MockPoetP return poetClient } -func defaultLayerClockMock(tb testing.TB) *MocklayerClock { - mclock := NewMocklayerClock(gomock.NewController(tb)) +func defaultLayerClockMock(ctrl *gomock.Controller) *MocklayerClock { + mclock := NewMocklayerClock(ctrl) mclock.EXPECT().LayerToTime(gomock.Any()).AnyTimes().DoAndReturn( func(got types.LayerID) time.Time { // time.Now() ~= currentLayer @@ -48,31 +47,22 @@ func TestNIPostBuilderWithMocks(t *testing.T) { } ctrl := gomock.NewController(t) - nipostClient := NewMocknipostClient(ctrl) - nipostClient.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) - nipostClient.EXPECT().CommitmentAtx().Return(types.EmptyATXID, nil).AnyTimes() - nipostClient.EXPECT().LastOpts().Return(&PostSetupOpts{}).AnyTimes() - postClient := NewMockPostClient(ctrl) postClient.EXPECT().Proof(gomock.Any(), gomock.Any()).Times(1) - nipostValidator := NewMocknipostValidator(ctrl) - 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 := defaultPoetServiceMock(ctrl, []byte("poet"), "http://localhost:9999") poetProvider.EXPECT().Proof(gomock.Any(), "").Return(&types.PoetProofMessage{ PoetProof: types.PoetProof{}, }, []types.Member{types.Member(challenge.Hash())}, nil) poetDb := NewMockpoetDbAPI(ctrl) poetDb.EXPECT().ValidateAndStore(gomock.Any(), gomock.Any()).Return(nil) - mclock := defaultLayerClockMock(t) + mclock := defaultLayerClockMock(ctrl) sig, err := signing.NewEdSigner() require.NoError(t, err) nb, err := NewNIPostBuilder( - types.NodeID{1}, - nipostClient, + sig.NodeID(), poetDb, []string{}, t.TempDir(), @@ -80,7 +70,6 @@ func TestNIPostBuilderWithMocks(t *testing.T) { sig, PoetConfig{}, mclock, - WithNipostValidator(nipostValidator), withPoetClients([]PoetProvingServiceClient{poetProvider}), ) require.NoError(t, err) @@ -92,33 +81,26 @@ func TestNIPostBuilderWithMocks(t *testing.T) { } func TestPostSetup(t *testing.T) { - r := require.New(t) - postProvider := newTestPostManager(t) - challenge := types.NIPostChallenge{ PublishEpoch: postGenesisEpoch + 2, } - poetProvider := defaultPoetServiceMock(t, []byte("poet"), "http://localhost:9999") + ctrl := gomock.NewController(t) + poetProvider := defaultPoetServiceMock(ctrl, []byte("poet"), "http://localhost:9999") poetProvider.EXPECT().Proof(gomock.Any(), "").Return(&types.PoetProofMessage{ PoetProof: types.PoetProof{}, }, []types.Member{types.Member(challenge.Hash())}, nil) - ctrl := gomock.NewController(t) poetDb := NewMockpoetDbAPI(ctrl) poetDb.EXPECT().ValidateAndStore(gomock.Any(), gomock.Any()).Return(nil) - mclock := defaultLayerClockMock(t) - - nipostValidator := NewMocknipostValidator(ctrl) - nipostValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(1).Return(nil) + mclock := defaultLayerClockMock(ctrl) postClient := NewMockPostClient(ctrl) postClient.EXPECT().Proof(gomock.Any(), gomock.Any()).Times(1) nb, err := NewNIPostBuilder( postProvider.id, - postProvider, poetDb, []string{}, t.TempDir(), @@ -126,33 +108,24 @@ func TestPostSetup(t *testing.T) { postProvider.signer, PoetConfig{}, mclock, - WithNipostValidator(nipostValidator), withPoetClients([]PoetProvingServiceClient{poetProvider}), ) - r.NoError(err) + require.NoError(t, err) nb.Connected(postClient) - r.NoError(postProvider.PrepareInitializer(context.Background(), postProvider.opts)) - r.NoError(postProvider.StartSession(context.Background())) + require.NoError(t, postProvider.PrepareInitializer(context.Background(), postProvider.opts)) + require.NoError(t, postProvider.StartSession(context.Background())) t.Cleanup(func() { assert.NoError(t, postProvider.Reset()) }) nipost, err := nb.BuildNIPost(context.Background(), &challenge) - r.NoError(err) - r.NotNil(nipost) + require.NoError(t, err) + require.NotNil(t, nipost) } func TestNIPostBuilder_BuildNIPost(t *testing.T) { t.Parallel() - req := require.New(t) dir := t.TempDir() - ctrl := gomock.NewController(t) - nipostValidator := NewMocknipostValidator(ctrl) - nipostClient := NewMocknipostClient(ctrl) - nipostClient.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}).AnyTimes() - nipostClient.EXPECT().CommitmentAtx().Return(types.EmptyATXID, nil).AnyTimes() - nipostClient.EXPECT().LastOpts().Return(&PostSetupOpts{}).AnyTimes() - challenge := types.NIPostChallenge{ PublishEpoch: postGenesisEpoch + 2, } @@ -165,7 +138,8 @@ func TestNIPostBuilder_BuildNIPost(t *testing.T) { Sequence: 2, } - poetProver := defaultPoetServiceMock(t, []byte("poet"), "http://localhost:9999") + ctrl := gomock.NewController(t) + poetProver := defaultPoetServiceMock(ctrl, []byte("poet"), "http://localhost:9999") poetProver.EXPECT().Proof(gomock.Any(), "").AnyTimes().Return( &types.PoetProofMessage{ PoetProof: types.PoetProof{}, @@ -178,14 +152,12 @@ func TestNIPostBuilder_BuildNIPost(t *testing.T) { poetDb := NewMockpoetDbAPI(ctrl) poetDb.EXPECT().ValidateAndStore(gomock.Any(), gomock.Any()).Return(nil) - mclock := defaultLayerClockMock(t) + mclock := defaultLayerClockMock(ctrl) sig, err := signing.NewEdSigner() - req.NoError(err) - nodeID := types.NodeID{1} + require.NoError(t, err) nb, err := NewNIPostBuilder( - nodeID, - nipostClient, + sig.NodeID(), poetDb, []string{}, dir, @@ -193,29 +165,24 @@ func TestNIPostBuilder_BuildNIPost(t *testing.T) { sig, PoetConfig{}, mclock, - WithNipostValidator(nipostValidator), withPoetClients([]PoetProvingServiceClient{poetProver}), ) - req.NoError(err) + require.NoError(t, err) postClient := NewMockPostClient(ctrl) postClient.EXPECT().Proof(gomock.Any(), gomock.Any()).Times(1) nb.Connected(postClient) - 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) + require.NoError(t, err) + require.NotNil(t, nipost) poetDb = NewMockpoetDbAPI(ctrl) poetDb.EXPECT().ValidateAndStore(gomock.Any(), gomock.Any()).Return(nil) // fail post exec - sig, err = signing.NewEdSigner() - req.NoError(err) nb, err = NewNIPostBuilder( - nodeID, - nipostClient, + sig.NodeID(), poetDb, []string{}, dir, @@ -225,23 +192,20 @@ func TestNIPostBuilder_BuildNIPost(t *testing.T) { mclock, withPoetClients([]PoetProvingServiceClient{poetProver}), ) - req.NoError(err) + require.NoError(t, err) postClient.EXPECT().Proof(gomock.Any(), gomock.Any()).Return(nil, nil, fmt.Errorf("error")).Times(1) nb.Connected(postClient) // check that proof ref is not called again nipost, err = nb.BuildNIPost(context.Background(), &challenge2) - req.Nil(nipost) - req.Error(err) + require.Nil(t, nipost) + require.Error(t, err) // successful post exec poetDb = NewMockpoetDbAPI(ctrl) - sig, err = signing.NewEdSigner() - req.NoError(err) nb, err = NewNIPostBuilder( - nodeID, - nipostClient, + sig.NodeID(), poetDb, []string{}, dir, @@ -249,32 +213,28 @@ func TestNIPostBuilder_BuildNIPost(t *testing.T) { sig, PoetConfig{}, mclock, - WithNipostValidator(nipostValidator), withPoetClients([]PoetProvingServiceClient{poetProver}), ) - req.NoError(err) + require.NoError(t, err) postClient.EXPECT().Proof(gomock.Any(), gomock.Any()).Times(1) nb.Connected(postClient) - 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) - req.NotNil(nipost) + require.NoError(t, err) + require.NotNil(t, nipost) // test state not loading if other challenge provided poetDb.EXPECT().ValidateAndStore(gomock.Any(), gomock.Any()).Return(nil) postClient.EXPECT().Proof(gomock.Any(), gomock.Any()).Times(1) - 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) + require.NoError(t, err) + require.NotNil(t, nipost) } func TestNIPostBuilder_ManyPoETs_SubmittingChallenge_DeadlineReached(t *testing.T) { t.Parallel() // Arrange - req := require.New(t) challenge := types.NIPostChallenge{ PublishEpoch: postGenesisEpoch + 1, } @@ -282,10 +242,9 @@ func TestNIPostBuilder_ManyPoETs_SubmittingChallenge_DeadlineReached(t *testing. proof := &types.PoetProofMessage{PoetProof: types.PoetProof{}} ctrl := gomock.NewController(t) - nipostValidator := NewMocknipostValidator(ctrl) poetDb := NewMockpoetDbAPI(ctrl) poetDb.EXPECT().ValidateAndStore(gomock.Any(), gomock.Any()).Return(nil) - mclock := defaultLayerClockMock(t) + mclock := defaultLayerClockMock(ctrl) poets := make([]PoetProvingServiceClient, 0, 2) { @@ -312,14 +271,10 @@ func TestNIPostBuilder_ManyPoETs_SubmittingChallenge_DeadlineReached(t *testing. } sig, err := signing.NewEdSigner() - req.NoError(err) + require.NoError(t, err) poetCfg := PoetConfig{ PhaseShift: layerDuration * layersPerEpoch / 2, } - nipostClient := NewMocknipostClient(ctrl) - nipostClient.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) - nipostClient.EXPECT().CommitmentAtx().Return(types.EmptyATXID, nil).AnyTimes() - nipostClient.EXPECT().LastOpts().Return(&PostSetupOpts{}).AnyTimes() postClient := NewMockPostClient(ctrl) postClient.EXPECT().Proof(gomock.Any(), gomock.Any()).DoAndReturn( @@ -329,10 +284,8 @@ func TestNIPostBuilder_ManyPoETs_SubmittingChallenge_DeadlineReached(t *testing. }, 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}, - nipostClient, + sig.NodeID(), poetDb, []string{}, t.TempDir(), @@ -340,26 +293,24 @@ func TestNIPostBuilder_ManyPoETs_SubmittingChallenge_DeadlineReached(t *testing. sig, poetCfg, mclock, - WithNipostValidator(nipostValidator), withPoetClients(poets), ) - req.NoError(err) + require.NoError(t, err) // Act nb.Connected(postClient) nipost, err := nb.BuildNIPost(context.Background(), &challenge) - req.NoError(err) + require.NoError(t, err) // Verify ref, _ := proof.Ref() - req.EqualValues(ref[:], nipost.PostMetadata.Challenge) + require.Equal(t, ref[:], nipost.PostMetadata.Challenge) } func TestNIPostBuilder_ManyPoETs_AllFinished(t *testing.T) { t.Parallel() - // Arrange - req := require.New(t) + // Arrange challenge := types.NIPostChallenge{ PublishEpoch: postGenesisEpoch + 2, } @@ -376,29 +327,24 @@ func TestNIPostBuilder_ManyPoETs_AllFinished(t *testing.T) { } ctrl := gomock.NewController(t) - nipostValidator := NewMocknipostValidator(ctrl) poetDb := NewMockpoetDbAPI(ctrl) poetDb.EXPECT().ValidateAndStore(gomock.Any(), gomock.Any()).Times(2).Return(nil) - mclock := defaultLayerClockMock(t) + mclock := defaultLayerClockMock(ctrl) poets := make([]PoetProvingServiceClient, 0, 2) { - poet := defaultPoetServiceMock(t, []byte("poet0"), "http://localhost:9999") + poet := defaultPoetServiceMock(ctrl, []byte("poet0"), "http://localhost:9999") poet.EXPECT().Proof(gomock.Any(), "").Return(proofWorse, []types.Member{types.Member(challenge.Hash())}, nil) poets = append(poets, poet) } { - poet := defaultPoetServiceMock(t, []byte("poet1"), "http://localhost:9998") + poet := defaultPoetServiceMock(ctrl, []byte("poet1"), "http://localhost:9998") poet.EXPECT().Proof(gomock.Any(), "").Return(proofBetter, []types.Member{types.Member(challenge.Hash())}, nil) poets = append(poets, poet) } sig, err := signing.NewEdSigner() - req.NoError(err) - nipostClient := NewMocknipostClient(ctrl) - nipostClient.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) - nipostClient.EXPECT().CommitmentAtx().Return(types.EmptyATXID, nil).AnyTimes() - nipostClient.EXPECT().LastOpts().Return(&PostSetupOpts{}).AnyTimes() + require.NoError(t, err) postClient := NewMockPostClient(ctrl) postClient.EXPECT().Proof(gomock.Any(), gomock.Any()).DoAndReturn( @@ -409,10 +355,8 @@ func TestNIPostBuilder_ManyPoETs_AllFinished(t *testing.T) { }, ) - 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}, - nipostClient, + sig.NodeID(), poetDb, []string{}, t.TempDir(), @@ -420,19 +364,18 @@ func TestNIPostBuilder_ManyPoETs_AllFinished(t *testing.T) { sig, PoetConfig{}, mclock, - WithNipostValidator(nipostValidator), withPoetClients(poets), ) - req.NoError(err) + require.NoError(t, err) nb.Connected(postClient) // Act nipost, err := nb.BuildNIPost(context.Background(), &challenge) - req.NoError(err) + require.NoError(t, err) // Verify ref, _ := proofBetter.Ref() - req.EqualValues(ref[:], nipost.PostMetadata.Challenge) + require.Equal(t, ref[:], nipost.PostMetadata.Challenge) } func TestNIPSTBuilder_PoetUnstable(t *testing.T) { @@ -446,22 +389,18 @@ func TestNIPSTBuilder_PoetUnstable(t *testing.T) { sig, err := signing.NewEdSigner() require.NoError(t, err) - nodeID := types.NodeID{1} t.Run("PoetServiceID fails", func(t *testing.T) { t.Parallel() ctrl := gomock.NewController(t) poetDb := NewMockpoetDbAPI(ctrl) - mclock := defaultLayerClockMock(t) - nipostClient := NewMocknipostClient(ctrl) - nipostClient.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) + mclock := defaultLayerClockMock(ctrl) poetProver := NewMockPoetProvingServiceClient(ctrl) poetProver.EXPECT().PoetServiceID(gomock.Any()).AnyTimes().Return(types.PoetServiceID{}, errors.New("test")) poetProver.EXPECT().Address().Return("http://localhost:9999") nb, err := NewNIPostBuilder( - nodeID, - nipostClient, + sig.NodeID(), poetDb, []string{}, t.TempDir(), @@ -480,9 +419,7 @@ func TestNIPSTBuilder_PoetUnstable(t *testing.T) { t.Parallel() ctrl := gomock.NewController(t) poetDb := NewMockpoetDbAPI(ctrl) - mclock := defaultLayerClockMock(t) - nipostClient := NewMocknipostClient(ctrl) - nipostClient.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) + mclock := defaultLayerClockMock(ctrl) poetProver := NewMockPoetProvingServiceClient(ctrl) poetProver.EXPECT().PoetServiceID(gomock.Any()).AnyTimes().Return(types.PoetServiceID{ServiceID: []byte{}}, nil) poetProver.EXPECT().Submit(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, errors.New("test")) @@ -490,8 +427,7 @@ func TestNIPSTBuilder_PoetUnstable(t *testing.T) { poetProver.EXPECT().Address().Return("http://localhost:9999") nb, err := NewNIPostBuilder( - nodeID, - nipostClient, + sig.NodeID(), poetDb, []string{}, t.TempDir(), @@ -511,9 +447,7 @@ func TestNIPSTBuilder_PoetUnstable(t *testing.T) { t.Parallel() ctrl := gomock.NewController(t) poetDb := NewMockpoetDbAPI(ctrl) - mclock := defaultLayerClockMock(t) - nipostClient := NewMocknipostClient(ctrl) - nipostClient.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) + mclock := defaultLayerClockMock(ctrl) poetProver := NewMockPoetProvingServiceClient(ctrl) poetProver.EXPECT().PoetServiceID(gomock.Any()).AnyTimes().Return(types.PoetServiceID{ServiceID: []byte{}}, nil) poetProver.EXPECT().Submit(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn( @@ -526,8 +460,7 @@ func TestNIPSTBuilder_PoetUnstable(t *testing.T) { poetProver.EXPECT().Address().Return("http://localhost:9999") nb, err := NewNIPostBuilder( - nodeID, - nipostClient, + sig.NodeID(), poetDb, []string{}, t.TempDir(), @@ -546,15 +479,12 @@ func TestNIPSTBuilder_PoetUnstable(t *testing.T) { t.Parallel() ctrl := gomock.NewController(t) poetDb := NewMockpoetDbAPI(ctrl) - mclock := defaultLayerClockMock(t) - nipostClient := NewMocknipostClient(ctrl) - nipostClient.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) - poetProver := defaultPoetServiceMock(t, []byte("poet"), "http://localhost:9999") + mclock := defaultLayerClockMock(ctrl) + poetProver := defaultPoetServiceMock(ctrl, []byte("poet"), "http://localhost:9999") poetProver.EXPECT().Proof(gomock.Any(), "").Return(nil, nil, errors.New("failed")) nb, err := NewNIPostBuilder( - nodeID, - nipostClient, + sig.NodeID(), poetDb, []string{}, t.TempDir(), @@ -574,15 +504,12 @@ func TestNIPSTBuilder_PoetUnstable(t *testing.T) { ctrl := gomock.NewController(t) poetDb := NewMockpoetDbAPI(ctrl) poetDb.EXPECT().ValidateAndStore(gomock.Any(), gomock.Any()).Return(nil) - mclock := defaultLayerClockMock(t) - nipostClient := NewMocknipostClient(ctrl) - nipostClient.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) - poetProver := defaultPoetServiceMock(t, []byte("poet"), "http://localhost:9999") + mclock := defaultLayerClockMock(ctrl) + poetProver := defaultPoetServiceMock(ctrl, []byte("poet"), "http://localhost:9999") poetProver.EXPECT().Proof(gomock.Any(), "").Return(&types.PoetProofMessage{PoetProof: types.PoetProof{}}, []types.Member{}, nil) nb, err := NewNIPostBuilder( - nodeID, - nipostClient, + sig.NodeID(), poetDb, []string{}, t.TempDir(), @@ -617,16 +544,14 @@ func TestNIPoSTBuilder_StaleChallenge(t *testing.T) { mclock := NewMocklayerClock(ctrl) poetProver := NewMockPoetProvingServiceClient(ctrl) poetProver.EXPECT().Address().Return("http://localhost:9999") - nipostClient := NewMocknipostClient(ctrl) - nipostClient.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) mclock.EXPECT().LayerToTime(gomock.Any()).DoAndReturn( func(got types.LayerID) time.Time { return genesis.Add(layerDuration * time.Duration(got)) - }).AnyTimes() + }, + ).AnyTimes() nb, err := NewNIPostBuilder( - types.NodeID{1}, - nipostClient, + sig.NodeID(), poetDb, []string{}, t.TempDir(), @@ -650,8 +575,6 @@ func TestNIPoSTBuilder_StaleChallenge(t *testing.T) { mclock := NewMocklayerClock(ctrl) poetProver := NewMockPoetProvingServiceClient(ctrl) poetProver.EXPECT().Address().Return("http://localhost:9999") - nipostClient := NewMocknipostClient(ctrl) - nipostClient.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) mclock.EXPECT().LayerToTime(gomock.Any()).DoAndReturn( func(got types.LayerID) time.Time { return genesis.Add(layerDuration * time.Duration(got)) @@ -659,8 +582,7 @@ func TestNIPoSTBuilder_StaleChallenge(t *testing.T) { dir := t.TempDir() nb, err := NewNIPostBuilder( - types.NodeID{1}, - nipostClient, + sig.NodeID(), poetDb, []string{}, dir, @@ -689,8 +611,6 @@ func TestNIPoSTBuilder_StaleChallenge(t *testing.T) { mclock := NewMocklayerClock(ctrl) poetProver := NewMockPoetProvingServiceClient(ctrl) poetProver.EXPECT().Address().Return("http://localhost:9999") - nipostClient := NewMocknipostClient(ctrl) - nipostClient.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) mclock.EXPECT().LayerToTime(gomock.Any()).DoAndReturn( func(got types.LayerID) time.Time { return genesis.Add(layerDuration * time.Duration(got)) @@ -698,8 +618,7 @@ func TestNIPoSTBuilder_StaleChallenge(t *testing.T) { dir := t.TempDir() nb, err := NewNIPostBuilder( - types.NodeID{1}, - nipostClient, + sig.NodeID(), poetDb, []string{}, dir, @@ -730,8 +649,8 @@ func TestNIPoSTBuilder_StaleChallenge(t *testing.T) { // a challenge has been submitted to poet. func TestNIPoSTBuilder_Continues_After_Interrupted(t *testing.T) { t.Parallel() + // Arrange - req := require.New(t) challenge := types.NIPostChallenge{ PublishEpoch: postGenesisEpoch + 1, } @@ -745,7 +664,7 @@ func TestNIPoSTBuilder_Continues_After_Interrupted(t *testing.T) { ctrl := gomock.NewController(t) poetDb := NewMockpoetDbAPI(ctrl) poetDb.EXPECT().ValidateAndStore(gomock.Any(), gomock.Any()).Return(nil) - mclock := defaultLayerClockMock(t) + mclock := defaultLayerClockMock(ctrl) buildCtx, cancel := context.WithCancel(context.Background()) @@ -762,14 +681,10 @@ func TestNIPoSTBuilder_Continues_After_Interrupted(t *testing.T) { poet.EXPECT().Address().Return("http://localhost:9999") sig, err := signing.NewEdSigner() - req.NoError(err) + require.NoError(t, err) poetCfg := PoetConfig{ PhaseShift: layerDuration * layersPerEpoch / 2, } - nipostClient := NewMocknipostClient(ctrl) - nipostClient.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}).Times(2) - nipostClient.EXPECT().CommitmentAtx().Return(types.EmptyATXID, nil).AnyTimes() - nipostClient.EXPECT().LastOpts().Return(&PostSetupOpts{}).AnyTimes() postClient := NewMockPostClient(ctrl) postClient.EXPECT().Proof(gomock.Any(), gomock.Any()).DoAndReturn( @@ -780,11 +695,8 @@ 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()).Times(1).Return(nil) nb, err := NewNIPostBuilder( - types.NodeID{1}, - nipostClient, + sig.NodeID(), poetDb, []string{}, t.TempDir(), @@ -792,26 +704,25 @@ func TestNIPoSTBuilder_Continues_After_Interrupted(t *testing.T) { sig, poetCfg, mclock, - WithNipostValidator(nipostValidator), withPoetClients([]PoetProvingServiceClient{poet}), ) - req.NoError(err) + require.NoError(t, err) nb.Connected(postClient) // Act nipost, err := nb.BuildNIPost(buildCtx, &challenge) - req.ErrorIs(err, context.Canceled) - req.Nil(nipost) + require.ErrorIs(t, err, context.Canceled) + require.Nil(t, nipost) // allow to submit in the second try poet.EXPECT().Submit(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(&types.PoetRound{}, nil) nipost, err = nb.BuildNIPost(context.Background(), &challenge) - req.NoError(err) + require.NoError(t, err) // Verify ref, _ := proof.Ref() - req.EqualValues(ref[:], nipost.PostMetadata.Challenge) + require.Equal(t, ref[:], nipost.PostMetadata.Challenge) } func TestConstructingMerkleProof(t *testing.T) { @@ -881,14 +792,6 @@ func TestNIPostBuilder_Mainnet_Poet_Workaround(t *testing.T) { } ctrl := gomock.NewController(t) - nipostClient := NewMocknipostClient(ctrl) - nipostClient.EXPECT().Status().Return(&PostSetupStatus{State: PostSetupStateComplete}) - nipostClient.EXPECT().CommitmentAtx().Return(types.EmptyATXID, nil).AnyTimes() - nipostClient.EXPECT().LastOpts().Return(&PostSetupOpts{}).AnyTimes() - - 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) @@ -940,8 +843,7 @@ func TestNIPostBuilder_Mainnet_Poet_Workaround(t *testing.T) { PhaseShift: layerDuration * layersPerEpoch / 2, } nb, err := NewNIPostBuilder( - types.NodeID{1}, - nipostClient, + sig.NodeID(), poetDb, []string{}, t.TempDir(), @@ -949,7 +851,6 @@ func TestNIPostBuilder_Mainnet_Poet_Workaround(t *testing.T) { sig, poetCfg, mclock, - WithNipostValidator(nipostValidator), withPoetClients(poets), ) require.NoError(t, err) @@ -974,9 +875,9 @@ func TestRandomDurationInRange(t *testing.T) { t.Parallel() test := func(min, max time.Duration) { for i := 0; i < 100; i++ { - waittime := randomDurationInRange(min, max) - require.LessOrEqual(t, waittime, max) - require.GreaterOrEqual(t, waittime, min) + waitTime := randomDurationInRange(min, max) + require.LessOrEqual(t, waitTime, max) + require.GreaterOrEqual(t, waitTime, min) } } t.Run("min = 0", func(t *testing.T) { diff --git a/node/node.go b/node/node.go index 9b2fa09c7a..222d05e92d 100644 --- a/node/node.go +++ b/node/node.go @@ -843,7 +843,6 @@ func (app *App) initServices(ctx context.Context) error { nipostBuilder, err := activation.NewNIPostBuilder( app.edSgn.NodeID(), - postSetupMgr, poetDb, app.Config.PoETServers, app.Config.SMESHING.Opts.DataDir, @@ -851,7 +850,6 @@ func (app *App) initServices(ctx context.Context) error { app.edSgn, app.Config.POET, app.clock, - activation.WithNipostValidator(app.validator), ) if err != nil { app.log.Panic("failed to create nipost builder: %v", err) From c5d384fc1e6ca02e20c0355b879d1c437c94127c Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Mon, 9 Oct 2023 16:13:51 +0000 Subject: [PATCH 25/40] Fix e2e tests --- activation/e2e/nipost_test.go | 15 +++------------ activation/e2e/validation_test.go | 4 +--- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/activation/e2e/nipost_test.go b/activation/e2e/nipost_test.go index e47606ea65..16ec16758b 100644 --- a/activation/e2e/nipost_test.go +++ b/activation/e2e/nipost_test.go @@ -186,11 +186,9 @@ func TestNIPostBuilderWithClients(t *testing.T) { t.Cleanup(func() { assert.NoError(t, verifier.Close()) }) poetDb := activation.NewPoetDb(sql.InMemory(), log.NewFromLog(logger).Named("poetDb")) - v := activation.NewValidator(poetDb, mgr.Config(), mgr.LastOpts().Scrypt, verifier) nb, err := activation.NewNIPostBuilder( sig.NodeID(), - mgr, poetDb, []string{poetProver.RestURL().String()}, t.TempDir(), @@ -198,7 +196,6 @@ func TestNIPostBuilderWithClients(t *testing.T) { sig, poetCfg, mclock, - activation.WithNipostValidator(v), ) require.NoError(t, err) @@ -227,6 +224,8 @@ func TestNIPostBuilderWithClients(t *testing.T) { nipost, err := nb.BuildNIPost(context.Background(), &challenge) require.NoError(t, err) + + v := activation.NewValidator(poetDb, mgr.Config(), mgr.LastOpts().Scrypt, verifier) _, err = v.NIPost( context.Background(), sig.NodeID(), @@ -246,10 +245,7 @@ func TestNIPostBuilder_Close(t *testing.T) { logger := zaptest.NewLogger(t) - nipostClient := activation.NewMocknipostClient(ctrl) - nipostClient.EXPECT().Status().Return(&activation.PostSetupStatus{State: activation.PostSetupStateComplete}) poetProver := spawnPoet(t, WithGenesis(time.Now()), WithEpochDuration(time.Second)) - poetDb := activation.NewMockpoetDbAPI(ctrl) mclock := activation.NewMocklayerClock(ctrl) @@ -263,7 +259,6 @@ func TestNIPostBuilder_Close(t *testing.T) { nb, err := activation.NewNIPostBuilder( sig.NodeID(), - nipostClient, poetDb, []string{poetProver.RestURL().String()}, t.TempDir(), @@ -322,12 +317,9 @@ func TestNewNIPostBuilderNotInitialized(t *testing.T) { ) poetDb := activation.NewPoetDb(sql.InMemory(), log.NewFromLog(logger).Named("poetDb")) - nipostValidator := activation.NewMocknipostValidator(ctrl) - nipostValidator.EXPECT().Post(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(1).Return(nil) nb, err := activation.NewNIPostBuilder( sig.NodeID(), - mgr, poetDb, []string{poetProver.RestURL().String()}, t.TempDir(), @@ -335,7 +327,6 @@ func TestNewNIPostBuilderNotInitialized(t *testing.T) { sig, poetCfg, mclock, - activation.WithNipostValidator(nipostValidator), ) require.NoError(t, err) @@ -364,7 +355,7 @@ func TestNewNIPostBuilderNotInitialized(t *testing.T) { } nipost, err := nb.BuildNIPost(context.Background(), &challenge) - require.EqualError(t, err, "post setup not complete") + require.ErrorContains(t, err, "failed to generate Post: error generating proof") require.Nil(t, nipost) opts := activation.DefaultPostSetupOpts() diff --git a/activation/e2e/validation_test.go b/activation/e2e/validation_test.go index 4bdfa5f16b..e32496cb73 100644 --- a/activation/e2e/validation_test.go +++ b/activation/e2e/validation_test.go @@ -73,11 +73,9 @@ func TestValidator_Validate(t *testing.T) { t.Cleanup(func() { assert.NoError(t, verifier.Close()) }) poetDb := activation.NewPoetDb(sql.InMemory(), log.NewFromLog(logger).Named("poetDb")) - v := activation.NewValidator(poetDb, mgr.Config(), mgr.LastOpts().Scrypt, verifier) nb, err := activation.NewNIPostBuilder( sig.NodeID(), - mgr, poetDb, []string{poetProver.RestURL().String()}, t.TempDir(), @@ -85,7 +83,6 @@ func TestValidator_Validate(t *testing.T) { sig, poetCfg, mclock, - activation.WithNipostValidator(v), ) require.NoError(t, err) @@ -116,6 +113,7 @@ func TestValidator_Validate(t *testing.T) { nipost, err := nb.BuildNIPost(context.Background(), &challenge) require.NoError(t, err) + v := activation.NewValidator(poetDb, mgr.Config(), mgr.LastOpts().Scrypt, verifier) _, err = v.NIPost(context.Background(), sig.NodeID(), goldenATX, nipost, challengeHash, mgr.LastOpts().NumUnits) require.NoError(t, err) From e6eeea2c280eec0f7d1b5ba83564170ed8b176ee Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Mon, 9 Oct 2023 16:19:36 +0000 Subject: [PATCH 26/40] Check challenge in response to match request challenge --- api/grpcserver/post_client.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/api/grpcserver/post_client.go b/api/grpcserver/post_client.go index f95584d8e2..2c6781d25c 100644 --- a/api/grpcserver/post_client.go +++ b/api/grpcserver/post_client.go @@ -1,6 +1,7 @@ package grpcserver import ( + "bytes" "context" "fmt" "time" @@ -74,8 +75,12 @@ func (pc *postClient) Proof(ctx context.Context, challenge []byte) (*types.Post, } } - proof := proofResp.GetProof() meta := proofResp.GetMetadata() + if !bytes.Equal(meta.GetChallenge(), challenge) { + return nil, nil, fmt.Errorf("unexpected challenge: %x", meta.GetChallenge()) + } + + proof := proofResp.GetProof() return &types.Post{ Nonce: proof.GetNonce(), Indices: proof.GetIndices(), From 2e02fea260b0ed5a5a76f7f5356b106db3936b89 Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Mon, 9 Oct 2023 16:20:31 +0000 Subject: [PATCH 27/40] Remove deprecated functionality --- activation/post.go | 32 ----------------------- activation/post_test.go | 48 ---------------------------------- config/presets/presets_test.go | 46 -------------------------------- 3 files changed, 126 deletions(-) delete mode 100644 config/presets/presets_test.go diff --git a/activation/post.go b/activation/post.go index ecf04424e5..911905d24d 100644 --- a/activation/post.go +++ b/activation/post.go @@ -10,7 +10,6 @@ import ( "github.com/spacemeshos/post/config" "github.com/spacemeshos/post/initialization" - "github.com/spacemeshos/post/proving" "go.uber.org/zap" "github.com/spacemeshos/go-spacemesh/common/types" @@ -496,37 +495,6 @@ func (mgr *PostSetupManager) Reset() error { return nil } -// Deprecated: GenerateProof generates a new Post. -func (mgr *PostSetupManager) GenerateProof(ctx context.Context, challenge []byte, options ...proving.OptionFunc) (*types.Post, *types.PostMetadata, error) { - mgr.mu.Lock() - - if mgr.state != PostSetupStateComplete { - mgr.mu.Unlock() - return nil, nil, errNotComplete - } - mgr.mu.Unlock() - - opts := []proving.OptionFunc{ - proving.WithDataSource(mgr.cfg.ToConfig(), mgr.id.Bytes(), mgr.commitmentAtxId.Bytes(), mgr.lastOpts.DataDir), - proving.WithNonces(mgr.provingOpts.Nonces), - proving.WithThreads(mgr.provingOpts.Threads), - proving.WithPowFlags(mgr.provingOpts.Flags), - } - opts = append(opts, options...) - - proof, proofMetadata, err := proving.Generate(ctx, challenge, mgr.cfg.ToConfig(), mgr.logger, opts...) - if err != nil { - return nil, nil, fmt.Errorf("generate proof: %w", err) - } - - p := (*types.Post)(proof) - m := &types.PostMetadata{ - Challenge: proofMetadata.Challenge, - LabelsPerUnit: proofMetadata.LabelsPerUnit, - } - return p, m, nil -} - // VRFNonce returns the VRF nonce found during initialization. func (mgr *PostSetupManager) VRFNonce() (*types.VRFPostIndex, error) { mgr.mu.Lock() diff --git a/activation/post_test.go b/activation/post_test.go index 073a835d88..13ee983e8c 100644 --- a/activation/post_test.go +++ b/activation/post_test.go @@ -10,7 +10,6 @@ import ( "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/zap/zaptest" "golang.org/x/sync/errgroup" @@ -216,53 +215,6 @@ func TestPostSetupManager_InitialStatus(t *testing.T) { req.Zero(status.NumLabelsWritten) } -func TestPostSetupManager_GenerateProof(t *testing.T) { - req := require.New(t) - ch := make([]byte, 32) - - mgr := newTestPostManager(t) - - // Attempt to generate proof. - _, _, err := mgr.GenerateProof(context.Background(), ch) - req.EqualError(err, errNotComplete.Error()) - - // Create data. - req.NoError(mgr.PrepareInitializer(context.Background(), mgr.opts)) - req.NoError(mgr.StartSession(context.Background())) - - // Generate proof. - p, m, err := mgr.GenerateProof(context.Background(), ch) - req.NoError(err) - - // Verify the proof - verifier, err := verifying.NewProofVerifier() - req.NoError(err) - defer verifier.Close() - err = verifier.Verify(&shared.Proof{ - Nonce: p.Nonce, - Indices: p.Indices, - Pow: p.Pow, - }, &shared.ProofMetadata{ - NodeId: mgr.id.Bytes(), - CommitmentAtxId: mgr.goldenATXID.Bytes(), - Challenge: ch, - NumUnits: mgr.opts.NumUnits, - LabelsPerUnit: m.LabelsPerUnit, - }, - config.DefaultConfig(), - logtest.New(t).WithName("verifying").Zap(), - verifying.WithLabelScryptParams(mgr.opts.Scrypt), - ) - req.NoError(err) - - // Re-instantiate `PostSetupManager`. - mgr = newTestPostManager(t) - - // Attempt to generate proof. - _, _, err = mgr.GenerateProof(context.Background(), ch) - req.ErrorIs(err, errNotComplete) -} - func TestPostSetupManager_VRFNonce(t *testing.T) { req := require.New(t) diff --git a/config/presets/presets_test.go b/config/presets/presets_test.go deleted file mode 100644 index 60e5d822d0..0000000000 --- a/config/presets/presets_test.go +++ /dev/null @@ -1,46 +0,0 @@ -package presets - -import ( - "context" - "testing" - - "github.com/stretchr/testify/require" - "go.uber.org/zap/zaptest" - - "github.com/spacemeshos/go-spacemesh/activation" - "github.com/spacemeshos/go-spacemesh/common/types" - "github.com/spacemeshos/go-spacemesh/config" - "github.com/spacemeshos/go-spacemesh/datastore" - "github.com/spacemeshos/go-spacemesh/log/logtest" - "github.com/spacemeshos/go-spacemesh/sql" -) - -func TestCanGeneratePOST(t *testing.T) { - runTest := func(params config.Config) func(t *testing.T) { - return func(t *testing.T) { - req := require.New(t) - ch := make([]byte, 32) - cdb := datastore.NewCachedDB(sql.InMemory(), logtest.New(t)) - goldenATXID := types.ATXID{2, 3, 4} - - opts := params.SMESHING.Opts - opts.DataDir = t.TempDir() - - mgr, err := activation.NewPostSetupManager( - types.EmptyNodeID, - params.POST, - zaptest.NewLogger(t).Named("post"), - cdb, goldenATXID, - params.SMESHING.ProvingOpts, - ) - req.NoError(err) - req.NoError(mgr.PrepareInitializer(context.Background(), opts)) - req.NoError(mgr.StartSession(context.Background())) - - _, _, err = mgr.GenerateProof(context.Background(), ch) - req.NoError(err) - } - } - - t.Run("fastnet", runTest(fastnet())) -} From 9d0f1fd89ba1a7a02c8e3628eb80562c37135b67 Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Mon, 9 Oct 2023 17:13:53 +0000 Subject: [PATCH 28/40] make generate --- activation/mocks.go | 138 -------------------------------------------- 1 file changed, 138 deletions(-) diff --git a/activation/mocks.go b/activation/mocks.go index 482f145fa9..ef9b45107f 100644 --- a/activation/mocks.go +++ b/activation/mocks.go @@ -1197,144 +1197,6 @@ func (c *postSetupProviderVRFNonceCall) DoAndReturn(f func() (*types.VRFPostInde return c } -// MocknipostClient is a mock of nipostClient interface. -type MocknipostClient struct { - ctrl *gomock.Controller - recorder *MocknipostClientMockRecorder -} - -// MocknipostClientMockRecorder is the mock recorder for MocknipostClient. -type MocknipostClientMockRecorder struct { - mock *MocknipostClient -} - -// NewMocknipostClient creates a new mock instance. -func NewMocknipostClient(ctrl *gomock.Controller) *MocknipostClient { - mock := &MocknipostClient{ctrl: ctrl} - mock.recorder = &MocknipostClientMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MocknipostClient) EXPECT() *MocknipostClientMockRecorder { - return m.recorder -} - -// CommitmentAtx mocks base method. -func (m *MocknipostClient) CommitmentAtx() (types.ATXID, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CommitmentAtx") - ret0, _ := ret[0].(types.ATXID) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// CommitmentAtx indicates an expected call of CommitmentAtx. -func (mr *MocknipostClientMockRecorder) CommitmentAtx() *nipostClientCommitmentAtxCall { - mr.mock.ctrl.T.Helper() - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CommitmentAtx", reflect.TypeOf((*MocknipostClient)(nil).CommitmentAtx)) - return &nipostClientCommitmentAtxCall{Call: call} -} - -// nipostClientCommitmentAtxCall wrap *gomock.Call -type nipostClientCommitmentAtxCall struct { - *gomock.Call -} - -// Return rewrite *gomock.Call.Return -func (c *nipostClientCommitmentAtxCall) Return(arg0 types.ATXID, arg1 error) *nipostClientCommitmentAtxCall { - c.Call = c.Call.Return(arg0, arg1) - return c -} - -// Do rewrite *gomock.Call.Do -func (c *nipostClientCommitmentAtxCall) Do(f func() (types.ATXID, error)) *nipostClientCommitmentAtxCall { - c.Call = c.Call.Do(f) - return c -} - -// DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *nipostClientCommitmentAtxCall) DoAndReturn(f func() (types.ATXID, error)) *nipostClientCommitmentAtxCall { - c.Call = c.Call.DoAndReturn(f) - return c -} - -// LastOpts mocks base method. -func (m *MocknipostClient) LastOpts() *PostSetupOpts { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "LastOpts") - ret0, _ := ret[0].(*PostSetupOpts) - return ret0 -} - -// LastOpts indicates an expected call of LastOpts. -func (mr *MocknipostClientMockRecorder) LastOpts() *nipostClientLastOptsCall { - mr.mock.ctrl.T.Helper() - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LastOpts", reflect.TypeOf((*MocknipostClient)(nil).LastOpts)) - return &nipostClientLastOptsCall{Call: call} -} - -// nipostClientLastOptsCall wrap *gomock.Call -type nipostClientLastOptsCall struct { - *gomock.Call -} - -// Return rewrite *gomock.Call.Return -func (c *nipostClientLastOptsCall) Return(arg0 *PostSetupOpts) *nipostClientLastOptsCall { - c.Call = c.Call.Return(arg0) - return c -} - -// Do rewrite *gomock.Call.Do -func (c *nipostClientLastOptsCall) Do(f func() *PostSetupOpts) *nipostClientLastOptsCall { - c.Call = c.Call.Do(f) - return c -} - -// DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *nipostClientLastOptsCall) DoAndReturn(f func() *PostSetupOpts) *nipostClientLastOptsCall { - c.Call = c.Call.DoAndReturn(f) - return c -} - -// Status mocks base method. -func (m *MocknipostClient) Status() *PostSetupStatus { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Status") - ret0, _ := ret[0].(*PostSetupStatus) - return ret0 -} - -// Status indicates an expected call of Status. -func (mr *MocknipostClientMockRecorder) Status() *nipostClientStatusCall { - mr.mock.ctrl.T.Helper() - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Status", reflect.TypeOf((*MocknipostClient)(nil).Status)) - return &nipostClientStatusCall{Call: call} -} - -// nipostClientStatusCall wrap *gomock.Call -type nipostClientStatusCall struct { - *gomock.Call -} - -// Return rewrite *gomock.Call.Return -func (c *nipostClientStatusCall) Return(arg0 *PostSetupStatus) *nipostClientStatusCall { - c.Call = c.Call.Return(arg0) - return c -} - -// Do rewrite *gomock.Call.Do -func (c *nipostClientStatusCall) Do(f func() *PostSetupStatus) *nipostClientStatusCall { - c.Call = c.Call.Do(f) - return c -} - -// DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *nipostClientStatusCall) DoAndReturn(f func() *PostSetupStatus) *nipostClientStatusCall { - c.Call = c.Call.DoAndReturn(f) - return c -} - // MockSmeshingProvider is a mock of SmeshingProvider interface. type MockSmeshingProvider struct { ctrl *gomock.Controller From 157978534748d8be600960e7586126b986dc084e Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Mon, 9 Oct 2023 17:44:21 +0000 Subject: [PATCH 29/40] Remove proving options from PostSetup Manager --- activation/e2e/nipost_test.go | 11 ++--------- activation/e2e/validation_test.go | 6 +----- activation/post.go | 12 +++++------- activation/post_test.go | 4 +--- api/grpcserver/post_service_test.go | 5 +---- node/node.go | 1 - 6 files changed, 10 insertions(+), 29 deletions(-) diff --git a/activation/e2e/nipost_test.go b/activation/e2e/nipost_test.go index 16ec16758b..2f7405f6bf 100644 --- a/activation/e2e/nipost_test.go +++ b/activation/e2e/nipost_test.go @@ -11,7 +11,6 @@ import ( "time" "github.com/spacemeshos/poet/logging" - "github.com/spacemeshos/post/config" "github.com/spacemeshos/post/initialization" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -148,10 +147,7 @@ func TestNIPostBuilderWithClients(t *testing.T) { cfg := activation.DefaultPostConfig() cdb := datastore.NewCachedDB(sql.InMemory(), log.NewFromLog(logger)) - provingOpts := activation.DefaultPostProvingOpts() - provingOpts.Flags = config.RecommendedPowFlags() - - mgr, err := activation.NewPostSetupManager(sig.NodeID(), cfg, logger, cdb, goldenATX, provingOpts) + mgr, err := activation.NewPostSetupManager(sig.NodeID(), cfg, logger, cdb, goldenATX) require.NoError(t, err) postDir := t.TempDir() @@ -290,10 +286,7 @@ func TestNewNIPostBuilderNotInitialized(t *testing.T) { cfg := activation.DefaultPostConfig() cdb := datastore.NewCachedDB(sql.InMemory(), log.NewFromLog(logger)) - provingOpts := activation.DefaultPostProvingOpts() - provingOpts.Flags = config.RecommendedPowFlags() - - mgr, err := activation.NewPostSetupManager(sig.NodeID(), cfg, logger, cdb, goldenATX, provingOpts) + mgr, err := activation.NewPostSetupManager(sig.NodeID(), cfg, logger, cdb, goldenATX) require.NoError(t, err) epoch := layersPerEpoch * layerDuration diff --git a/activation/e2e/validation_test.go b/activation/e2e/validation_test.go index e32496cb73..de6859f9e9 100644 --- a/activation/e2e/validation_test.go +++ b/activation/e2e/validation_test.go @@ -6,7 +6,6 @@ import ( "testing" "time" - "github.com/spacemeshos/post/config" "github.com/spacemeshos/post/initialization" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -35,10 +34,7 @@ func TestValidator_Validate(t *testing.T) { cfg := activation.DefaultPostConfig() cdb := datastore.NewCachedDB(sql.InMemory(), log.NewFromLog(logger)) - provingOpts := activation.DefaultPostProvingOpts() - provingOpts.Flags = config.RecommendedPowFlags() - - mgr, err := activation.NewPostSetupManager(sig.NodeID(), cfg, logger, cdb, goldenATX, provingOpts) + mgr, err := activation.NewPostSetupManager(sig.NodeID(), cfg, logger, cdb, goldenATX) require.NoError(t, err) postDir := t.TempDir() diff --git a/activation/post.go b/activation/post.go index 911905d24d..5638770465 100644 --- a/activation/post.go +++ b/activation/post.go @@ -217,15 +217,14 @@ type PostSetupManager struct { db *datastore.CachedDB goldenATXID types.ATXID - mu sync.Mutex // mu protects setting the values below. - lastOpts *PostSetupOpts // the last options used to initiate a Post setup session. - state PostSetupState // state is the current state of the Post setup. - init *initialization.Initializer // init is the current initializer instance. - provingOpts PostProvingOpts + mu sync.Mutex // mu protects setting the values below. + lastOpts *PostSetupOpts // the last options used to initiate a Post setup session. + state PostSetupState // state is the current state of the Post setup. + init *initialization.Initializer // init is the current initializer instance. } // NewPostSetupManager creates a new instance of PostSetupManager. -func NewPostSetupManager(id types.NodeID, cfg PostConfig, logger *zap.Logger, db *datastore.CachedDB, goldenATXID types.ATXID, provingOpts PostProvingOpts) (*PostSetupManager, error) { +func NewPostSetupManager(id types.NodeID, cfg PostConfig, logger *zap.Logger, db *datastore.CachedDB, goldenATXID types.ATXID) (*PostSetupManager, error) { mgr := &PostSetupManager{ id: id, cfg: cfg, @@ -233,7 +232,6 @@ func NewPostSetupManager(id types.NodeID, cfg PostConfig, logger *zap.Logger, db db: db, goldenATXID: goldenATXID, state: PostSetupStateNotStarted, - provingOpts: provingOpts, } return mgr, nil diff --git a/activation/post_test.go b/activation/post_test.go index 13ee983e8c..569d026212 100644 --- a/activation/post_test.go +++ b/activation/post_test.go @@ -418,9 +418,7 @@ func newTestPostManager(tb testing.TB) *testPostManager { goldenATXID := types.ATXID{2, 3, 4} cdb := datastore.NewCachedDB(sql.InMemory(), logtest.New(tb)) - provingOpts := DefaultPostProvingOpts() - provingOpts.Flags = config.RecommendedPowFlags() - mgr, err := NewPostSetupManager(id, DefaultPostConfig(), zaptest.NewLogger(tb), cdb, goldenATXID, provingOpts) + mgr, err := NewPostSetupManager(id, DefaultPostConfig(), zaptest.NewLogger(tb), cdb, goldenATXID) require.NoError(tb, err) return &testPostManager{ diff --git a/api/grpcserver/post_service_test.go b/api/grpcserver/post_service_test.go index 37120813b3..e7b71ac2c0 100644 --- a/api/grpcserver/post_service_test.go +++ b/api/grpcserver/post_service_test.go @@ -8,7 +8,6 @@ import ( "testing" "time" - "github.com/spacemeshos/post/config" "github.com/spacemeshos/post/initialization" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -42,9 +41,7 @@ func initPost(tb testing.TB, log *zap.Logger, dir string) { goldenATXID := types.ATXID{2, 3, 4} cdb := datastore.NewCachedDB(sql.InMemory(), logtest.New(tb)) - provingOpts := activation.DefaultPostProvingOpts() - provingOpts.Flags = config.RecommendedPowFlags() - mgr, err := activation.NewPostSetupManager(id, cfg, log.Named("manager"), cdb, goldenATXID, provingOpts) + mgr, err := activation.NewPostSetupManager(id, cfg, log.Named("manager"), cdb, goldenATXID) require.NoError(tb, err) ctx, cancel := context.WithCancel(context.Background()) diff --git a/node/node.go b/node/node.go index 222d05e92d..52f4bd8ab8 100644 --- a/node/node.go +++ b/node/node.go @@ -835,7 +835,6 @@ func (app *App) initServices(ctx context.Context) error { app.Config.POST, app.addLogger(PostLogger, lg).Zap(), app.cachedDB, goldenATXID, - app.Config.SMESHING.ProvingOpts, ) if err != nil { app.log.Panic("failed to create post setup manager: %v", err) From 341fbbf371f94ecbcbd8934b99022482ae145f17 Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Mon, 9 Oct 2023 17:45:02 +0000 Subject: [PATCH 30/40] Replace Flags in proving options with RandomX mode --- activation/post.go | 12 +++++++----- config/presets/fastnet.go | 3 +-- config/presets/standalone.go | 3 +-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/activation/post.go b/activation/post.go index 5638770465..37b52e679a 100644 --- a/activation/post.go +++ b/activation/post.go @@ -106,17 +106,19 @@ func (id *PostProviderID) Value() *int64 { type PostProvingOpts struct { // Number of threads used in POST proving process. Threads uint `mapstructure:"smeshing-opts-proving-threads"` + // Number of nonces tried in parallel in POST proving process. Nonces uint `mapstructure:"smeshing-opts-proving-nonces"` - // Flags used in the PoW computation. - Flags config.PowFlags `mapstructure:"smeshing-opts-proving-powflags"` + + // RandomXMode is the mode used for RandomX computations. + RandomXMode string `mapstructure:"smeshing-opts-proving-randomx-mode"` } func DefaultPostProvingOpts() PostProvingOpts { return PostProvingOpts{ - Threads: 1, - Nonces: 16, - Flags: config.DefaultProvingPowFlags(), + Threads: 1, + Nonces: 16, + RandomXMode: "fast", } } diff --git a/config/presets/fastnet.go b/config/presets/fastnet.go index d6471f347b..f46ccf707b 100644 --- a/config/presets/fastnet.go +++ b/config/presets/fastnet.go @@ -5,7 +5,6 @@ import ( "math/big" "time" - postCfg "github.com/spacemeshos/post/config" "github.com/spacemeshos/post/initialization" "github.com/spacemeshos/go-spacemesh/common/types" @@ -77,7 +76,7 @@ func fastnet() config.Config { 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() + conf.SMESHING.ProvingOpts.RandomXMode = "light" conf.Beacon.Kappa = 40 conf.Beacon.Theta = big.NewRat(1, 4) diff --git a/config/presets/standalone.go b/config/presets/standalone.go index 9ff1012261..12f179bec6 100644 --- a/config/presets/standalone.go +++ b/config/presets/standalone.go @@ -6,7 +6,6 @@ import ( "path/filepath" "time" - postCfg "github.com/spacemeshos/post/config" "github.com/spacemeshos/post/initialization" "github.com/spacemeshos/go-spacemesh/common/types" @@ -62,7 +61,7 @@ func standalone() config.Config { conf.SMESHING.Opts.NumUnits = 1 conf.SMESHING.Opts.Throttle = true conf.SMESHING.Opts.DataDir = conf.DataDirParent - conf.SMESHING.ProvingOpts.Flags = postCfg.RecommendedPowFlags() + conf.SMESHING.ProvingOpts.RandomXMode = "light" conf.Beacon.Kappa = 40 conf.Beacon.Theta = big.NewRat(1, 4) From 1650a9077283fed214b20890fcd3b4eef7c81207 Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Mon, 9 Oct 2023 20:42:33 +0000 Subject: [PATCH 31/40] Deduplicate config, improve parsing and add tests --- activation/e2e/nipost_test.go | 33 ++++---- activation/e2e/validation_test.go | 5 +- activation/post.go | 53 +----------- activation/post_supervisor.go | 91 +++++++-------------- activation/post_supervisor_test.go | 46 +++++++---- activation/post_test.go | 64 --------------- activation/post_types.go | 109 +++++++++++++++++++++++++ activation/post_types_test.go | 121 ++++++++++++++++++++++++++++ api/grpcserver/post_service_test.go | 62 +++++++------- api/grpcserver/smesher_service.go | 2 + cmd/base.go | 8 ++ cmd/root.go | 57 ++++++++----- config/config.go | 2 +- config/mainnet.go | 2 +- config/presets/fastnet.go | 9 +-- config/presets/standalone.go | 8 +- node/node.go | 6 +- node/node_test.go | 4 - 18 files changed, 398 insertions(+), 284 deletions(-) create mode 100644 activation/post_types_test.go diff --git a/activation/e2e/nipost_test.go b/activation/e2e/nipost_test.go index 2f7405f6bf..20925b7801 100644 --- a/activation/e2e/nipost_test.go +++ b/activation/e2e/nipost_test.go @@ -62,20 +62,19 @@ func spawnPoet(tb testing.TB, opts ...HTTPPoetOpt) *HTTPPoetTestHarness { return poetProver } -func launchPostSupervisor(tb testing.TB, log *zap.Logger, cfg grpcserver.Config, postDir string) func() { +func launchPostSupervisor(tb testing.TB, log *zap.Logger, cfg grpcserver.Config, postOpts activation.PostSetupOpts) func() { path, err := exec.Command("go", "env", "GOMOD").Output() require.NoError(tb, err) - opts := activation.PostSupervisorConfig{ - PostServiceCmd: filepath.Join(filepath.Dir(string(path)), "build", "service"), - DataDir: postDir, - NodeAddress: fmt.Sprintf("http://%s", cfg.PublicListener), - PowDifficulty: activation.DefaultPostConfig().PowDifficulty, - PostServiceMode: "light", - N: 2, + cmdCfg := activation.PostSupervisorConfig{ + PostServiceCmd: filepath.Join(filepath.Dir(string(path)), "build", "service"), + NodeAddress: fmt.Sprintf("http://%s", cfg.PublicListener), } + postCfg := activation.DefaultPostConfig() + provingOpts := activation.DefaultPostProvingOpts() + provingOpts.RandomXMode = activation.PostRandomXModeLight - ps, err := activation.NewPostSupervisor(log, opts) + ps, err := activation.NewPostSupervisor(log, cmdCfg, postCfg, postOpts, provingOpts) require.NoError(tb, err) require.NotNil(tb, ps) return func() { assert.NoError(tb, ps.Close()) } @@ -150,9 +149,8 @@ func TestNIPostBuilderWithClients(t *testing.T) { mgr, err := activation.NewPostSetupManager(sig.NodeID(), cfg, logger, cdb, goldenATX) require.NoError(t, err) - postDir := t.TempDir() opts := activation.DefaultPostSetupOpts() - opts.DataDir = postDir + opts.DataDir = t.TempDir() opts.ProviderID.SetInt64(int64(initialization.CPUProviderID())) opts.Scrypt.N = 2 // Speedup initialization in tests. initPost(t, logger.Named("manager"), mgr, opts) @@ -206,7 +204,7 @@ func TestNIPostBuilderWithClients(t *testing.T) { grpcCfg, cleanup := launchServer(t, svc) t.Cleanup(cleanup) - t.Cleanup(launchPostSupervisor(t, logger, grpcCfg, postDir)) + t.Cleanup(launchPostSupervisor(t, logger, grpcCfg, opts)) select { case <-connected: @@ -334,8 +332,11 @@ func TestNewNIPostBuilderNotInitialized(t *testing.T) { grpcCfg, cleanup := launchServer(t, svc) t.Cleanup(cleanup) - postDir := t.TempDir() - t.Cleanup(launchPostSupervisor(t, logger, grpcCfg, postDir)) + opts := activation.DefaultPostSetupOpts() + opts.DataDir = t.TempDir() + opts.ProviderID.SetInt64(int64(initialization.CPUProviderID())) + opts.Scrypt.N = 2 // Speedup initialization in tests. + t.Cleanup(launchPostSupervisor(t, logger, grpcCfg, opts)) select { case <-connected: @@ -351,10 +352,6 @@ func TestNewNIPostBuilderNotInitialized(t *testing.T) { require.ErrorContains(t, err, "failed to generate Post: error generating proof") require.Nil(t, nipost) - opts := activation.DefaultPostSetupOpts() - opts.DataDir = postDir - opts.ProviderID.SetInt64(int64(initialization.CPUProviderID())) - opts.Scrypt.N = 2 // Speedup initialization in tests. initPost(t, logger.Named("manager"), mgr, opts) nipost, err = nb.BuildNIPost(context.Background(), &challenge) diff --git a/activation/e2e/validation_test.go b/activation/e2e/validation_test.go index de6859f9e9..b1a30ba28a 100644 --- a/activation/e2e/validation_test.go +++ b/activation/e2e/validation_test.go @@ -37,9 +37,8 @@ func TestValidator_Validate(t *testing.T) { mgr, err := activation.NewPostSetupManager(sig.NodeID(), cfg, logger, cdb, goldenATX) require.NoError(t, err) - postDir := t.TempDir() opts := activation.DefaultPostSetupOpts() - opts.DataDir = postDir + opts.DataDir = t.TempDir() opts.ProviderID.SetInt64(int64(initialization.CPUProviderID())) opts.Scrypt.N = 2 // Speedup initialization in tests. initPost(t, logger.Named("manager"), mgr, opts) @@ -93,7 +92,7 @@ func TestValidator_Validate(t *testing.T) { grpcCfg, cleanup := launchServer(t, svc) t.Cleanup(cleanup) - t.Cleanup(launchPostSupervisor(t, logger, grpcCfg, postDir)) + t.Cleanup(launchPostSupervisor(t, logger, grpcCfg, opts)) select { case <-connected: diff --git a/activation/post.go b/activation/post.go index 37b52e679a..72b73426a8 100644 --- a/activation/post.go +++ b/activation/post.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" "runtime" - "strconv" "sync" "github.com/spacemeshos/post/config" @@ -58,50 +57,6 @@ type PostSetupOpts struct { ComputeBatchSize uint64 `mapstructure:"smeshing-opts-compute-batch-size"` } -type PostProviderID struct { - value *int64 -} - -// String implements pflag.Value.String. -func (id PostProviderID) String() string { - if id.value == nil { - return "" - } - return fmt.Sprintf("%d", *id.value) -} - -// Type implements pflag.Value.Type. -func (PostProviderID) Type() string { - return "PostProviderID" -} - -// Set implements pflag.Value.Set. -func (id *PostProviderID) Set(value string) error { - if len(value) == 0 { - id.value = nil - return nil - } - - i, err := strconv.ParseInt(value, 10, 33) - if err != nil { - return fmt.Errorf("failed to parse PoST Provider ID (\"%s\"): %w", value, err) - } - - id.value = new(int64) - *id.value = int64(i) - return nil -} - -// SetInt64 sets the value of the PostProviderID to the given int64. -func (id *PostProviderID) SetInt64(value int64) { - id.value = &value -} - -// Value returns the value of the PostProviderID as a pointer to uint32. -func (id *PostProviderID) Value() *int64 { - return id.value -} - // PostProvingOpts are the options controlling POST proving process. type PostProvingOpts struct { // Number of threads used in POST proving process. @@ -111,14 +66,14 @@ type PostProvingOpts struct { Nonces uint `mapstructure:"smeshing-opts-proving-nonces"` // RandomXMode is the mode used for RandomX computations. - RandomXMode string `mapstructure:"smeshing-opts-proving-randomx-mode"` + RandomXMode PostRandomXMode `mapstructure:"smeshing-opts-proving-randomx-mode"` } func DefaultPostProvingOpts() PostProvingOpts { return PostProvingOpts{ Threads: 1, Nonces: 16, - RandomXMode: "fast", + RandomXMode: PostRandomXModeFast, } } @@ -127,7 +82,7 @@ type PostProofVerifyingOpts struct { // Number of workers spawned to verify proofs. Workers int `mapstructure:"smeshing-opts-verifying-workers"` // Flags used for the PoW verification. - Flags config.PowFlags `mapstructure:"smeshing-opts-verifying-powflags"` + Flags PostPowFlags `mapstructure:"smeshing-opts-verifying-powflags"` } func DefaultPostVerifyingOpts() PostProofVerifyingOpts { @@ -137,7 +92,7 @@ func DefaultPostVerifyingOpts() PostProofVerifyingOpts { } return PostProofVerifyingOpts{ Workers: workers, - Flags: config.DefaultVerifyingPowFlags(), + Flags: PostPowFlags(config.DefaultVerifyingPowFlags()), } } diff --git a/activation/post_supervisor.go b/activation/post_supervisor.go index fec62195e1..f0bb683474 100644 --- a/activation/post_supervisor.go +++ b/activation/post_supervisor.go @@ -5,13 +5,13 @@ import ( "context" "fmt" "io" + "os" "os/exec" "path/filepath" "strconv" "strings" "sync/atomic" - "github.com/spacemeshos/post/config" "go.uber.org/zap" "golang.org/x/sync/errgroup" @@ -20,45 +20,16 @@ import ( // DefaultPostServiceConfig returns the default config for post service. These are intended for testing. func DefaultPostServiceConfig() PostSupervisorConfig { - cfg := PostSupervisorConfig{ - PostServiceCmd: "/bin/service", - DataDir: config.DefaultDataDir, - NodeAddress: "http://127.0.0.1:9093", - PowDifficulty: config.DefaultConfig().PowDifficulty, - PostServiceMode: "light", + return PostSupervisorConfig{ + PostServiceCmd: "/bin/service", + NodeAddress: "http://127.0.0.1:9093", } - - return cfg -} - -// MainnetPostServiceConfig returns the default config for mainnet. -func MainnetPostServiceConfig() PostSupervisorConfig { - cfg := PostSupervisorConfig{ - PostServiceCmd: "/bin/service", - DataDir: config.DefaultDataDir, - NodeAddress: "http://127.0.0.1:9093", - PowDifficulty: config.MainnetConfig().PowDifficulty, - PostServiceMode: "fast", - } - - return cfg } type PostSupervisorConfig struct { PostServiceCmd string `mapstructure:"post-opts-post-service"` - DataDir string `mapstructure:"post-opts-datadir"` - NodeAddress string `mapstructure:"post-opts-node-address"` - PostServiceMode string `mapstructure:"post-opts-post-service-mode"` - - PowDifficulty PowDifficulty `mapstructure:"post-opts-pow-difficulty"` - K1 uint32 `mapstructure:"post-opts-k1"` - K2 uint32 `mapstructure:"post-opts-k2"` - K3 uint32 `mapstructure:"post-opts-k3"` - - N uint `mapstructure:"post-opts-n"` - R uint `mapstructure:"post-opts-r"` - P uint `mapstructure:"post-opts-p"` + NodeAddress string `mapstructure:"post-opts-node-address"` } // PostSupervisor manages a local post service. @@ -72,14 +43,17 @@ type PostSupervisor struct { } // NewPostSupervisor returns a new post service. -func NewPostSupervisor(logger *zap.Logger, opts PostSupervisorConfig) (*PostSupervisor, error) { - ctx, stop := context.WithCancel(context.Background()) +func NewPostSupervisor(logger *zap.Logger, cmdCfg PostSupervisorConfig, postCfg PostConfig, postOpts PostSetupOpts, provingOpts PostProvingOpts) (*PostSupervisor, error) { + if _, err := os.Stat(cmdCfg.PostServiceCmd); err != nil { + return nil, fmt.Errorf("post service binary not found: %s", cmdCfg.PostServiceCmd) + } + ctx, stop := context.WithCancel(context.Background()) ps := &PostSupervisor{ logger: logger, stop: stop, } - ps.eg.Go(func() error { return ps.runCmd(ctx, opts) }) + ps.eg.Go(func() error { return ps.runCmd(ctx, cmdCfg, postCfg, postOpts, provingOpts) }) return ps, nil } @@ -112,39 +86,32 @@ func (ps *PostSupervisor) captureCmdOutput(pipe io.ReadCloser) func() error { } } -func (ps *PostSupervisor) runCmd(ctx context.Context, opts PostSupervisorConfig) error { +func (ps *PostSupervisor) runCmd(ctx context.Context, cmdCfg PostSupervisorConfig, postCfg PostConfig, postOpts PostSetupOpts, provingOpts PostProvingOpts) error { for { args := []string{ - "--dir", opts.DataDir, - "--address", opts.NodeAddress, - "--pow-difficulty", opts.PowDifficulty.String(), - "--randomx-mode", opts.PostServiceMode, - } - if opts.K1 != 0 { - args = append(args, "--k1", strconv.FormatUint(uint64(opts.K1), 10)) - } - if opts.K2 != 0 { - args = append(args, "--k2", strconv.FormatUint(uint64(opts.K2), 10)) - } - if opts.K3 != 0 { - args = append(args, "--k3", strconv.FormatUint(uint64(opts.K3), 10)) - } - if opts.N != 0 { - args = append(args, "-n", strconv.FormatUint(uint64(opts.N), 10)) - } - if opts.R != 0 { - args = append(args, "-r", strconv.FormatUint(uint64(opts.R), 10)) - } - if opts.P != 0 { - args = append(args, "-p", strconv.FormatUint(uint64(opts.P), 10)) + "--address", cmdCfg.NodeAddress, + + "--k1", strconv.FormatUint(uint64(postCfg.K1), 10), + "--k2", strconv.FormatUint(uint64(postCfg.K2), 10), + "--k3", strconv.FormatUint(uint64(postCfg.K3), 10), + "--pow-difficulty", postCfg.PowDifficulty.String(), + + "--dir", postOpts.DataDir, + "-n", strconv.FormatUint(uint64(postOpts.Scrypt.N), 10), + "-r", strconv.FormatUint(uint64(postOpts.Scrypt.R), 10), + "-p", strconv.FormatUint(uint64(postOpts.Scrypt.P), 10), + + "--threads", strconv.FormatUint(uint64(provingOpts.Threads), 10), + "--nonces", strconv.FormatUint(uint64(provingOpts.Nonces), 10), + "--randomx-mode", provingOpts.RandomXMode.String(), } cmd := exec.CommandContext( ctx, - opts.PostServiceCmd, + cmdCfg.PostServiceCmd, args..., ) - cmd.Dir = filepath.Dir(opts.PostServiceCmd) + cmd.Dir = filepath.Dir(cmdCfg.PostServiceCmd) pipe, err := cmd.StderrPipe() if err != nil { return fmt.Errorf("setup stderr pipe for post service: %w", err) diff --git a/activation/post_supervisor_test.go b/activation/post_supervisor_test.go index c410fa9014..ce73cb2bdb 100644 --- a/activation/post_supervisor_test.go +++ b/activation/post_supervisor_test.go @@ -14,22 +14,37 @@ import ( "go.uber.org/zap/zaptest" ) +func Test_PostSupervisor_ErrOnMissingBinary(t *testing.T) { + log := zaptest.NewLogger(t) + + cmdCfg := PostSupervisorConfig{ + PostServiceCmd: filepath.Join(t.TempDir(), "service"), + NodeAddress: "http://127.0.0.1:12345", // node isn't listening and not relevant for test + } + postCfg := DefaultPostConfig() + postOpts := DefaultPostSetupOpts() + provingOpts := DefaultPostProvingOpts() + + ps, err := NewPostSupervisor(log.Named("supervisor"), cmdCfg, postCfg, postOpts, provingOpts) + require.ErrorContains(t, err, "post service binary not found") + require.Nil(t, ps) +} + func Test_PostSupervisor_StartsServiceCmd(t *testing.T) { log := zaptest.NewLogger(t) - postDir := t.TempDir() path, err := exec.Command("go", "env", "GOMOD").Output() require.NoError(t, err) - opts := PostSupervisorConfig{ - PostServiceCmd: filepath.Join(filepath.Dir(string(path)), "build", "service"), - DataDir: postDir, - NodeAddress: "http://127.0.0.1:12345", // node isn't listening, but also not relevant for test - PowDifficulty: DefaultPostConfig().PowDifficulty, - PostServiceMode: "light", + cmdCfg := PostSupervisorConfig{ + PostServiceCmd: filepath.Join(filepath.Dir(string(path)), "build", "service"), + NodeAddress: "http://127.0.0.1:12345", // node isn't listening and not relevant for test } + postCfg := DefaultPostConfig() + postOpts := DefaultPostSetupOpts() + provingOpts := DefaultPostProvingOpts() - ps, err := NewPostSupervisor(log.Named("supervisor"), opts) + ps, err := NewPostSupervisor(log.Named("supervisor"), cmdCfg, postCfg, postOpts, provingOpts) require.NoError(t, err) require.NotNil(t, ps) t.Cleanup(func() { assert.NoError(t, ps.Close()) }) @@ -55,19 +70,18 @@ func Test_PostSupervisor_StartsServiceCmd(t *testing.T) { func Test_PostSupervisor_RestartsOnCrash(t *testing.T) { log := zaptest.NewLogger(t) - postDir := t.TempDir() path, err := exec.Command("go", "env", "GOMOD").Output() require.NoError(t, err) - opts := PostSupervisorConfig{ - PostServiceCmd: filepath.Join(filepath.Dir(string(path)), "build", "service"), - DataDir: postDir, - NodeAddress: "http://127.0.0.1:12345", // node isn't listening, but also not relevant for test - PowDifficulty: DefaultPostConfig().PowDifficulty, - PostServiceMode: "light", + cmdCfg := PostSupervisorConfig{ + PostServiceCmd: filepath.Join(filepath.Dir(string(path)), "build", "service"), + NodeAddress: "http://127.0.0.1:12345", // node isn't listening and not relevant for test } + postCfg := DefaultPostConfig() + postOpts := DefaultPostSetupOpts() + provingOpts := DefaultPostProvingOpts() - ps, err := NewPostSupervisor(log.Named("supervisor"), opts) + ps, err := NewPostSupervisor(log.Named("supervisor"), cmdCfg, postCfg, postOpts, provingOpts) require.NoError(t, err) require.NotNil(t, ps) t.Cleanup(func() { assert.NoError(t, ps.Close()) }) diff --git a/activation/post_test.go b/activation/post_test.go index 569d026212..98a53dd2b2 100644 --- a/activation/post_test.go +++ b/activation/post_test.go @@ -1,9 +1,7 @@ package activation import ( - "bytes" "context" - "encoding/hex" "testing" "time" @@ -428,65 +426,3 @@ func newTestPostManager(tb testing.TB) *testPostManager { cdb: cdb, } } - -func TestSettingPowDifficulty(t *testing.T) { - t.Parallel() - expected := bytes.Repeat([]byte{0x01, 0x02, 0x03, 0x04}, 8) - encoded := hex.EncodeToString(expected) - t.Run("parse 32B hex", func(t *testing.T) { - t.Parallel() - d := PowDifficulty{} - err := d.Set(encoded) - require.NoError(t, err) - require.Equal(t, expected, d[:]) - }) - t.Run("input too short", func(t *testing.T) { - t.Parallel() - d := PowDifficulty{} - require.Error(t, d.Set("123")) - require.Equal(t, PowDifficulty{}, d) - }) - t.Run("input too long", func(t *testing.T) { - t.Parallel() - d := PowDifficulty{} - require.Error(t, d.Set(hex.EncodeToString(bytes.Repeat([]byte{0x01}, 33)))) - require.Equal(t, PowDifficulty{}, d) - }) - t.Run("not a hex string", func(t *testing.T) { - t.Parallel() - encoded := encoded[:len(encoded)-1] + "G" - d := PowDifficulty{} - require.Error(t, d.Set(encoded)) - require.Equal(t, PowDifficulty{}, d) - }) -} - -func TestSettingProviderID(t *testing.T) { - t.Parallel() - - t.Run("valid value", func(t *testing.T) { - t.Parallel() - id := new(PostProviderID) - require.NoError(t, id.Set("1234")) - require.Equal(t, int64(1234), *id.Value()) - }) - t.Run("no value", func(t *testing.T) { - t.Parallel() - id := new(PostProviderID) - require.NoError(t, id.Set("")) - require.Nil(t, id.Value()) - }) - t.Run("not a number", func(t *testing.T) { - t.Parallel() - id := new(PostProviderID) - require.Error(t, id.Set("asdf")) - require.Nil(t, id.Value()) - }) - // TODO(mafa): re-enable test, see https://github.com/spacemeshos/go-spacemesh/issues/4801 - // t.Run("negative", func(t *testing.T) { - // t.Parallel() - // id := new(PostProviderID) - // require.Error(t, id.Set("-1")) - // require.Nil(t, id.Value()) - // }) -} diff --git a/activation/post_types.go b/activation/post_types.go index b81dadd66d..ee2874d626 100644 --- a/activation/post_types.go +++ b/activation/post_types.go @@ -3,6 +3,9 @@ package activation import ( "encoding/hex" "fmt" + "strconv" + + "github.com/spacemeshos/post/config" ) type PowDifficulty [32]byte @@ -33,3 +36,109 @@ func (d *PowDifficulty) UnmarshalText(text []byte) error { *d = PowDifficulty(dst) return nil } + +type PostProviderID struct { + value *int64 +} + +// String implements pflag.Value.String. +func (id PostProviderID) String() string { + if id.value == nil { + return "" + } + return fmt.Sprintf("%d", *id.value) +} + +// Type implements pflag.Value.Type. +func (PostProviderID) Type() string { + return "PostProviderID" +} + +// Set implements pflag.Value.Set. +func (id *PostProviderID) Set(value string) error { + if len(value) == 0 { + id.value = nil + return nil + } + + i, err := strconv.ParseInt(value, 10, 33) + if err != nil { + return fmt.Errorf("failed to parse PoST Provider ID (\"%s\"): %w", value, err) + } + + id.value = new(int64) + *id.value = int64(i) + return nil +} + +// SetInt64 sets the value of the PostProviderID to the given int64. +func (id *PostProviderID) SetInt64(value int64) { + id.value = &value +} + +// Value returns the value of the PostProviderID as a pointer to uint32. +func (id *PostProviderID) Value() *int64 { + return id.value +} + +type PostPowFlags config.PowFlags + +// String implements pflag.Value.String. +func (f PostPowFlags) String() string { + return fmt.Sprintf("%d", f) +} + +// Type implements pflag.Value.Type. +func (PostPowFlags) Type() string { + return "PostPowFlags" +} + +// Set implements pflag.Value.Set. +func (f *PostPowFlags) Set(value string) error { + if len(value) == 0 { + *f = 0 + return nil + } + + i, err := strconv.ParseUint(value, 10, 32) + if err != nil { + return fmt.Errorf("failed to parse PoST PoW flags (\"%s\"): %w", value, err) + } + + *f = PostPowFlags(i) + return nil +} + +func (f *PostPowFlags) Value() config.PowFlags { + return config.PowFlags(*f) +} + +type PostRandomXMode string + +const ( + PostRandomXModeFast PostRandomXMode = "fast" + PostRandomXModeLight PostRandomXMode = "light" +) + +// String implements pflag.Value.String. +func (m PostRandomXMode) String() string { + return string(m) +} + +// Type implements pflag.Value.Type. +func (PostRandomXMode) Type() string { + return "PostRandomXMode" +} + +// Set implements pflag.Value.Set. +func (m *PostRandomXMode) Set(value string) error { + switch value { + case string(PostRandomXModeFast): + *m = PostRandomXModeFast + case string(PostRandomXModeLight): + *m = PostRandomXModeLight + default: + return fmt.Errorf("invalid PoST RandomX mode (\"%s\")", value) + } + return nil +} diff --git a/activation/post_types_test.go b/activation/post_types_test.go new file mode 100644 index 0000000000..43e1916acd --- /dev/null +++ b/activation/post_types_test.go @@ -0,0 +1,121 @@ +package activation + +import ( + "bytes" + "encoding/hex" + "fmt" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestSettingPowDifficulty(t *testing.T) { + t.Parallel() + + expected := bytes.Repeat([]byte{0x01, 0x02, 0x03, 0x04}, 8) + encoded := hex.EncodeToString(expected) + t.Run("parse 32B hex", func(t *testing.T) { + t.Parallel() + d := PowDifficulty{} + err := d.Set(encoded) + require.NoError(t, err) + require.Equal(t, expected, d[:]) + }) + t.Run("input too short", func(t *testing.T) { + t.Parallel() + d := PowDifficulty{} + require.Error(t, d.Set("123")) + require.Equal(t, PowDifficulty{}, d) + }) + t.Run("input too long", func(t *testing.T) { + t.Parallel() + d := PowDifficulty{} + require.Error(t, d.Set(hex.EncodeToString(bytes.Repeat([]byte{0x01}, 33)))) + require.Equal(t, PowDifficulty{}, d) + }) + t.Run("not a hex string", func(t *testing.T) { + t.Parallel() + encoded := encoded[:len(encoded)-1] + "G" + d := PowDifficulty{} + require.Error(t, d.Set(encoded)) + require.Equal(t, PowDifficulty{}, d) + }) +} + +func TestSettingProviderID(t *testing.T) { + t.Parallel() + + t.Run("valid value", func(t *testing.T) { + t.Parallel() + id := new(PostProviderID) + require.NoError(t, id.Set("1234")) + require.Equal(t, int64(1234), *id.Value()) + }) + t.Run("no value", func(t *testing.T) { + t.Parallel() + id := new(PostProviderID) + require.NoError(t, id.Set("")) + require.Nil(t, id.Value()) + }) + t.Run("not a number", func(t *testing.T) { + t.Parallel() + id := new(PostProviderID) + require.Error(t, id.Set("asdf")) + require.Nil(t, id.Value()) + }) + // TODO(mafa): re-enable test, see https://github.com/spacemeshos/go-spacemesh/issues/4801 + // t.Run("negative", func(t *testing.T) { + // t.Parallel() + // id := new(PostProviderID) + // require.Error(t, id.Set("-1")) + // require.Nil(t, id.Value()) + // }) +} + +func TestSettingPostPowFlags(t *testing.T) { + t.Parallel() + + t.Run("valid value", func(t *testing.T) { + t.Parallel() + f := new(PostPowFlags) + require.NoError(t, f.Set("123")) + require.EqualValues(t, 123, *f) + }) + t.Run("no value", func(t *testing.T) { + t.Parallel() + f := new(PostPowFlags) + require.NoError(t, f.Set("")) + require.EqualValues(t, 0, *f) + }) + t.Run("not a number", func(t *testing.T) { + t.Parallel() + f := new(PostPowFlags) + require.Error(t, f.Set("a123")) + }) +} + +func TestSettingPostRandomXMode(t *testing.T) { + t.Parallel() + + for _, mode := range []PostRandomXMode{PostRandomXModeFast, PostRandomXModeLight} { + mode := mode + t.Run(fmt.Sprintf("valid value %s", mode.String()), func(t *testing.T) { + t.Parallel() + m := new(PostRandomXMode) + require.NoError(t, m.Set(mode.String())) + require.Equal(t, mode, *m) + }) + } + t.Run("no value", func(t *testing.T) { + t.Parallel() + m := new(PostRandomXMode) + require.Error(t, m.Set("")) + require.Empty(t, m) + }) + t.Run("not a valid value", func(t *testing.T) { + t.Parallel() + m := new(PostRandomXMode) + require.Error(t, m.Set("asdf")) + require.Empty(t, m) + }) +} diff --git a/api/grpcserver/post_service_test.go b/api/grpcserver/post_service_test.go index e7b71ac2c0..6d71b47ec1 100644 --- a/api/grpcserver/post_service_test.go +++ b/api/grpcserver/post_service_test.go @@ -24,7 +24,7 @@ import ( "github.com/spacemeshos/go-spacemesh/sql" ) -func initPost(tb testing.TB, log *zap.Logger, dir string) { +func initPost(tb testing.TB, log *zap.Logger, opts activation.PostSetupOpts) { tb.Helper() cfg := activation.DefaultPostConfig() @@ -33,11 +33,6 @@ func initPost(tb testing.TB, log *zap.Logger, dir string) { require.NoError(tb, err) id := sig.NodeID() - opts := activation.DefaultPostSetupOpts() - opts.DataDir = dir - opts.ProviderID.SetInt64(int64(initialization.CPUProviderID())) - opts.Scrypt.N = 2 // Speedup initialization in tests. - goldenATXID := types.ATXID{2, 3, 4} cdb := datastore.NewCachedDB(sql.InMemory(), logtest.New(tb)) @@ -77,20 +72,19 @@ func initPost(tb testing.TB, log *zap.Logger, dir string) { require.Equal(tb, activation.PostSetupStateComplete, mgr.Status().State) } -func launchPostSupervisor(tb testing.TB, log *zap.Logger, cfg Config, postDir string) func() { +func launchPostSupervisor(tb testing.TB, log *zap.Logger, cfg Config, postOpts activation.PostSetupOpts) func() { path, err := exec.Command("go", "env", "GOMOD").Output() require.NoError(tb, err) opts := activation.PostSupervisorConfig{ - PostServiceCmd: filepath.Join(filepath.Dir(string(path)), "build", "service"), - DataDir: postDir, - NodeAddress: fmt.Sprintf("http://%s", cfg.PublicListener), - PowDifficulty: activation.DefaultPostConfig().PowDifficulty, - PostServiceMode: "light", - N: 2, + PostServiceCmd: filepath.Join(filepath.Dir(string(path)), "build", "service"), + NodeAddress: fmt.Sprintf("http://%s", cfg.PublicListener), } + postCfg := activation.DefaultPostConfig() + provingOpts := activation.DefaultPostProvingOpts() + provingOpts.RandomXMode = activation.PostRandomXModeLight - ps, err := activation.NewPostSupervisor(log, opts) + ps, err := activation.NewPostSupervisor(log, opts, postCfg, postOpts, provingOpts) require.NoError(tb, err) require.NotNil(tb, ps) return func() { assert.NoError(tb, ps.Close()) } @@ -112,9 +106,12 @@ func Test_GenerateProof(t *testing.T) { }).Times(1) con.EXPECT().Disconnected(gomock.Any()).Times(1) - postDir := t.TempDir() - initPost(t, log.Named("post"), postDir) - postCleanup := launchPostSupervisor(t, log.Named("supervisor"), cfg, postDir) + opts := activation.DefaultPostSetupOpts() + opts.DataDir = t.TempDir() + opts.ProviderID.SetInt64(int64(initialization.CPUProviderID())) + opts.Scrypt.N = 2 // Speedup initialization in tests. + initPost(t, log.Named("post"), opts) + postCleanup := launchPostSupervisor(t, log.Named("supervisor"), cfg, opts) t.Cleanup(postCleanup) select { @@ -161,9 +158,12 @@ func Test_Cancel_GenerateProof(t *testing.T) { }).Times(1) con.EXPECT().Disconnected(gomock.Any()).Times(1) - postDir := t.TempDir() - initPost(t, log.Named("post"), postDir) - t.Cleanup(launchPostSupervisor(t, log.Named("supervisor"), cfg, postDir)) + opts := activation.DefaultPostSetupOpts() + opts.DataDir = t.TempDir() + opts.ProviderID.SetInt64(int64(initialization.CPUProviderID())) + opts.Scrypt.N = 2 // Speedup initialization in tests. + initPost(t, log.Named("post"), opts) + t.Cleanup(launchPostSupervisor(t, log.Named("supervisor"), cfg, opts)) select { case <-connected: @@ -202,18 +202,22 @@ func Test_GenerateProof_MultipleServices(t *testing.T) { }).Times(1) con.EXPECT().Disconnected(gomock.Any()).Times(1) + opts := activation.DefaultPostSetupOpts() + opts.DataDir = t.TempDir() + opts.ProviderID.SetInt64(int64(initialization.CPUProviderID())) + opts.Scrypt.N = 2 // Speedup initialization in tests. + // all but one should not be able to register to the node (i.e. open a stream to it). - postDir1 := t.TempDir() - initPost(t, log.Named("post1"), postDir1) - t.Cleanup(launchPostSupervisor(t, log.Named("supervisor1"), cfg, postDir1)) + initPost(t, log.Named("post1"), opts) + t.Cleanup(launchPostSupervisor(t, log.Named("supervisor1"), cfg, opts)) - postDir2 := t.TempDir() - initPost(t, log.Named("post2"), postDir2) - t.Cleanup(launchPostSupervisor(t, log.Named("supervisor2"), cfg, postDir2)) + opts.DataDir = t.TempDir() + initPost(t, log.Named("post2"), opts) + t.Cleanup(launchPostSupervisor(t, log.Named("supervisor2"), cfg, opts)) - postDir3 := t.TempDir() - initPost(t, log.Named("post3"), postDir3) - t.Cleanup(launchPostSupervisor(t, log.Named("supervisor3"), cfg, postDir3)) + opts.DataDir = t.TempDir() + initPost(t, log.Named("post3"), opts) + t.Cleanup(launchPostSupervisor(t, log.Named("supervisor3"), cfg, opts)) select { case <-connected: diff --git a/api/grpcserver/smesher_service.go b/api/grpcserver/smesher_service.go index 1d77c34886..c5129ea2a8 100644 --- a/api/grpcserver/smesher_service.go +++ b/api/grpcserver/smesher_service.go @@ -50,6 +50,7 @@ func (s SmesherService) IsSmeshing(context.Context, *emptypb.Empty) (*pb.IsSmesh } // StartSmeshing requests that the node begin smeshing. +// TODO(mafa): stop post supervisor. func (s SmesherService) StartSmeshing(ctx context.Context, in *pb.StartSmeshingRequest) (*pb.StartSmeshingResponse, error) { if in.Coinbase == nil { return nil, status.Errorf(codes.InvalidArgument, "`Coinbase` must be provided") @@ -98,6 +99,7 @@ func (s SmesherService) StartSmeshing(ctx context.Context, in *pb.StartSmeshingR } // StopSmeshing requests that the node stop smeshing. +// TODO(mafa): stop post supervisor. func (s SmesherService) StopSmeshing(ctx context.Context, in *pb.StopSmeshingRequest) (*pb.StopSmeshingResponse, error) { errchan := make(chan error, 1) go func() { diff --git a/cmd/base.go b/cmd/base.go index f33bef8597..77ec57fb54 100644 --- a/cmd/base.go +++ b/cmd/base.go @@ -160,6 +160,14 @@ func EnsureCLIFlags(cmd *cobra.Command, appCFG *config.Config) error { elem = reflect.ValueOf(&appCFG.SMESHING.Opts).Elem() assignFields(ff, elem, name) + ff = reflect.TypeOf(appCFG.SMESHING.ProvingOpts) + elem = reflect.ValueOf(&appCFG.SMESHING.ProvingOpts).Elem() + assignFields(ff, elem, name) + + ff = reflect.TypeOf(appCFG.SMESHING.VerifyingOpts) + elem = reflect.ValueOf(&appCFG.SMESHING.VerifyingOpts).Elem() + assignFields(ff, elem, name) + ff = reflect.TypeOf(appCFG.LOGGING) elem = reflect.ValueOf(&appCFG.LOGGING).Elem() assignFields(ff, elem, name) diff --git a/cmd/root.go b/cmd/root.go index 38a444f9c8..f3787bf47c 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/spf13/cobra" + "github.com/spf13/pflag" "github.com/spf13/viper" "github.com/spacemeshos/go-spacemesh/common/types" @@ -226,7 +227,12 @@ func AddCommands(cmd *cobra.Command) { cfg.POST.K2, "number of labels to prove") cmd.PersistentFlags().Uint32Var(&cfg.POST.K3, "post-k3", cfg.POST.K3, "subset of labels to verify in a proof") - cmd.PersistentFlags().VarP(&cfg.POST.PowDifficulty, "post-pow-difficulty", "", "difficulty of randomx-based proof of work") + cmd.PersistentFlags().AddFlag(&pflag.Flag{ + Name: "post-pow-difficulty", + Value: &cfg.POST.PowDifficulty, + DefValue: cfg.POST.PowDifficulty.String(), + Usage: "difficulty of randomx-based proof of work", + }) /**======================== Smeshing Flags ========================== **/ @@ -242,35 +248,44 @@ func AddCommands(cmd *cobra.Command) { cfg.SMESHING.Opts.NumUnits, "") cmd.PersistentFlags().Uint64Var(&cfg.SMESHING.Opts.MaxFileSize, "smeshing-opts-maxfilesize", cfg.SMESHING.Opts.MaxFileSize, "") - cmd.PersistentFlags().VarP(&cfg.SMESHING.Opts.ProviderID, "smeshing-opts-provider", - "", "") + cmd.PersistentFlags().AddFlag(&pflag.Flag{ + Name: "smeshing-opts-provider", + Value: &cfg.SMESHING.Opts.ProviderID, + DefValue: cfg.SMESHING.Opts.ProviderID.String(), + }) cmd.PersistentFlags().BoolVar(&cfg.SMESHING.Opts.Throttle, "smeshing-opts-throttle", cfg.SMESHING.Opts.Throttle, "") + // TODO(mafa): add Scrypt-Opts? + + /**======================== PoST Proving Flags ========================== **/ + + cmd.PersistentFlags().UintVar(&cfg.SMESHING.ProvingOpts.Threads, "smeshing-opts-proving-threads", + cfg.SMESHING.ProvingOpts.Threads, "") + cmd.PersistentFlags().UintVar(&cfg.SMESHING.ProvingOpts.Nonces, "smeshing-opts-proving-nonces", + cfg.SMESHING.ProvingOpts.Nonces, "") + cmd.PersistentFlags().AddFlag(&pflag.Flag{ + Name: "smeshing-opts-proving-randomx-mode", + Value: &cfg.SMESHING.ProvingOpts.RandomXMode, + DefValue: cfg.SMESHING.ProvingOpts.RandomXMode.String(), + }) + + /**======================== PoST Verifying Flags ========================== **/ + + cmd.PersistentFlags().IntVar(&cfg.SMESHING.VerifyingOpts.Workers, "smeshing-opts-verifying-threads", + cfg.SMESHING.VerifyingOpts.Workers, "") + cmd.PersistentFlags().AddFlag(&pflag.Flag{ + Name: "smeshing-opts-verifying-powflags", + Value: &cfg.SMESHING.VerifyingOpts.Flags, + DefValue: cfg.SMESHING.VerifyingOpts.Flags.String(), + }) + /**======================== PoST service Flags ========================== **/ cmd.PersistentFlags().StringVar(&cfg.POSTService.PostServiceCmd, "post-opts-post-service", cfg.POSTService.PostServiceCmd, "") - cmd.PersistentFlags().StringVar(&cfg.POSTService.DataDir, "post-opts-datadir", - cfg.POSTService.DataDir, "") cmd.PersistentFlags().StringVar(&cfg.POSTService.NodeAddress, "post-opts-node-address", cfg.POSTService.NodeAddress, "") - cmd.PersistentFlags().StringVar(&cfg.POSTService.PostServiceMode, "post-opts-post-service-mode", - cfg.POSTService.PostServiceMode, "") - cmd.PersistentFlags().VarP(&cfg.POSTService.PowDifficulty, "post-opts-pow-difficulty", - "", "") - cmd.PersistentFlags().Uint32Var(&cfg.POSTService.K1, "post-opts-k1", - cfg.POSTService.K1, "") - cmd.PersistentFlags().Uint32Var(&cfg.POSTService.K2, "post-opts-k2", - cfg.POSTService.K2, "") - cmd.PersistentFlags().Uint32Var(&cfg.POSTService.K3, "post-opts-k3", - cfg.POSTService.K3, "") - cmd.PersistentFlags().UintVar(&cfg.POSTService.N, "post-opts-n", - cfg.POSTService.N, "") - cmd.PersistentFlags().UintVar(&cfg.POSTService.R, "post-opts-r", - cfg.POSTService.R, "") - cmd.PersistentFlags().UintVar(&cfg.POSTService.P, "post-opts-p", - cfg.POSTService.P, "") /**======================== Consensus Flags ========================== **/ diff --git a/config/config.go b/config/config.go index f2b0a028c8..f9829bdc1e 100644 --- a/config/config.go +++ b/config/config.go @@ -137,7 +137,7 @@ type SmeshingConfig struct { Start bool `mapstructure:"smeshing-start"` CoinbaseAccount string `mapstructure:"smeshing-coinbase"` Opts activation.PostSetupOpts `mapstructure:"smeshing-opts"` - ProvingOpts activation.PostProvingOpts `mapstructure:"smeshing-proving-opts"` // TODO(mafa): remove? + ProvingOpts activation.PostProvingOpts `mapstructure:"smeshing-proving-opts"` VerifyingOpts activation.PostProofVerifyingOpts `mapstructure:"smeshing-verifying-opts"` } diff --git a/config/mainnet.go b/config/mainnet.go index 09e13acf11..223f9d40f8 100644 --- a/config/mainnet.go +++ b/config/mainnet.go @@ -148,7 +148,7 @@ func MainnetConfig() Config { API: grpcserver.DefaultConfig(), TIME: timeConfig.DefaultConfig(), SMESHING: smeshing, - POSTService: activation.MainnetPostServiceConfig(), + POSTService: activation.DefaultPostServiceConfig(), FETCH: fetch.DefaultConfig(), LOGGING: logging, Sync: syncer.Config{ diff --git a/config/presets/fastnet.go b/config/presets/fastnet.go index f46ccf707b..414747e79d 100644 --- a/config/presets/fastnet.go +++ b/config/presets/fastnet.go @@ -7,6 +7,7 @@ import ( "github.com/spacemeshos/post/initialization" + "github.com/spacemeshos/go-spacemesh/activation" "github.com/spacemeshos/go-spacemesh/common/types" "github.com/spacemeshos/go-spacemesh/config" ) @@ -76,7 +77,7 @@ func fastnet() config.Config { 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.RandomXMode = "light" + conf.SMESHING.ProvingOpts.RandomXMode = activation.PostRandomXModeLight conf.Beacon.Kappa = 40 conf.Beacon.Theta = big.NewRat(1, 4) @@ -95,11 +96,5 @@ func fastnet() config.Config { conf.POET.RequestTimeout = 12 * time.Second // RequestRetryDelay * 2 * MaxRequestRetries*(MaxRequestRetries+1)/2 conf.POET.RequestRetryDelay = 1 * time.Second conf.POET.MaxRequestRetries = 3 - - conf.POSTService.N = conf.SMESHING.Opts.Scrypt.N - - conf.POSTService.K1 = conf.POST.K1 - conf.POSTService.K2 = conf.POST.K2 - conf.POSTService.K3 = conf.POST.K3 return conf } diff --git a/config/presets/standalone.go b/config/presets/standalone.go index 12f179bec6..233aa916e1 100644 --- a/config/presets/standalone.go +++ b/config/presets/standalone.go @@ -8,6 +8,7 @@ import ( "github.com/spacemeshos/post/initialization" + "github.com/spacemeshos/go-spacemesh/activation" "github.com/spacemeshos/go-spacemesh/common/types" "github.com/spacemeshos/go-spacemesh/config" ) @@ -61,7 +62,7 @@ func standalone() config.Config { conf.SMESHING.Opts.NumUnits = 1 conf.SMESHING.Opts.Throttle = true conf.SMESHING.Opts.DataDir = conf.DataDirParent - conf.SMESHING.ProvingOpts.RandomXMode = "light" + conf.SMESHING.ProvingOpts.RandomXMode = activation.PostRandomXModeLight conf.Beacon.Kappa = 40 conf.Beacon.Theta = big.NewRat(1, 4) @@ -88,10 +89,5 @@ func standalone() config.Config { conf.API.PrivateListener = "0.0.0.0:10093" conf.POSTService.NodeAddress = "http://127.0.0.1:10093" - conf.POSTService.DataDir = conf.SMESHING.Opts.DataDir - - conf.POSTService.K1 = conf.POST.K1 - conf.POSTService.K2 = conf.POST.K2 - conf.POSTService.K3 = conf.POST.K3 return conf } diff --git a/node/node.go b/node/node.go index 52f4bd8ab8..f8a2103d0d 100644 --- a/node/node.go +++ b/node/node.go @@ -554,7 +554,7 @@ func (app *App) initServices(ctx context.Context) error { nipostValidatorLogger := app.addLogger(NipostValidatorLogger, lg) postVerifiers := make([]activation.PostVerifier, 0, app.Config.SMESHING.VerifyingOpts.Workers) lg.Debug("creating post verifier") - verifier, err := activation.NewPostVerifier(app.Config.POST, nipostValidatorLogger.Zap(), verifying.WithPowFlags(app.Config.SMESHING.VerifyingOpts.Flags)) + verifier, err := activation.NewPostVerifier(app.Config.POST, nipostValidatorLogger.Zap(), verifying.WithPowFlags(app.Config.SMESHING.VerifyingOpts.Flags.Value())) lg.With().Debug("created post verifier", log.Err(err)) if err != nil { return err @@ -564,8 +564,8 @@ func (app *App) initServices(ctx context.Context) error { } app.postVerifier = activation.NewOffloadingPostVerifier(postVerifiers, nipostValidatorLogger) - if app.Config.POSTService.PostServiceCmd != "" { - app.postSupervisor, err = activation.NewPostSupervisor(app.log.Zap(), app.Config.POSTService) + if app.Config.SMESHING.Start { + app.postSupervisor, err = activation.NewPostSupervisor(app.log.Zap(), app.Config.POSTService, app.Config.POST, app.Config.SMESHING.Opts, app.Config.SMESHING.ProvingOpts) if err != nil { return fmt.Errorf("start post service: %w", err) } diff --git a/node/node_test.go b/node/node_test.go index 2c184f4c7c..53398bb165 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -427,8 +427,6 @@ func TestSpacemeshApp_NodeService(t *testing.T) { panic(err) } app.Config.POSTService.PostServiceCmd = filepath.Join(filepath.Dir(string(path)), "build", "service") - app.Config.POSTService.DataDir = app.Config.SMESHING.Opts.DataDir - app.Config.POSTService.N = app.Config.SMESHING.Opts.Scrypt.N edSgn, err := signing.NewEdSigner() require.NoError(t, err) @@ -1106,8 +1104,6 @@ func TestAdminEvents(t *testing.T) { panic(err) } cfg.POSTService.PostServiceCmd = filepath.Join(filepath.Dir(string(path)), "build", "service") - cfg.POSTService.DataDir = cfg.SMESHING.Opts.DataDir - cfg.POSTService.N = cfg.SMESHING.Opts.Scrypt.N cfg.Genesis.GenesisTime = time.Now().Add(5 * time.Second).Format(time.RFC3339) types.SetLayersPerEpoch(cfg.LayersPerEpoch) From 980711f4f5599ecbeed334f935fadccaedbe6a2d Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Mon, 9 Oct 2023 21:37:31 +0000 Subject: [PATCH 32/40] Remove obsolete parameter --- systest/cluster/nodes.go | 1 - 1 file changed, 1 deletion(-) diff --git a/systest/cluster/nodes.go b/systest/cluster/nodes.go index 19836f591b..edaec3347f 100644 --- a/systest/cluster/nodes.go +++ b/systest/cluster/nodes.go @@ -473,7 +473,6 @@ func deployNode(ctx *testcontext.Context, id string, labels map[string]string, f "-c=" + configDir + attachedSmesherConfig, "--pprof-server", "--smeshing-opts-datadir=/data/post", - "--post-opts-datadir=/data/post", "-d=/data/state", "--log-encoder=json", "--metrics", From d33e258bd6e0d0660a3e8542b303b209cbeeb201 Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Tue, 10 Oct 2023 17:07:44 +0000 Subject: [PATCH 33/40] Update post service --- Makefile-libs.Inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile-libs.Inc b/Makefile-libs.Inc index 1ebee8716c..5fa5345887 100644 --- a/Makefile-libs.Inc +++ b/Makefile-libs.Inc @@ -50,7 +50,7 @@ else endif endif -POSTRS_SETUP_REV = 0.5.0-alpha2 +POSTRS_SETUP_REV = 0.5.0-alpha3 POSTRS_SETUP_ZIP = libpost-$(platform)-v$(POSTRS_SETUP_REV).zip POSTRS_SETUP_URL_ZIP ?= https://github.com/spacemeshos/post-rs/releases/download/v$(POSTRS_SETUP_REV)/$(POSTRS_SETUP_ZIP) POSTRS_PROFILER_ZIP = profiler-$(platform)-v$(POSTRS_SETUP_REV).zip From a906dec68e3949d2ef766ac4fa43a87e6a7f8110 Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Tue, 10 Oct 2023 17:09:04 +0000 Subject: [PATCH 34/40] Remove scrypt options --- cmd/root.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index f3787bf47c..0d989b7cd8 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -256,8 +256,6 @@ func AddCommands(cmd *cobra.Command) { cmd.PersistentFlags().BoolVar(&cfg.SMESHING.Opts.Throttle, "smeshing-opts-throttle", cfg.SMESHING.Opts.Throttle, "") - // TODO(mafa): add Scrypt-Opts? - /**======================== PoST Proving Flags ========================== **/ cmd.PersistentFlags().UintVar(&cfg.SMESHING.ProvingOpts.Threads, "smeshing-opts-proving-threads", From 0a1805bd07ca7990add606150adc297e4b6ff470 Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Tue, 10 Oct 2023 17:41:52 +0000 Subject: [PATCH 35/40] Fix supervisor for windows and make restartable --- activation/e2e/nipost_test.go | 14 ++---- activation/post_supervisor.go | 60 +++++++++++++++-------- activation/post_supervisor_nix.go | 29 +++++++++++ activation/post_supervisor_test.go | 75 ++++++++++++++++++++--------- activation/post_supervisor_win.go | 29 +++++++++++ api/grpcserver/post_service_test.go | 16 ++---- config/config.go | 16 ------ config/config_nix.go | 26 ++++++++++ config/config_win.go | 26 ++++++++++ node/node.go | 5 +- 10 files changed, 214 insertions(+), 82 deletions(-) create mode 100644 activation/post_supervisor_nix.go create mode 100644 activation/post_supervisor_win.go create mode 100644 config/config_nix.go create mode 100644 config/config_win.go diff --git a/activation/e2e/nipost_test.go b/activation/e2e/nipost_test.go index 20925b7801..2fcf8efc39 100644 --- a/activation/e2e/nipost_test.go +++ b/activation/e2e/nipost_test.go @@ -3,10 +3,7 @@ package activation_test import ( "context" "errors" - "fmt" "os" - "os/exec" - "path/filepath" "testing" "time" @@ -63,13 +60,7 @@ func spawnPoet(tb testing.TB, opts ...HTTPPoetOpt) *HTTPPoetTestHarness { } func launchPostSupervisor(tb testing.TB, log *zap.Logger, cfg grpcserver.Config, postOpts activation.PostSetupOpts) func() { - path, err := exec.Command("go", "env", "GOMOD").Output() - require.NoError(tb, err) - - cmdCfg := activation.PostSupervisorConfig{ - PostServiceCmd: filepath.Join(filepath.Dir(string(path)), "build", "service"), - NodeAddress: fmt.Sprintf("http://%s", cfg.PublicListener), - } + cmdCfg := activation.DefaultTestPostServiceConfig() postCfg := activation.DefaultPostConfig() provingOpts := activation.DefaultPostProvingOpts() provingOpts.RandomXMode = activation.PostRandomXModeLight @@ -77,7 +68,8 @@ func launchPostSupervisor(tb testing.TB, log *zap.Logger, cfg grpcserver.Config, ps, err := activation.NewPostSupervisor(log, cmdCfg, postCfg, postOpts, provingOpts) require.NoError(tb, err) require.NotNil(tb, ps) - return func() { assert.NoError(tb, ps.Close()) } + require.NoError(tb, ps.Start()) + return func() { assert.NoError(tb, ps.Stop()) } } func launchServer(tb testing.TB, services ...grpcserver.ServiceAPI) (grpcserver.Config, func()) { diff --git a/activation/post_supervisor.go b/activation/post_supervisor.go index f0bb683474..5f4a00be5c 100644 --- a/activation/post_supervisor.go +++ b/activation/post_supervisor.go @@ -10,6 +10,7 @@ import ( "path/filepath" "strconv" "strings" + "sync" "sync/atomic" "go.uber.org/zap" @@ -18,14 +19,6 @@ import ( "github.com/spacemeshos/go-spacemesh/events" ) -// DefaultPostServiceConfig returns the default config for post service. These are intended for testing. -func DefaultPostServiceConfig() PostSupervisorConfig { - return PostSupervisorConfig{ - PostServiceCmd: "/bin/service", - NodeAddress: "http://127.0.0.1:9093", - } -} - type PostSupervisorConfig struct { PostServiceCmd string `mapstructure:"post-opts-post-service"` @@ -36,10 +29,16 @@ type PostSupervisorConfig struct { type PostSupervisor struct { logger *zap.Logger + cmdCfg PostSupervisorConfig + postCfg PostConfig + postOpts PostSetupOpts + provingOpts PostProvingOpts + pid atomic.Int64 // pid of the running post service, only for tests. - stop context.CancelFunc // stops the running command. + mtx sync.Mutex // protects fields below eg errgroup.Group // eg manages post service goroutines. + stop context.CancelFunc // stops the running command. } // NewPostSupervisor returns a new post service. @@ -48,19 +47,42 @@ func NewPostSupervisor(logger *zap.Logger, cmdCfg PostSupervisorConfig, postCfg return nil, fmt.Errorf("post service binary not found: %s", cmdCfg.PostServiceCmd) } - ctx, stop := context.WithCancel(context.Background()) - ps := &PostSupervisor{ - logger: logger, - stop: stop, + return &PostSupervisor{ + logger: logger, + cmdCfg: cmdCfg, + postCfg: postCfg, + postOpts: postOpts, + provingOpts: provingOpts, + }, nil +} + +func (ps *PostSupervisor) Start() error { + ps.mtx.Lock() + defer ps.mtx.Unlock() + if ps.stop != nil { + return fmt.Errorf("post service already started") } - ps.eg.Go(func() error { return ps.runCmd(ctx, cmdCfg, postCfg, postOpts, provingOpts) }) - return ps, nil + + ctx, stop := context.WithCancel(context.Background()) + ps.stop = stop + ps.eg = errgroup.Group{} // reset errgroup to allow restarts. + ps.eg.Go(func() error { return ps.runCmd(ctx, ps.cmdCfg, ps.postCfg, ps.postOpts, ps.provingOpts) }) + return nil } -func (ps *PostSupervisor) Close() error { +// Stop stops the post service. +func (ps *PostSupervisor) Stop() error { + ps.mtx.Lock() + defer ps.mtx.Unlock() + + if ps.stop == nil { + return nil + } + ps.stop() - ps.eg.Wait() - return nil + ps.stop = nil + ps.pid.Store(0) + return ps.eg.Wait() } // captureCmdOutput returns a function that reads from the given pipe and logs the output. @@ -132,7 +154,7 @@ func (ps *PostSupervisor) runCmd(ctx context.Context, cmdCfg PostSupervisorConfi if err := eg.Wait(); err != nil { ps.logger.Warn("output reading goroutine failed", zap.Error(err)) } - return ctx.Err() + return nil } ps.logger.Warn("post service exited", zap.Error(err)) eg.Wait() diff --git a/activation/post_supervisor_nix.go b/activation/post_supervisor_nix.go new file mode 100644 index 0000000000..95c1d19914 --- /dev/null +++ b/activation/post_supervisor_nix.go @@ -0,0 +1,29 @@ +//go:build !windows + +package activation + +import ( + "os/exec" + "path/filepath" +) + +// DefaultPostServiceConfig returns the default config for post service. +func DefaultPostServiceConfig() PostSupervisorConfig { + return PostSupervisorConfig{ + PostServiceCmd: "/bin/service", + NodeAddress: "http://127.0.0.1:9093", + } +} + +// DefaultTestPostServiceConfig returns the default config for post service in tests. +func DefaultTestPostServiceConfig() PostSupervisorConfig { + path, err := exec.Command("go", "env", "GOMOD").Output() + if err != nil { + panic(err) + } + + return PostSupervisorConfig{ + PostServiceCmd: filepath.Join(filepath.Dir(string(path)), "build", "service"), + NodeAddress: "http://127.0.0.1:9093", + } +} diff --git a/activation/post_supervisor_test.go b/activation/post_supervisor_test.go index ce73cb2bdb..238bf9dbbb 100644 --- a/activation/post_supervisor_test.go +++ b/activation/post_supervisor_test.go @@ -2,8 +2,6 @@ package activation import ( "os" - "os/exec" - "path/filepath" "runtime" "syscall" "testing" @@ -14,13 +12,11 @@ import ( "go.uber.org/zap/zaptest" ) -func Test_PostSupervisor_ErrOnMissingBinary(t *testing.T) { +func Test_PostSupervisor_ErrorOnMissingBinary(t *testing.T) { log := zaptest.NewLogger(t) - cmdCfg := PostSupervisorConfig{ - PostServiceCmd: filepath.Join(t.TempDir(), "service"), - NodeAddress: "http://127.0.0.1:12345", // node isn't listening and not relevant for test - } + cmdCfg := DefaultTestPostServiceConfig() + cmdCfg.PostServiceCmd = "missing" postCfg := DefaultPostConfig() postOpts := DefaultPostSetupOpts() provingOpts := DefaultPostProvingOpts() @@ -30,16 +26,25 @@ func Test_PostSupervisor_ErrOnMissingBinary(t *testing.T) { require.Nil(t, ps) } -func Test_PostSupervisor_StartsServiceCmd(t *testing.T) { +func Test_PostSupervisor_StopWithoutStart(t *testing.T) { log := zaptest.NewLogger(t) - path, err := exec.Command("go", "env", "GOMOD").Output() + cmdCfg := DefaultTestPostServiceConfig() + postCfg := DefaultPostConfig() + postOpts := DefaultPostSetupOpts() + provingOpts := DefaultPostProvingOpts() + + ps, err := NewPostSupervisor(log.Named("supervisor"), cmdCfg, postCfg, postOpts, provingOpts) require.NoError(t, err) + require.NotNil(t, ps) - cmdCfg := PostSupervisorConfig{ - PostServiceCmd: filepath.Join(filepath.Dir(string(path)), "build", "service"), - NodeAddress: "http://127.0.0.1:12345", // node isn't listening and not relevant for test - } + require.NoError(t, ps.Stop()) +} + +func Test_PostSupervisor_StartsServiceCmd(t *testing.T) { + log := zaptest.NewLogger(t) + + cmdCfg := DefaultTestPostServiceConfig() postCfg := DefaultPostConfig() postOpts := DefaultPostSetupOpts() provingOpts := DefaultPostProvingOpts() @@ -47,7 +52,9 @@ func Test_PostSupervisor_StartsServiceCmd(t *testing.T) { ps, err := NewPostSupervisor(log.Named("supervisor"), cmdCfg, postCfg, postOpts, provingOpts) require.NoError(t, err) require.NotNil(t, ps) - t.Cleanup(func() { assert.NoError(t, ps.Close()) }) + + require.NoError(t, ps.Start()) + t.Cleanup(func() { assert.NoError(t, ps.Stop()) }) require.Eventually(t, func() bool { return (ps.pid.Load() != 0) }, 5*time.Second, 100*time.Millisecond) @@ -60,23 +67,43 @@ func Test_PostSupervisor_StartsServiceCmd(t *testing.T) { require.NoError(t, process.Signal(syscall.Signal(0))) // check if process is running } - require.NoError(t, ps.Close()) + require.NoError(t, ps.Stop()) if runtime.GOOS != "windows" { require.Error(t, process.Signal(syscall.Signal(0))) // check if process is closed } } -func Test_PostSupervisor_RestartsOnCrash(t *testing.T) { +func Test_PostSupervisor_Restart_Possible(t *testing.T) { log := zaptest.NewLogger(t) - path, err := exec.Command("go", "env", "GOMOD").Output() + cmdCfg := DefaultTestPostServiceConfig() + postCfg := DefaultPostConfig() + postOpts := DefaultPostSetupOpts() + provingOpts := DefaultPostProvingOpts() + + ps, err := NewPostSupervisor(log.Named("supervisor"), cmdCfg, postCfg, postOpts, provingOpts) require.NoError(t, err) + require.NotNil(t, ps) - cmdCfg := PostSupervisorConfig{ - PostServiceCmd: filepath.Join(filepath.Dir(string(path)), "build", "service"), - NodeAddress: "http://127.0.0.1:12345", // node isn't listening and not relevant for test - } + require.NoError(t, ps.Start()) + t.Cleanup(func() { assert.NoError(t, ps.Stop()) }) + require.Eventually(t, func() bool { return (ps.pid.Load() != 0) }, 5*time.Second, 100*time.Millisecond) + + require.NoError(t, ps.Stop()) + require.Eventually(t, func() bool { return (ps.pid.Load() == 0) }, 5*time.Second, 100*time.Millisecond) + + require.NoError(t, ps.Start()) + require.Eventually(t, func() bool { return (ps.pid.Load() != 0) }, 5*time.Second, 100*time.Millisecond) + + require.NoError(t, ps.Stop()) + require.Eventually(t, func() bool { return (ps.pid.Load() == 0) }, 5*time.Second, 100*time.Millisecond) +} + +func Test_PostSupervisor_RestartsOnCrash(t *testing.T) { + log := zaptest.NewLogger(t) + + cmdCfg := DefaultTestPostServiceConfig() postCfg := DefaultPostConfig() postOpts := DefaultPostSetupOpts() provingOpts := DefaultPostProvingOpts() @@ -84,7 +111,9 @@ func Test_PostSupervisor_RestartsOnCrash(t *testing.T) { ps, err := NewPostSupervisor(log.Named("supervisor"), cmdCfg, postCfg, postOpts, provingOpts) require.NoError(t, err) require.NotNil(t, ps) - t.Cleanup(func() { assert.NoError(t, ps.Close()) }) + + require.NoError(t, ps.Start()) + t.Cleanup(func() { assert.NoError(t, ps.Stop()) }) require.Eventually(t, func() bool { return (ps.pid.Load() != 0) }, 5*time.Second, 100*time.Millisecond) @@ -102,5 +131,5 @@ func Test_PostSupervisor_RestartsOnCrash(t *testing.T) { require.NotNil(t, process) require.NotEqual(t, oldPid, pid) - require.NoError(t, ps.Close()) + require.NoError(t, ps.Stop()) } diff --git a/activation/post_supervisor_win.go b/activation/post_supervisor_win.go new file mode 100644 index 0000000000..2496243c36 --- /dev/null +++ b/activation/post_supervisor_win.go @@ -0,0 +1,29 @@ +//go:build windows + +package activation + +import ( + "os/exec" + "path/filepath" +) + +// DefaultPostServiceConfig returns the default config for post service. +func DefaultPostServiceConfig() PostSupervisorConfig { + return PostSupervisorConfig{ + PostServiceCmd: "C:\\service.exe", + NodeAddress: "http://127.0.0.1:9093", + } +} + +// DefaultTestPostServiceConfig returns the default config for post service in tests. +func DefaultTestPostServiceConfig() PostSupervisorConfig { + path, err := exec.Command("go", "env", "GOMOD").Output() + if err != nil { + panic(err) + } + + return PostSupervisorConfig{ + PostServiceCmd: filepath.Join(filepath.Dir(string(path)), "build", "service.exe"), + NodeAddress: "http://127.0.0.1:9093", + } +} diff --git a/api/grpcserver/post_service_test.go b/api/grpcserver/post_service_test.go index 6d71b47ec1..91c95883a1 100644 --- a/api/grpcserver/post_service_test.go +++ b/api/grpcserver/post_service_test.go @@ -2,9 +2,6 @@ package grpcserver import ( "context" - "fmt" - "os/exec" - "path/filepath" "testing" "time" @@ -73,21 +70,16 @@ func initPost(tb testing.TB, log *zap.Logger, opts activation.PostSetupOpts) { } func launchPostSupervisor(tb testing.TB, log *zap.Logger, cfg Config, postOpts activation.PostSetupOpts) func() { - path, err := exec.Command("go", "env", "GOMOD").Output() - require.NoError(tb, err) - - opts := activation.PostSupervisorConfig{ - PostServiceCmd: filepath.Join(filepath.Dir(string(path)), "build", "service"), - NodeAddress: fmt.Sprintf("http://%s", cfg.PublicListener), - } + cmdCfg := activation.DefaultTestPostServiceConfig() postCfg := activation.DefaultPostConfig() provingOpts := activation.DefaultPostProvingOpts() provingOpts.RandomXMode = activation.PostRandomXModeLight - ps, err := activation.NewPostSupervisor(log, opts, postCfg, postOpts, provingOpts) + ps, err := activation.NewPostSupervisor(log, cmdCfg, postCfg, postOpts, provingOpts) require.NoError(tb, err) require.NotNil(tb, ps) - return func() { assert.NoError(tb, ps.Close()) } + require.NoError(tb, ps.Start()) + return func() { assert.NoError(tb, ps.Stop()) } } func Test_GenerateProof(t *testing.T) { diff --git a/config/config.go b/config/config.go index f9829bdc1e..0ab77f7111 100644 --- a/config/config.go +++ b/config/config.go @@ -5,7 +5,6 @@ import ( "fmt" "math" "os" - "os/exec" "path/filepath" "time" @@ -168,21 +167,6 @@ func DefaultConfig() Config { } } -// DefaultTestConfig returns the default config for tests. -func DefaultTestConfig() Config { - conf := DefaultConfig() - conf.BaseConfig = defaultTestConfig() - conf.P2P = p2p.DefaultConfig() - conf.API = grpcserver.DefaultTestConfig() - - path, err := exec.Command("go", "env", "GOMOD").Output() - if err != nil { - panic(err) - } - conf.POSTService.PostServiceCmd = filepath.Join(filepath.Dir(string(path)), "build", "service") - return conf -} - // DefaultBaseConfig returns a default configuration for spacemesh. func defaultBaseConfig() BaseConfig { return BaseConfig{ diff --git a/config/config_nix.go b/config/config_nix.go new file mode 100644 index 0000000000..dd6748ea06 --- /dev/null +++ b/config/config_nix.go @@ -0,0 +1,26 @@ +//go:build !windows + +package config + +import ( + "os/exec" + "path/filepath" + + "github.com/spacemeshos/go-spacemesh/api/grpcserver" + "github.com/spacemeshos/go-spacemesh/p2p" +) + +// DefaultTestConfig returns the default config for tests. +func DefaultTestConfig() Config { + conf := DefaultConfig() + conf.BaseConfig = defaultTestConfig() + conf.P2P = p2p.DefaultConfig() + conf.API = grpcserver.DefaultTestConfig() + + path, err := exec.Command("go", "env", "GOMOD").Output() + if err != nil { + panic(err) + } + conf.POSTService.PostServiceCmd = filepath.Join(filepath.Dir(string(path)), "build", "service") + return conf +} diff --git a/config/config_win.go b/config/config_win.go new file mode 100644 index 0000000000..f64b7ff1ee --- /dev/null +++ b/config/config_win.go @@ -0,0 +1,26 @@ +//go:build windows + +package config + +import ( + "os/exec" + "path/filepath" + + "github.com/spacemeshos/go-spacemesh/api/grpcserver" + "github.com/spacemeshos/go-spacemesh/p2p" +) + +// DefaultTestConfig returns the default config for tests. +func DefaultTestConfig() Config { + conf := DefaultConfig() + conf.BaseConfig = defaultTestConfig() + conf.P2P = p2p.DefaultConfig() + conf.API = grpcserver.DefaultTestConfig() + + path, err := exec.Command("go", "env", "GOMOD").Output() + if err != nil { + panic(err) + } + conf.POSTService.PostServiceCmd = filepath.Join(filepath.Dir(string(path)), "build", "service.exe") + return conf +} diff --git a/node/node.go b/node/node.go index f8a2103d0d..9f2640cf3d 100644 --- a/node/node.go +++ b/node/node.go @@ -569,6 +569,9 @@ func (app *App) initServices(ctx context.Context) error { if err != nil { return fmt.Errorf("start post service: %w", err) } + if err := app.postSupervisor.Start(); err != nil { + return fmt.Errorf("start post service: %w", err) + } } validator := activation.NewValidator(poetDb, app.Config.POST, app.Config.SMESHING.Opts.Scrypt, app.postVerifier) @@ -1246,7 +1249,7 @@ func (app *App) stopServices(ctx context.Context) { } if app.postSupervisor != nil { - if err := app.postSupervisor.Close(); err != nil { + if err := app.postSupervisor.Stop(); err != nil { app.log.With().Error("error stopping local post service", log.Err(err)) } } From 90305db607e3286c63ee1d500d317e9f753c5614 Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Tue, 10 Oct 2023 18:25:19 +0000 Subject: [PATCH 36/40] Fix tests --- activation/e2e/nipost_test.go | 2 ++ api/grpcserver/post_service_test.go | 6 ++++-- node/node_test.go | 8 ++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/activation/e2e/nipost_test.go b/activation/e2e/nipost_test.go index 2fcf8efc39..b9b2283a2c 100644 --- a/activation/e2e/nipost_test.go +++ b/activation/e2e/nipost_test.go @@ -3,6 +3,7 @@ package activation_test import ( "context" "errors" + "fmt" "os" "testing" "time" @@ -61,6 +62,7 @@ func spawnPoet(tb testing.TB, opts ...HTTPPoetOpt) *HTTPPoetTestHarness { func launchPostSupervisor(tb testing.TB, log *zap.Logger, cfg grpcserver.Config, postOpts activation.PostSetupOpts) func() { cmdCfg := activation.DefaultTestPostServiceConfig() + cmdCfg.NodeAddress = fmt.Sprintf("http://%s", cfg.PublicListener) postCfg := activation.DefaultPostConfig() provingOpts := activation.DefaultPostProvingOpts() provingOpts.RandomXMode = activation.PostRandomXModeLight diff --git a/api/grpcserver/post_service_test.go b/api/grpcserver/post_service_test.go index 91c95883a1..835303e797 100644 --- a/api/grpcserver/post_service_test.go +++ b/api/grpcserver/post_service_test.go @@ -2,6 +2,7 @@ package grpcserver import ( "context" + "fmt" "testing" "time" @@ -71,6 +72,7 @@ func initPost(tb testing.TB, log *zap.Logger, opts activation.PostSetupOpts) { func launchPostSupervisor(tb testing.TB, log *zap.Logger, cfg Config, postOpts activation.PostSetupOpts) func() { cmdCfg := activation.DefaultTestPostServiceConfig() + cmdCfg.NodeAddress = fmt.Sprintf("http://%s", cfg.PublicListener) postCfg := activation.DefaultPostConfig() provingOpts := activation.DefaultPostProvingOpts() provingOpts.RandomXMode = activation.PostRandomXModeLight @@ -159,7 +161,7 @@ func Test_Cancel_GenerateProof(t *testing.T) { select { case <-connected: - case <-time.After(5 * time.Second): + case <-time.After(10 * time.Second): require.Fail(t, "timed out waiting for connection") } @@ -213,7 +215,7 @@ func Test_GenerateProof_MultipleServices(t *testing.T) { select { case <-connected: - case <-time.After(5 * time.Second): + case <-time.After(10 * time.Second): require.Fail(t, "timed out waiting for connection") } diff --git a/node/node_test.go b/node/node_test.go index 53398bb165..f1d685fa87 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -422,12 +422,6 @@ func TestSpacemeshApp_NodeService(t *testing.T) { app.Config.SMESHING.Opts.DataDir = t.TempDir() app.Config.SMESHING.Opts.Scrypt.N = 2 - path, err := exec.Command("go", "env", "GOMOD").Output() - if err != nil { - panic(err) - } - app.Config.POSTService.PostServiceCmd = filepath.Join(filepath.Dir(string(path)), "build", "service") - edSgn, err := signing.NewEdSigner() require.NoError(t, err) app.edSgn = edSgn @@ -1221,6 +1215,8 @@ func getTestDefaultConfig(tb testing.TB) *config.Config { cfg.Genesis = config.DefaultTestGenesisConfig() + cfg.POSTService = config.DefaultTestConfig().POSTService + types.SetLayersPerEpoch(cfg.LayersPerEpoch) return cfg From b049226abaa1a035a0cc84ce6298f63dde387c60 Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Tue, 10 Oct 2023 18:47:26 +0000 Subject: [PATCH 37/40] revert to alpha2 --- Makefile-libs.Inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile-libs.Inc b/Makefile-libs.Inc index 5fa5345887..1ebee8716c 100644 --- a/Makefile-libs.Inc +++ b/Makefile-libs.Inc @@ -50,7 +50,7 @@ else endif endif -POSTRS_SETUP_REV = 0.5.0-alpha3 +POSTRS_SETUP_REV = 0.5.0-alpha2 POSTRS_SETUP_ZIP = libpost-$(platform)-v$(POSTRS_SETUP_REV).zip POSTRS_SETUP_URL_ZIP ?= https://github.com/spacemeshos/post-rs/releases/download/v$(POSTRS_SETUP_REV)/$(POSTRS_SETUP_ZIP) POSTRS_PROFILER_ZIP = profiler-$(platform)-v$(POSTRS_SETUP_REV).zip From 6904bf8650be8f3db7d7a75fb6e6e89e81f8cee3 Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Tue, 10 Oct 2023 19:27:44 +0000 Subject: [PATCH 38/40] Fix test on windows --- node/node_test.go | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/node/node_test.go b/node/node_test.go index f1d685fa87..def43e9c5a 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -9,7 +9,6 @@ import ( "io" "net/http" "os" - "os/exec" "path/filepath" "strconv" "sync" @@ -1092,12 +1091,7 @@ func TestAdminEvents(t *testing.T) { cfg.FileLock = filepath.Join(cfg.DataDirParent, "LOCK") cfg.SMESHING.Opts.DataDir = cfg.DataDirParent cfg.SMESHING.Opts.Scrypt.N = 2 - - path, err := exec.Command("go", "env", "GOMOD").Output() - if err != nil { - panic(err) - } - cfg.POSTService.PostServiceCmd = filepath.Join(filepath.Dir(string(path)), "build", "service") + cfg.POSTService.PostServiceCmd = activation.DefaultTestPostServiceConfig().PostServiceCmd cfg.Genesis.GenesisTime = time.Now().Add(5 * time.Second).Format(time.RFC3339) types.SetLayersPerEpoch(cfg.LayersPerEpoch) From 21064a75ada70b93bde0ec692aea824baa2c723a Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Tue, 10 Oct 2023 20:28:50 +0000 Subject: [PATCH 39/40] Start and Stop smeshing via GRPC uses supervisor --- api/grpcserver/grpcserver_test.go | 141 ++++++++++++++----------- api/grpcserver/interface.go | 5 + api/grpcserver/mocks.go | 99 +++++++++++++++++ api/grpcserver/smesher_service.go | 36 +++---- api/grpcserver/smesher_service_test.go | 20 ++-- node/node.go | 2 +- 6 files changed, 216 insertions(+), 87 deletions(-) diff --git a/api/grpcserver/grpcserver_test.go b/api/grpcserver/grpcserver_test.go index cd0ac8c00e..61d65c717e 100644 --- a/api/grpcserver/grpcserver_test.go +++ b/api/grpcserver/grpcserver_test.go @@ -432,38 +432,6 @@ func newChallenge(sequence uint64, prevAtxID, posAtxID types.ATXID, epoch types. } } -// SmeshingAPIMock is a mock for Smeshing API. -type SmeshingAPIMock struct { - UpdatePoETErr error -} - -func (s *SmeshingAPIMock) UpdatePoETServers(context.Context, []string) error { - return s.UpdatePoETErr -} - -func (*SmeshingAPIMock) Smeshing() bool { - return false -} - -func (*SmeshingAPIMock) StartSmeshing(types.Address, activation.PostSetupOpts) error { - return nil -} - -func (*SmeshingAPIMock) StopSmeshing(bool) error { - return nil -} - -func (*SmeshingAPIMock) SmesherID() types.NodeID { - return signer.NodeID() -} - -func (*SmeshingAPIMock) Coinbase() types.Address { - return addr1 -} - -func (*SmeshingAPIMock) SetCoinbase(coinbase types.Address) { -} - func marshalProto(t *testing.T, msg proto.Message) []byte { buf, err := protojson.Marshal(msg) require.NoError(t, err) @@ -904,34 +872,56 @@ func TestGlobalStateService(t *testing.T) { } } -func TestSmesherService(t *testing.T) { - ctrl := gomock.NewController(t) +type smesherServiceConn struct { + pb.SmesherServiceClient + + postProvider *MockpostSetupProvider + smeshingProvider *activation.MockSmeshingProvider + postSupervisor *MockpostSupervisor +} + +func setupSmesherService(t *testing.T) (*smesherServiceConn, context.Context) { + ctrl, mockCtx := gomock.WithContext(context.Background(), t) postProvider := NewMockpostSetupProvider(ctrl) - postProvider.EXPECT().Config().Return(activation.DefaultPostConfig()).AnyTimes() - postProvider.EXPECT().Status().Return(&activation.PostSetupStatus{}).AnyTimes() - postProvider.EXPECT().Providers().Return(nil, nil).AnyTimes() - smeshingAPI := &SmeshingAPIMock{} - svc := NewSmesherService(postProvider, smeshingAPI, 10*time.Millisecond, activation.DefaultPostSetupOpts()) + smeshingProvider := activation.NewMockSmeshingProvider(ctrl) + postSupervisor := NewMockpostSupervisor(ctrl) + svc := NewSmesherService(postProvider, smeshingProvider, postSupervisor, 10*time.Millisecond, activation.DefaultPostSetupOpts()) cfg, cleanup := launchServer(t, svc) t.Cleanup(cleanup) ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() conn := dialGrpc(ctx, t, cfg.PublicListener) - c := pb.NewSmesherServiceClient(conn) + client := pb.NewSmesherServiceClient(conn) + return &smesherServiceConn{ + SmesherServiceClient: client, + + postProvider: postProvider, + smeshingProvider: smeshingProvider, + postSupervisor: postSupervisor, + }, mockCtx +} + +func TestSmesherService(t *testing.T) { t.Run("IsSmeshing", func(t *testing.T) { - res, err := c.IsSmeshing(context.Background(), &emptypb.Empty{}) + t.Parallel() + c, ctx := setupSmesherService(t) + c.smeshingProvider.EXPECT().Smeshing().Return(false) + res, err := c.IsSmeshing(ctx, &emptypb.Empty{}) require.NoError(t, err) require.False(t, res.IsSmeshing, "expected IsSmeshing to be false") }) t.Run("StartSmeshingMissingArgs", func(t *testing.T) { - _, err := c.StartSmeshing(context.Background(), &pb.StartSmeshingRequest{}) + t.Parallel() + c, ctx := setupSmesherService(t) + _, err := c.StartSmeshing(ctx, &pb.StartSmeshingRequest{}) require.Equal(t, codes.InvalidArgument, status.Code(err)) }) t.Run("StartSmeshing", func(t *testing.T) { + t.Parallel() opts := &pb.PostSetupOpts{} opts.DataDir = t.TempDir() opts.NumUnits = 1 @@ -939,7 +929,10 @@ func TestSmesherService(t *testing.T) { coinbase := &pb.AccountId{Address: addr1.String()} - res, err := c.StartSmeshing(context.Background(), &pb.StartSmeshingRequest{ + c, ctx := setupSmesherService(t) + c.smeshingProvider.EXPECT().StartSmeshing(gomock.Any(), gomock.Any()).Return(nil) + c.postSupervisor.EXPECT().Start().Return(nil) + res, err := c.StartSmeshing(ctx, &pb.StartSmeshingRequest{ Opts: opts, Coinbase: coinbase, }) @@ -948,27 +941,38 @@ func TestSmesherService(t *testing.T) { }) t.Run("StopSmeshing", func(t *testing.T) { - res, err := c.StopSmeshing(context.Background(), &pb.StopSmeshingRequest{}) + t.Parallel() + c, ctx := setupSmesherService(t) + c.smeshingProvider.EXPECT().StopSmeshing(gomock.Any()).Return(nil) + c.postSupervisor.EXPECT().Stop().Return(nil) + res, err := c.StopSmeshing(ctx, &pb.StopSmeshingRequest{}) require.NoError(t, err) require.Equal(t, int32(code.Code_OK), res.Status.Code) }) t.Run("SmesherID", func(t *testing.T) { - res, err := c.SmesherID(context.Background(), &emptypb.Empty{}) - require.NoError(t, err) + t.Parallel() + c, ctx := setupSmesherService(t) + c.smeshingProvider.EXPECT().SmesherID().Return(signer.NodeID()) + res, err := c.SmesherID(ctx, &emptypb.Empty{}) require.NoError(t, err) require.Equal(t, signer.NodeID().Bytes(), res.PublicKey) }) t.Run("SetCoinbaseMissingArgs", func(t *testing.T) { - _, err := c.SetCoinbase(context.Background(), &pb.SetCoinbaseRequest{}) + t.Parallel() + c, ctx := setupSmesherService(t) + _, err := c.SetCoinbase(ctx, &pb.SetCoinbaseRequest{}) require.Error(t, err) statusCode := status.Code(err) require.Equal(t, codes.InvalidArgument, statusCode) }) t.Run("SetCoinbase", func(t *testing.T) { - res, err := c.SetCoinbase(context.Background(), &pb.SetCoinbaseRequest{ + t.Parallel() + c, ctx := setupSmesherService(t) + c.smeshingProvider.EXPECT().SetCoinbase(addr1) + res, err := c.SetCoinbase(ctx, &pb.SetCoinbaseRequest{ Id: &pb.AccountId{Address: addr1.String()}, }) require.NoError(t, err) @@ -976,34 +980,48 @@ func TestSmesherService(t *testing.T) { }) t.Run("Coinbase", func(t *testing.T) { - res, err := c.Coinbase(context.Background(), &emptypb.Empty{}) + t.Parallel() + c, ctx := setupSmesherService(t) + c.smeshingProvider.EXPECT().Coinbase().Return(addr1) + res, err := c.Coinbase(ctx, &emptypb.Empty{}) require.NoError(t, err) addr, err := types.StringToAddress(res.AccountId.Address) require.NoError(t, err) - require.Equal(t, addr1.Bytes(), addr.Bytes()) + require.Equal(t, addr1, addr) }) t.Run("MinGas", func(t *testing.T) { - _, err := c.MinGas(context.Background(), &emptypb.Empty{}) + t.Parallel() + c, ctx := setupSmesherService(t) + _, err := c.MinGas(ctx, &emptypb.Empty{}) require.Error(t, err) statusCode := status.Code(err) require.Equal(t, codes.Unimplemented, statusCode) }) t.Run("SetMinGas", func(t *testing.T) { - _, err := c.SetMinGas(context.Background(), &pb.SetMinGasRequest{}) + t.Parallel() + c, ctx := setupSmesherService(t) + _, err := c.SetMinGas(ctx, &pb.SetMinGasRequest{}) require.Error(t, err) statusCode := status.Code(err) require.Equal(t, codes.Unimplemented, statusCode) }) t.Run("PostSetupComputeProviders", func(t *testing.T) { - _, err := c.PostSetupProviders(context.Background(), &pb.PostSetupProvidersRequest{Benchmark: false}) + t.Parallel() + c, ctx := setupSmesherService(t) + c.postProvider.EXPECT().Providers().Return(nil, nil) + _, err := c.PostSetupProviders(ctx, &pb.PostSetupProvidersRequest{Benchmark: false}) require.NoError(t, err) }) t.Run("PostSetupStatusStream", func(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) + t.Parallel() + c, ctx := setupSmesherService(t) + c.postProvider.EXPECT().Status().Return(&activation.PostSetupStatus{}).AnyTimes() + + ctx, cancel := context.WithCancel(ctx) defer cancel() stream, err := c.PostSetupStatusStream(ctx, &emptypb.Empty{}) require.NoError(t, err) @@ -1018,18 +1036,23 @@ func TestSmesherService(t *testing.T) { _, err = stream.Recv() require.ErrorContains(t, err, context.Canceled.Error()) }) + t.Run("UpdatePoetServer", func(t *testing.T) { - smeshingAPI.UpdatePoETErr = nil - res, err := c.UpdatePoetServers(context.Background(), &pb.UpdatePoetServersRequest{Urls: []string{"test"}}) + t.Parallel() + c, ctx := setupSmesherService(t) + c.smeshingProvider.EXPECT().UpdatePoETServers(gomock.Any(), gomock.Any()).Return(nil) + res, err := c.UpdatePoetServers(ctx, &pb.UpdatePoetServersRequest{Urls: []string{"test"}}) require.NoError(t, err) require.EqualValues(t, res.Status.Code, code.Code_OK) }) t.Run("UpdatePoetServerUnavailable", func(t *testing.T) { - smeshingAPI.UpdatePoETErr = activation.ErrPoetServiceUnstable + t.Parallel() + c, ctx := setupSmesherService(t) + c.smeshingProvider.EXPECT().UpdatePoETServers(gomock.Any(), gomock.Any()).Return(activation.ErrPoetServiceUnstable) urls := []string{"test"} - res, err := c.UpdatePoetServers(context.Background(), &pb.UpdatePoetServersRequest{Urls: urls}) + res, err := c.UpdatePoetServers(ctx, &pb.UpdatePoetServersRequest{Urls: urls}) require.Nil(t, res) - require.ErrorIs(t, err, status.Errorf(codes.Unavailable, "can't reach poet service (%v). retry later", smeshingAPI.UpdatePoETErr)) + require.ErrorIs(t, err, status.Errorf(codes.Unavailable, "can't reach poet service (%v). retry later", activation.ErrPoetServiceUnstable)) }) } diff --git a/api/grpcserver/interface.go b/api/grpcserver/interface.go index fbc631aa7a..6ef17af3d7 100644 --- a/api/grpcserver/interface.go +++ b/api/grpcserver/interface.go @@ -55,6 +55,11 @@ type postSetupProvider interface { Config() activation.PostConfig } +type postSupervisor interface { + Start() error + Stop() error +} + // peerCounter is an api to get amount of connected peers. type peerCounter interface { PeerCount() uint64 diff --git a/api/grpcserver/mocks.go b/api/grpcserver/mocks.go index e2700576cd..4467826ac0 100644 --- a/api/grpcserver/mocks.go +++ b/api/grpcserver/mocks.go @@ -932,6 +932,105 @@ func (c *postSetupProviderStatusCall) DoAndReturn(f func() *activation.PostSetup return c } +// MockpostSupervisor is a mock of postSupervisor interface. +type MockpostSupervisor struct { + ctrl *gomock.Controller + recorder *MockpostSupervisorMockRecorder +} + +// MockpostSupervisorMockRecorder is the mock recorder for MockpostSupervisor. +type MockpostSupervisorMockRecorder struct { + mock *MockpostSupervisor +} + +// NewMockpostSupervisor creates a new mock instance. +func NewMockpostSupervisor(ctrl *gomock.Controller) *MockpostSupervisor { + mock := &MockpostSupervisor{ctrl: ctrl} + mock.recorder = &MockpostSupervisorMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockpostSupervisor) EXPECT() *MockpostSupervisorMockRecorder { + return m.recorder +} + +// Start mocks base method. +func (m *MockpostSupervisor) Start() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Start") + ret0, _ := ret[0].(error) + return ret0 +} + +// Start indicates an expected call of Start. +func (mr *MockpostSupervisorMockRecorder) Start() *postSupervisorStartCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Start", reflect.TypeOf((*MockpostSupervisor)(nil).Start)) + return &postSupervisorStartCall{Call: call} +} + +// postSupervisorStartCall wrap *gomock.Call +type postSupervisorStartCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *postSupervisorStartCall) Return(arg0 error) *postSupervisorStartCall { + c.Call = c.Call.Return(arg0) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *postSupervisorStartCall) Do(f func() error) *postSupervisorStartCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *postSupervisorStartCall) DoAndReturn(f func() error) *postSupervisorStartCall { + c.Call = c.Call.DoAndReturn(f) + return c +} + +// Stop mocks base method. +func (m *MockpostSupervisor) Stop() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Stop") + ret0, _ := ret[0].(error) + return ret0 +} + +// Stop indicates an expected call of Stop. +func (mr *MockpostSupervisorMockRecorder) Stop() *postSupervisorStopCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Stop", reflect.TypeOf((*MockpostSupervisor)(nil).Stop)) + return &postSupervisorStopCall{Call: call} +} + +// postSupervisorStopCall wrap *gomock.Call +type postSupervisorStopCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *postSupervisorStopCall) Return(arg0 error) *postSupervisorStopCall { + c.Call = c.Call.Return(arg0) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *postSupervisorStopCall) Do(f func() error) *postSupervisorStopCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *postSupervisorStopCall) DoAndReturn(f func() error) *postSupervisorStopCall { + c.Call = c.Call.DoAndReturn(f) + return c +} + // MockpeerCounter is a mock of peerCounter interface. type MockpeerCounter struct { ctrl *gomock.Controller diff --git a/api/grpcserver/smesher_service.go b/api/grpcserver/smesher_service.go index c5129ea2a8..3bc2b724aa 100644 --- a/api/grpcserver/smesher_service.go +++ b/api/grpcserver/smesher_service.go @@ -24,6 +24,7 @@ import ( type SmesherService struct { postSetupProvider postSetupProvider smeshingProvider activation.SmeshingProvider + postSupervisor postSupervisor streamInterval time.Duration postOpts activation.PostSetupOpts @@ -35,10 +36,11 @@ func (s SmesherService) RegisterService(server *Server) { } // NewSmesherService creates a new grpc service using config data. -func NewSmesherService(post postSetupProvider, smeshing activation.SmeshingProvider, streamInterval time.Duration, postOpts activation.PostSetupOpts) *SmesherService { +func NewSmesherService(post postSetupProvider, smeshing activation.SmeshingProvider, postSupervisor postSupervisor, streamInterval time.Duration, postOpts activation.PostSetupOpts) *SmesherService { return &SmesherService{ postSetupProvider: post, smeshingProvider: smeshing, + postSupervisor: postSupervisor, streamInterval: streamInterval, postOpts: postOpts, } @@ -50,7 +52,6 @@ func (s SmesherService) IsSmeshing(context.Context, *emptypb.Empty) (*pb.IsSmesh } // StartSmeshing requests that the node begin smeshing. -// TODO(mafa): stop post supervisor. func (s SmesherService) StartSmeshing(ctx context.Context, in *pb.StartSmeshingRequest) (*pb.StartSmeshingResponse, error) { if in.Coinbase == nil { return nil, status.Errorf(codes.InvalidArgument, "`Coinbase` must be provided") @@ -87,33 +88,28 @@ func (s SmesherService) StartSmeshing(ctx context.Context, in *pb.StartSmeshingR if err != nil { return nil, fmt.Errorf("failed to parse in.Coinbase.Address `%s`: %w", in.Coinbase.Address, err) } + if err := s.postSupervisor.Start(); err != nil { + ctxzap.Error(ctx, "failed to start post supervisor", zap.Error(err)) + return nil, status.Error(codes.Internal, fmt.Sprintf("failed to start post supervisor: %v", err)) + } if err := s.smeshingProvider.StartSmeshing(coinbaseAddr, opts); err != nil { - err := fmt.Sprintf("failed to start smeshing: %v", err) - ctxzap.Error(ctx, err) - return nil, status.Error(codes.Internal, err) + ctxzap.Error(ctx, "failed to start smeshing", zap.Error(err)) + return nil, status.Error(codes.Internal, fmt.Sprintf("failed to start smeshing: %v", err)) } - return &pb.StartSmeshingResponse{ Status: &rpcstatus.Status{Code: int32(code.Code_OK)}, }, nil } // StopSmeshing requests that the node stop smeshing. -// TODO(mafa): stop post supervisor. func (s SmesherService) StopSmeshing(ctx context.Context, in *pb.StopSmeshingRequest) (*pb.StopSmeshingResponse, error) { - errchan := make(chan error, 1) - go func() { - errchan <- s.smeshingProvider.StopSmeshing(in.DeleteFiles) - }() - select { - case <-ctx.Done(): - return nil, fmt.Errorf("context done: %w", ctx.Err()) - case err := <-errchan: - if err != nil { - err := fmt.Sprintf("failed to stop smeshing: %v", err) - ctxzap.Error(ctx, err) - return nil, status.Error(codes.Internal, err) - } + if err := s.smeshingProvider.StopSmeshing(in.DeleteFiles); err != nil { + ctxzap.Error(ctx, "failed to stop smeshing", zap.Error(err)) + return nil, status.Error(codes.Internal, fmt.Sprintf("failed to stop smeshing: %v", err)) + } + if err := s.postSupervisor.Stop(); err != nil { + ctxzap.Error(ctx, "failed to stop post supervisor", zap.Error(err)) + return nil, status.Error(codes.Internal, fmt.Sprintf("failed to stop post supervisor: %v", err)) } return &pb.StopSmeshingResponse{ Status: &rpcstatus.Status{Code: int32(code.Code_OK)}, diff --git a/api/grpcserver/smesher_service_test.go b/api/grpcserver/smesher_service_test.go index 87423be59d..0c3764b6dc 100644 --- a/api/grpcserver/smesher_service_test.go +++ b/api/grpcserver/smesher_service_test.go @@ -21,8 +21,8 @@ func TestPostConfig(t *testing.T) { ctrl := gomock.NewController(t) postSetupProvider := grpcserver.NewMockpostSetupProvider(ctrl) smeshingProvider := activation.NewMockSmeshingProvider(ctrl) - - svc := grpcserver.NewSmesherService(postSetupProvider, smeshingProvider, time.Second, activation.DefaultPostSetupOpts()) + postSupervisor := grpcserver.NewMockpostSupervisor(ctrl) + svc := grpcserver.NewSmesherService(postSetupProvider, smeshingProvider, postSupervisor, time.Second, activation.DefaultPostSetupOpts()) postConfig := activation.PostConfig{ MinNumUnits: rand.Uint32(), @@ -47,7 +47,8 @@ func TestStartSmeshingPassesCorrectSmeshingOpts(t *testing.T) { ctrl := gomock.NewController(t) postSetupProvider := grpcserver.NewMockpostSetupProvider(ctrl) smeshingProvider := activation.NewMockSmeshingProvider(ctrl) - svc := grpcserver.NewSmesherService(postSetupProvider, smeshingProvider, time.Second, activation.DefaultPostSetupOpts()) + postSupervisor := grpcserver.NewMockpostSupervisor(ctrl) + svc := grpcserver.NewSmesherService(postSetupProvider, smeshingProvider, postSupervisor, time.Second, activation.DefaultPostSetupOpts()) types.SetNetworkHRP("stest") addr, err := types.StringToAddress("stest1qqqqqqrs60l66w5uksxzmaznwq6xnhqfv56c28qlkm4a5") @@ -62,6 +63,7 @@ func TestStartSmeshingPassesCorrectSmeshingOpts(t *testing.T) { ComputeBatchSize: config.DefaultComputeBatchSize, } opts.ProviderID.SetInt64(int64(providerID)) + postSupervisor.EXPECT().Start().Return(nil) smeshingProvider.EXPECT().StartSmeshing(addr, opts).Return(nil) _, err = svc.StartSmeshing(context.Background(), &pb.StartSmeshingRequest{ @@ -81,7 +83,8 @@ func TestSmesherService_PostSetupProviders(t *testing.T) { ctrl := gomock.NewController(t) postSetupProvider := grpcserver.NewMockpostSetupProvider(ctrl) smeshingProvider := activation.NewMockSmeshingProvider(ctrl) - svc := grpcserver.NewSmesherService(postSetupProvider, smeshingProvider, time.Second, activation.DefaultPostSetupOpts()) + postSupervisor := grpcserver.NewMockpostSupervisor(ctrl) + svc := grpcserver.NewSmesherService(postSetupProvider, smeshingProvider, postSupervisor, time.Second, activation.DefaultPostSetupOpts()) providers := []activation.PostSetupProvider{ { @@ -122,7 +125,8 @@ func TestSmesherService_PostSetupStatus(t *testing.T) { ctrl := gomock.NewController(t) postSetupProvider := grpcserver.NewMockpostSetupProvider(ctrl) smeshingProvider := activation.NewMockSmeshingProvider(ctrl) - svc := grpcserver.NewSmesherService(postSetupProvider, smeshingProvider, time.Second, activation.DefaultPostSetupOpts()) + postSupervisor := grpcserver.NewMockpostSupervisor(ctrl) + svc := grpcserver.NewSmesherService(postSetupProvider, smeshingProvider, postSupervisor, time.Second, activation.DefaultPostSetupOpts()) postSetupProvider.EXPECT().Status().Return(&activation.PostSetupStatus{ State: activation.PostSetupStateComplete, @@ -140,7 +144,8 @@ func TestSmesherService_PostSetupStatus(t *testing.T) { ctrl := gomock.NewController(t) postSetupProvider := grpcserver.NewMockpostSetupProvider(ctrl) smeshingProvider := activation.NewMockSmeshingProvider(ctrl) - svc := grpcserver.NewSmesherService(postSetupProvider, smeshingProvider, time.Second, activation.DefaultPostSetupOpts()) + postSupervisor := grpcserver.NewMockpostSupervisor(ctrl) + svc := grpcserver.NewSmesherService(postSetupProvider, smeshingProvider, postSupervisor, time.Second, activation.DefaultPostSetupOpts()) id := activation.PostProviderID{} id.SetInt64(1) @@ -171,7 +176,8 @@ func TestSmesherService_PostSetupStatus(t *testing.T) { ctrl := gomock.NewController(t) postSetupProvider := grpcserver.NewMockpostSetupProvider(ctrl) smeshingProvider := activation.NewMockSmeshingProvider(ctrl) - svc := grpcserver.NewSmesherService(postSetupProvider, smeshingProvider, time.Second, activation.DefaultPostSetupOpts()) + postSupervisor := grpcserver.NewMockpostSupervisor(ctrl) + svc := grpcserver.NewSmesherService(postSetupProvider, smeshingProvider, postSupervisor, time.Second, activation.DefaultPostSetupOpts()) id := activation.PostProviderID{} id.SetInt64(100) diff --git a/node/node.go b/node/node.go index 9f2640cf3d..f378e49a3c 100644 --- a/node/node.go +++ b/node/node.go @@ -1094,7 +1094,7 @@ func (app *App) initService(ctx context.Context, svc grpcserver.Service) (grpcse case grpcserver.Admin: return grpcserver.NewAdminService(app.db, app.Config.DataDir(), app.host), nil case grpcserver.Smesher: - return grpcserver.NewSmesherService(app.postSetupMgr, app.atxBuilder, app.Config.API.SmesherStreamInterval, app.Config.SMESHING.Opts), nil + return grpcserver.NewSmesherService(app.postSetupMgr, app.atxBuilder, app.postSupervisor, app.Config.API.SmesherStreamInterval, app.Config.SMESHING.Opts), nil case grpcserver.Post: return grpcserver.NewPostService(app.log.Zap(), app.nipostBuilder, app.atxBuilder), nil case grpcserver.Transaction: From 584315d8aba55a58d6a1f735ce0174e549e250c1 Mon Sep 17 00:00:00 2001 From: Matthias <5011972+fasmat@users.noreply.github.com> Date: Wed, 11 Oct 2023 13:26:48 +0000 Subject: [PATCH 40/40] Update review feedback --- activation/post_supervisor.go | 26 ++++++++++++++++++++++++++ activation/post_supervisor_nix.go | 26 +------------------------- activation/post_supervisor_win.go | 26 +------------------------- config/config.go | 10 ++++++++++ config/config_nix.go | 26 -------------------------- config/config_win.go | 26 -------------------------- 6 files changed, 38 insertions(+), 102 deletions(-) delete mode 100644 config/config_nix.go delete mode 100644 config/config_win.go diff --git a/activation/post_supervisor.go b/activation/post_supervisor.go index 5f4a00be5c..3365c1f050 100644 --- a/activation/post_supervisor.go +++ b/activation/post_supervisor.go @@ -19,6 +19,32 @@ import ( "github.com/spacemeshos/go-spacemesh/events" ) +// DefaultPostServiceConfig returns the default config for post service. +func DefaultPostServiceConfig() PostSupervisorConfig { + path, err := os.Executable() + if err != nil { + panic(err) + } + + return PostSupervisorConfig{ + PostServiceCmd: filepath.Join(filepath.Dir(path), DefaultPostServiceName), + NodeAddress: "http://127.0.0.1:9093", + } +} + +// DefaultTestPostServiceConfig returns the default config for post service in tests. +func DefaultTestPostServiceConfig() PostSupervisorConfig { + path, err := exec.Command("go", "env", "GOMOD").Output() + if err != nil { + panic(err) + } + + return PostSupervisorConfig{ + PostServiceCmd: filepath.Join(filepath.Dir(string(path)), "build", DefaultPostServiceName), + NodeAddress: "http://127.0.0.1:9093", + } +} + type PostSupervisorConfig struct { PostServiceCmd string `mapstructure:"post-opts-post-service"` diff --git a/activation/post_supervisor_nix.go b/activation/post_supervisor_nix.go index 95c1d19914..637ec40455 100644 --- a/activation/post_supervisor_nix.go +++ b/activation/post_supervisor_nix.go @@ -2,28 +2,4 @@ package activation -import ( - "os/exec" - "path/filepath" -) - -// DefaultPostServiceConfig returns the default config for post service. -func DefaultPostServiceConfig() PostSupervisorConfig { - return PostSupervisorConfig{ - PostServiceCmd: "/bin/service", - NodeAddress: "http://127.0.0.1:9093", - } -} - -// DefaultTestPostServiceConfig returns the default config for post service in tests. -func DefaultTestPostServiceConfig() PostSupervisorConfig { - path, err := exec.Command("go", "env", "GOMOD").Output() - if err != nil { - panic(err) - } - - return PostSupervisorConfig{ - PostServiceCmd: filepath.Join(filepath.Dir(string(path)), "build", "service"), - NodeAddress: "http://127.0.0.1:9093", - } -} +const DefaultPostServiceName = "service" diff --git a/activation/post_supervisor_win.go b/activation/post_supervisor_win.go index 2496243c36..99628be55c 100644 --- a/activation/post_supervisor_win.go +++ b/activation/post_supervisor_win.go @@ -2,28 +2,4 @@ package activation -import ( - "os/exec" - "path/filepath" -) - -// DefaultPostServiceConfig returns the default config for post service. -func DefaultPostServiceConfig() PostSupervisorConfig { - return PostSupervisorConfig{ - PostServiceCmd: "C:\\service.exe", - NodeAddress: "http://127.0.0.1:9093", - } -} - -// DefaultTestPostServiceConfig returns the default config for post service in tests. -func DefaultTestPostServiceConfig() PostSupervisorConfig { - path, err := exec.Command("go", "env", "GOMOD").Output() - if err != nil { - panic(err) - } - - return PostSupervisorConfig{ - PostServiceCmd: filepath.Join(filepath.Dir(string(path)), "build", "service.exe"), - NodeAddress: "http://127.0.0.1:9093", - } -} +const DefaultPostServiceName = "service.exe" diff --git a/config/config.go b/config/config.go index 0ab77f7111..322c94541b 100644 --- a/config/config.go +++ b/config/config.go @@ -167,6 +167,16 @@ func DefaultConfig() Config { } } +// DefaultTestConfig returns the default config for tests. +func DefaultTestConfig() Config { + conf := DefaultConfig() + conf.BaseConfig = defaultTestConfig() + conf.P2P = p2p.DefaultConfig() + conf.API = grpcserver.DefaultTestConfig() + conf.POSTService = activation.DefaultTestPostServiceConfig() + return conf +} + // DefaultBaseConfig returns a default configuration for spacemesh. func defaultBaseConfig() BaseConfig { return BaseConfig{ diff --git a/config/config_nix.go b/config/config_nix.go deleted file mode 100644 index dd6748ea06..0000000000 --- a/config/config_nix.go +++ /dev/null @@ -1,26 +0,0 @@ -//go:build !windows - -package config - -import ( - "os/exec" - "path/filepath" - - "github.com/spacemeshos/go-spacemesh/api/grpcserver" - "github.com/spacemeshos/go-spacemesh/p2p" -) - -// DefaultTestConfig returns the default config for tests. -func DefaultTestConfig() Config { - conf := DefaultConfig() - conf.BaseConfig = defaultTestConfig() - conf.P2P = p2p.DefaultConfig() - conf.API = grpcserver.DefaultTestConfig() - - path, err := exec.Command("go", "env", "GOMOD").Output() - if err != nil { - panic(err) - } - conf.POSTService.PostServiceCmd = filepath.Join(filepath.Dir(string(path)), "build", "service") - return conf -} diff --git a/config/config_win.go b/config/config_win.go deleted file mode 100644 index f64b7ff1ee..0000000000 --- a/config/config_win.go +++ /dev/null @@ -1,26 +0,0 @@ -//go:build windows - -package config - -import ( - "os/exec" - "path/filepath" - - "github.com/spacemeshos/go-spacemesh/api/grpcserver" - "github.com/spacemeshos/go-spacemesh/p2p" -) - -// DefaultTestConfig returns the default config for tests. -func DefaultTestConfig() Config { - conf := DefaultConfig() - conf.BaseConfig = defaultTestConfig() - conf.P2P = p2p.DefaultConfig() - conf.API = grpcserver.DefaultTestConfig() - - path, err := exec.Command("go", "env", "GOMOD").Output() - if err != nil { - panic(err) - } - conf.POSTService.PostServiceCmd = filepath.Join(filepath.Dir(string(path)), "build", "service.exe") - return conf -}