Skip to content

Commit

Permalink
Add PoST service to node (#5091)
Browse files Browse the repository at this point in the history
## Motivation
Part of #5042

This PR adds the GRPC API for the PoST service and adds tests verifying it works correctly.

## Changes
- PoST service is downloaded with tests and builds, as well as included in the `Dockerfile`
- `PostSetupManager` now uses `zap` directly instead of the `go-spacemesh/log` wrapper
- `grpcserver.PostService` uses the PoST service API is added to gRPCs `PrivateListener` endpoint
  - temporary, will be changed to public + authentication in the future
- Any amount of PoST services can connect to the API but only the first calling `Register` will be able to successfully create a stream
  - in the future this will be extended to allow any number of PoST services to connect
  - a successful `Register` will create a `PostClient` and notify all services that are `postConnectionListener` about the service connecting (and disconnecting)
- TODO: bundled PoST service is started when the node starts 

## Test Plan
- new tests have been added for gRPC API

## TODO
<!-- This section should be removed when all items are complete -->
- [x] Explain motivation or link existing issue(s)
- [x] Test changes and document test plan
- [x] Update documentation as needed
- [x] Update [changelog](../CHANGELOG.md) as needed
  • Loading branch information
fasmat committed Oct 6, 2023
1 parent b2b7b01 commit bdedfe1
Show file tree
Hide file tree
Showing 27 changed files with 995 additions and 64 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ See [RELEASE](./RELEASE.md) for workflow instructions.

## UNRELEASED

### Upgrade information

### Highlights

### Features

### Improvements

* [#5118](https://github.com/spacemeshos/go-spacemesh/pull/5118) reduce number of tortoise results returned after recovery.
Expand All @@ -12,6 +18,8 @@ this is hotfix for a bug introduced in v1.2.0. in rare conditions node may loop

> 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.

## v1.2.0

### Upgrade information
Expand Down Expand Up @@ -42,6 +50,7 @@ Support for old certificate sync protocol is dropped. This update is incompatibl
* [#5067](https://github.com/spacemeshos/go-spacemesh/pull/5067) dbstat virtual table can be read periodically to collect table/index sizes.

In order to enable provide following configuration:

```json
"main": {
"db-size-metering-interval": "10m"
Expand Down
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ FROM linux AS spacemesh

# Finally we copy the statically compiled Go binary.
COPY --from=builder /src/build/go-spacemesh /bin/
COPY --from=builder /src/build/service /bin/
COPY --from=builder /src/build/libpost.so /bin/
COPY --from=builder /src/build/gen-p2p-identity /bin/

Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@ install:
go install honnef.co/go/tools/cmd/[email protected]
.PHONY: install

build: go-spacemesh get-profiler
build: go-spacemesh get-profiler get-postrs-service
.PHONY: build

get-libs: get-postrs-lib
get-libs: get-postrs-lib get-postrs-service
.PHONY: get-libs

get-profiler: get-postrs-profiler
Expand Down
17 changes: 15 additions & 2 deletions Makefile-libs.Inc
Original file line number Diff line number Diff line change
Expand Up @@ -50,22 +50,28 @@ else
endif
endif

POSTRS_SETUP_REV = 0.4.4
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
POSTRS_PROFILER_URL ?= https://github.com/spacemeshos/post-rs/releases/download/v$(POSTRS_SETUP_REV)/$(POSTRS_PROFILER_ZIP)
POSTRS_SERVICE_ZIP = service-$(platform)-v$(POSTRS_SETUP_REV).zip
POSTRS_SERVICE_URL ?= https://github.com/spacemeshos/post-rs/releases/download/v$(POSTRS_SETUP_REV)/$(POSTRS_SERVICE_ZIP)

ifeq ($(platform), windows)
POSTRS_SETUP_LIBS = post.h post.dll

POSTRS_PROFILER_BIN = profiler.exe
POSTRS_SERVICE_BIN = service.exe
else
POSTRS_PROFILER_BIN = profiler
ifeq ($(platform), $(filter $(platform), macos macos-m1))
POSTRS_SETUP_LIBS = post.h libpost.dylib
else
POSTRS_SETUP_LIBS = post.h libpost.so
endif

POSTRS_PROFILER_BIN = profiler
POSTRS_SERVICE_BIN = service
endif

BINDIR_POSTRS_SETUP_LIBS = $(foreach X,$(POSTRS_SETUP_LIBS),$(BIN_DIR)$(X))
Expand All @@ -86,9 +92,16 @@ $(PROJ_DIR)$(POSTRS_SETUP_ZIP):
$(BIN_DIR)$(POSTRS_PROFILER_BIN):
curl -sSL $(CURL_OPTIONS) $(POSTRS_PROFILER_URL) -o $(PROJ_DIR)$(POSTRS_PROFILER_ZIP)
unzip -o -j $(PROJ_DIR)$(POSTRS_PROFILER_ZIP) -d $(BIN_DIR)
chmod +x $(BIN_DIR)$(POSTRS_PROFILER_BIN)

$(BIN_DIR)$(POSTRS_SERVICE_BIN):
curl -sSL $(CURL_OPTIONS) $(POSTRS_SERVICE_URL) -o $(PROJ_DIR)$(POSTRS_SERVICE_ZIP)
unzip -o -j $(PROJ_DIR)$(POSTRS_SERVICE_ZIP) -d $(BIN_DIR)
chmod +x $(BIN_DIR)$(POSTRS_SERVICE_BIN)

get-postrs-lib: $(PROJ_DIR)$(POSTRS_SETUP_ZIP) $(BINDIR_POSTRS_SETUP_LIBS)
get-postrs-profiler: $(BIN_DIR)$(POSTRS_PROFILER_BIN)
get-postrs-service: $(BIN_DIR)$(POSTRS_SERVICE_BIN)

go-env: get-postrs-lib
go env -w CGO_CFLAGS="$(CGO_CFLAGS)"
Expand Down
4 changes: 4 additions & 0 deletions activation/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,7 @@ type SmeshingProvider interface {
SetCoinbase(coinbase types.Address)
UpdatePoETServers(ctx context.Context, endpoints []string) error
}

type PostClient interface {
Proof(ctx context.Context, challenge []byte) (*types.Post, *types.PostMetadata, error)
}
63 changes: 63 additions & 0 deletions activation/mocks.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 0 additions & 4 deletions activation/nipost_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ func TestNIPostBuilderWithMocks(t *testing.T) {
}

func TestPostSetup(t *testing.T) {
t.Parallel()
r := require.New(t)

postProvider := newTestPostManager(t)
Expand Down Expand Up @@ -139,8 +138,6 @@ func TestPostSetup(t *testing.T) {
}

func TestNIPostBuilderWithClients(t *testing.T) {
t.Parallel()

challenge := types.NIPostChallenge{
PublishEpoch: postGenesisEpoch + 2,
}
Expand Down Expand Up @@ -228,7 +225,6 @@ func TestNewNIPostBuilderNotInitialized(t *testing.T) {
if testing.Short() {
t.Skip()
}
t.Parallel()

r := require.New(t)

Expand Down
56 changes: 30 additions & 26 deletions activation/post.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ 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"
"github.com/spacemeshos/go-spacemesh/datastore"
"github.com/spacemeshos/go-spacemesh/events"
"github.com/spacemeshos/go-spacemesh/log"
"github.com/spacemeshos/go-spacemesh/metrics/public"
"github.com/spacemeshos/go-spacemesh/sql"
"github.com/spacemeshos/go-spacemesh/sql/atxs"
Expand Down Expand Up @@ -94,7 +94,7 @@ type PostProviderID struct {
}

// String implements pflag.Value.String.
func (id *PostProviderID) String() string {
func (id PostProviderID) String() string {
if id.value == nil {
return ""
}
Expand Down Expand Up @@ -244,7 +244,7 @@ type PostSetupManager struct {
commitmentAtxId types.ATXID

cfg PostConfig
logger log.Log
logger *zap.Logger
db *datastore.CachedDB
goldenATXID types.ATXID

Expand All @@ -256,7 +256,7 @@ type PostSetupManager struct {
}

// NewPostSetupManager creates a new instance of PostSetupManager.
func NewPostSetupManager(id types.NodeID, cfg PostConfig, logger log.Log, 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, provingOpts PostProvingOpts) (*PostSetupManager, error) {
mgr := &PostSetupManager{
id: id,
cfg: cfg,
Expand Down Expand Up @@ -358,13 +358,13 @@ func (mgr *PostSetupManager) StartSession(ctx context.Context) error {
if err != nil {
return err
}
mgr.logger.With().Info("post setup session starting",
log.String("node_id", mgr.id.String()),
log.String("commitment_atx", mgr.commitmentAtxId.String()),
log.String("data_dir", mgr.lastOpts.DataDir),
log.String("num_units", fmt.Sprintf("%d", mgr.lastOpts.NumUnits)),
log.String("labels_per_unit", fmt.Sprintf("%d", mgr.cfg.LabelsPerUnit)),
log.String("provider", fmt.Sprintf("%d", mgr.lastOpts.ProviderID)),
mgr.logger.Info("post setup session starting",
zap.Stringer("node_id", mgr.id),
zap.Stringer("commitment_atx", mgr.commitmentAtxId),
zap.String("data_dir", mgr.lastOpts.DataDir),
zap.Uint32("num_units", mgr.lastOpts.NumUnits),
zap.Uint64("labels_per_unit", mgr.cfg.LabelsPerUnit),
zap.Stringer("provider", mgr.lastOpts.ProviderID),
)
public.InitStart.Set(float64(mgr.lastOpts.NumUnits))
events.EmitInitStart(mgr.id, mgr.commitmentAtxId)
Expand All @@ -379,26 +379,26 @@ func (mgr *PostSetupManager) StartSession(ctx context.Context) error {
mgr.state = PostSetupStateStopped
return err
case errors.As(err, &errLabelMismatch):
mgr.logger.With().Error("post setup session failed due to an issue with the initialization provider", log.Err(errLabelMismatch))
mgr.logger.Error("post setup session failed due to an issue with the initialization provider", zap.Error(errLabelMismatch))
mgr.state = PostSetupStateError
events.EmitInitFailure(mgr.id, mgr.commitmentAtxId, errLabelMismatch)
return nil
case err != nil:
mgr.logger.With().Error("post setup session failed", log.Err(err))
mgr.logger.Error("post setup session failed", zap.Error(err))
mgr.state = PostSetupStateError
events.EmitInitFailure(mgr.id, mgr.commitmentAtxId, err)
return err
}
public.InitEnd.Set(float64(mgr.lastOpts.NumUnits))
events.EmitInitComplete()

mgr.logger.With().Info("post setup completed",
log.String("node_id", mgr.id.String()),
log.String("commitment_atx", mgr.commitmentAtxId.String()),
log.String("data_dir", mgr.lastOpts.DataDir),
log.String("num_units", fmt.Sprintf("%d", mgr.lastOpts.NumUnits)),
log.String("labels_per_unit", fmt.Sprintf("%d", mgr.cfg.LabelsPerUnit)),
log.String("provider", fmt.Sprintf("%d", mgr.lastOpts.ProviderID)),
mgr.logger.Info("post setup completed",
zap.Stringer("node_id", mgr.id),
zap.Stringer("commitment_atx", mgr.commitmentAtxId),
zap.String("data_dir", mgr.lastOpts.DataDir),
zap.Uint32("num_units", mgr.lastOpts.NumUnits),
zap.Uint64("labels_per_unit", mgr.cfg.LabelsPerUnit),
zap.Stringer("provider", mgr.lastOpts.ProviderID),
)
mgr.state = PostSetupStateComplete
return nil
Expand All @@ -420,15 +420,19 @@ func (mgr *PostSetupManager) PrepareInitializer(ctx context.Context, opts PostSe

// TODO(mafa): remove this, see https://github.com/spacemeshos/go-spacemesh/issues/4801
if opts.ProviderID.Value() != nil && *opts.ProviderID.Value() == -1 {
mgr.logger.Warning("DEPRECATED: auto-determining compute provider is deprecated, please specify a valid provider ID in the config file")
mgr.logger.Warn("DEPRECATED: auto-determining compute provider is deprecated, please specify a valid provider ID in the config file")

p, err := mgr.BestProvider()
if err != nil {
return err
}

mgr.logger.Warning("DEPRECATED: found best compute provider: id: %d, model: %v, device type: %v", p.ID, p.Model, p.DeviceType)
mgr.logger.Warning("DEPRECATED: please update your config file: {\"smeshing\": {\"smeshing-opts\": {\"smeshing-opts-provider\": %d }}}", p.ID)
mgr.logger.Warn("DEPRECATED: found best compute provider",
zap.Uint32("id", p.ID),
zap.String("model", p.Model),
zap.Stringer("device type", p.DeviceType),
)
mgr.logger.Sugar().Warnf("DEPRECATED: please update your config file: {\"smeshing\": {\"smeshing-opts\": {\"smeshing-opts-provider\": %d }}}", p.ID)
opts.ProviderID.SetInt64(int64(p.ID))
}

Expand All @@ -443,7 +447,7 @@ func (mgr *PostSetupManager) PrepareInitializer(ctx context.Context, opts PostSe
initialization.WithCommitmentAtxId(mgr.commitmentAtxId.Bytes()),
initialization.WithConfig(mgr.cfg.ToConfig()),
initialization.WithInitOpts(opts.ToInitOpts()),
initialization.WithLogger(mgr.logger.Zap()),
initialization.WithLogger(mgr.logger),
)
if err != nil {
mgr.state = PostSetupStateError
Expand Down Expand Up @@ -499,7 +503,7 @@ func (mgr *PostSetupManager) findCommitmentAtx(ctx context.Context) (types.ATXID
atx, err := atxs.GetIDWithMaxHeight(mgr.db, types.EmptyNodeID)
switch {
case errors.Is(err, sql.ErrNotFound):
mgr.logger.With().Info("using golden atx as commitment atx")
mgr.logger.Info("using golden atx as commitment atx")
return mgr.goldenATXID, nil
case err != nil:
return types.EmptyATXID, fmt.Errorf("get commitment atx: %w", err)
Expand Down Expand Up @@ -540,7 +544,7 @@ func (mgr *PostSetupManager) GenerateProof(ctx context.Context, challenge []byte
}
opts = append(opts, options...)

proof, proofMetadata, err := proving.Generate(ctx, challenge, mgr.cfg.ToConfig(), mgr.logger.Zap(), opts...)
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)
}
Expand Down
Loading

0 comments on commit bdedfe1

Please sign in to comment.