Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[Merged by Bors] - Refactor NIPostBuilder and activation.Builder for multiple identities. #5484

Closed
wants to merge 32 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
141a254
Refactor NIPostBuilder and activation.Builder for multiple identities.
fasmat Jan 19, 2024
bc0831d
Use stop func instead of start boolean to check if smeshing
fasmat Jan 23, 2024
5099a38
Add more tests
fasmat Jan 24, 2024
42c3966
Remove shorten utility function
fasmat Jan 24, 2024
a69fb46
Remove comment
fasmat Jan 25, 2024
102bcfc
Cleanup tests
fasmat Jan 25, 2024
4b089ec
Allow tests with multiple identities
fasmat Jan 25, 2024
eb299b0
Add tests for multi-smesher setup
fasmat Jan 29, 2024
5057547
Simplify tests
fasmat Jan 29, 2024
8730af0
Add HappyPath test for multismesher
fasmat Jan 30, 2024
95c9430
Prevent possible race
fasmat Jan 30, 2024
fe4a371
Remove unneeded assertion
fasmat Jan 30, 2024
f107041
Cleanup
fasmat Jan 30, 2024
fc5f75c
Update API
fasmat Jan 31, 2024
20b9682
Update API reference
fasmat Jan 31, 2024
ef0e6fb
Return unimplemented on deprecated GRPC call
fasmat Feb 1, 2024
cf39e02
Update api dependency
fasmat Feb 1, 2024
1a6bbae
Review feedback
fasmat Feb 1, 2024
f5be09b
Merge remote-tracking branch 'origin/develop' into 5149-multi-smesher…
fasmat Feb 1, 2024
3357261
Review feedback
fasmat Feb 1, 2024
a8b5e80
Continue reset when one ID fails
fasmat Feb 1, 2024
7fe8fc7
Review feedback
fasmat Feb 1, 2024
e040fed
Merge remote-tracking branch 'origin/develop' into 5149-multi-smesher…
fasmat Feb 1, 2024
e49d52a
Merge remote-tracking branch 'origin/develop' into 5149-multi-smesher…
fasmat Feb 2, 2024
d0fa77c
Add e2e test
fasmat Feb 2, 2024
cff5466
Merge remote-tracking branch 'origin/develop' into 5149-multi-smesher…
fasmat Feb 2, 2024
138617d
Merge remote-tracking branch 'origin/develop' into 5149-multi-smesher…
fasmat Feb 2, 2024
23cdcb5
Add e2e test for atxbuilder
fasmat Feb 2, 2024
5bdbc80
Merge remote-tracking branch 'origin/develop' into 5149-multi-smesher…
fasmat Feb 2, 2024
e06ab21
Fix issues after merge
fasmat Feb 2, 2024
8dfbcb3
Cleanup and test fixes
fasmat Feb 2, 2024
512cd65
Fix races
fasmat Feb 2, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
215 changes: 124 additions & 91 deletions activation/activation.go

Large diffs are not rendered by default.

480 changes: 480 additions & 0 deletions activation/activation_multi_test.go

Large diffs are not rendered by default.

696 changes: 381 additions & 315 deletions activation/activation_test.go

Large diffs are not rendered by default.

207 changes: 207 additions & 0 deletions activation/e2e/activation_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
package activation_test

import (
"context"
"sync"
"testing"
"time"

"github.com/spacemeshos/post/initialization"
"github.com/stretchr/testify/assert"
"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/api/grpcserver"
"github.com/spacemeshos/go-spacemesh/codec"
"github.com/spacemeshos/go-spacemesh/common/types"
"github.com/spacemeshos/go-spacemesh/datastore"
"github.com/spacemeshos/go-spacemesh/log"
"github.com/spacemeshos/go-spacemesh/p2p/pubsub"
"github.com/spacemeshos/go-spacemesh/p2p/pubsub/mocks"
"github.com/spacemeshos/go-spacemesh/signing"
"github.com/spacemeshos/go-spacemesh/sql"
"github.com/spacemeshos/go-spacemesh/sql/localsql"
"github.com/spacemeshos/go-spacemesh/timesync"
)

func Test_BuilderWithMultipleClients(t *testing.T) {
ctrl := gomock.NewController(t)

numSigners := 3
signers := make(map[types.NodeID]*signing.EdSigner, numSigners)
for i := 0; i < numSigners; i++ {
sig, err := signing.NewEdSigner()
require.NoError(t, err)

signers[sig.NodeID()] = sig
}

logger := zaptest.NewLogger(t)
goldenATX := types.ATXID{2, 3, 4}
cfg := activation.DefaultPostConfig()
db := sql.InMemory()
cdb := datastore.NewCachedDB(db, log.NewFromLog(logger))

syncer := activation.NewMocksyncer(ctrl)
syncer.EXPECT().RegisterForATXSynced().DoAndReturn(func() <-chan struct{} {
synced := make(chan struct{})
close(synced)
return synced
}).AnyTimes()

svc := grpcserver.NewPostService(logger)
grpcCfg, cleanup := launchServer(t, svc)
t.Cleanup(cleanup)

opts := activation.DefaultPostSetupOpts()
opts.ProviderID.SetUint32(initialization.CPUProviderID())
opts.Scrypt.N = 2 // Speedup initialization in tests.

var eg errgroup.Group
for _, sig := range signers {
sig := sig
opts := opts
eg.Go(func() error {
validator := activation.NewMocknipostValidator(ctrl)
mgr, err := activation.NewPostSetupManager(sig.NodeID(), cfg, logger, cdb, goldenATX, syncer, validator)
require.NoError(t, err)

opts.DataDir = t.TempDir()
initPost(t, mgr, opts)
t.Cleanup(launchPostSupervisor(t, logger, mgr, grpcCfg, opts))

require.Eventually(t, func() bool {
_, err := svc.Client(sig.NodeID())
return err == nil
}, 10*time.Second, 100*time.Millisecond, "timed out waiting for connection")
return nil
})
}
require.NoError(t, eg.Wait())

// ensure that genesis aligns with layer timings
genesis := time.Now().Add(layerDuration).Round(layerDuration)
layerDuration := 3 * time.Second
epoch := layersPerEpoch * layerDuration
poetCfg := activation.PoetConfig{
PhaseShift: epoch / 2,
CycleGap: epoch / 4,
GracePeriod: epoch / 5,
RequestTimeout: epoch / 5,
RequestRetryDelay: epoch / 50,
MaxRequestRetries: 10,
}
poetProver := spawnPoet(
t,
WithGenesis(genesis),
WithEpochDuration(epoch),
WithPhaseShift(poetCfg.PhaseShift),
WithCycleGap(poetCfg.CycleGap),
)

clock, err := timesync.NewClock(
timesync.WithGenesisTime(genesis),
timesync.WithLayerDuration(layerDuration),
timesync.WithTickInterval(100*time.Millisecond),
timesync.WithLogger(logger),
)
require.NoError(t, err)
t.Cleanup(clock.Close)

poetDb := activation.NewPoetDb(db, log.NewFromLog(logger).Named("poetDb"))

localDB := localsql.InMemory()
nb, err := activation.NewNIPostBuilder(
localDB,
poetDb,
svc,
[]types.PoetServer{{Address: poetProver.RestURL().String()}},
logger.Named("nipostBuilder"),
poetCfg,
clock,
)
require.NoError(t, err)

conf := activation.Config{
GoldenATXID: goldenATX,
RegossipInterval: 0,
}

var atxMtx sync.Mutex
atxs := make(map[types.NodeID]types.ActivationTx)
endChan := make(chan struct{})
mpub := mocks.NewMockPublisher(ctrl)
mpub.EXPECT().Publish(gomock.Any(), pubsub.AtxProtocol, gomock.Any()).DoAndReturn(
func(ctx context.Context, topic string, got []byte) error {
atxMtx.Lock()
defer atxMtx.Unlock()
var gotAtx types.ActivationTx
require.NoError(t, codec.Decode(got, &gotAtx))
atxs[gotAtx.SmesherID] = gotAtx
if len(atxs) == numSigners {
close(endChan)
}
return nil
},
).Times(numSigners)

tab := activation.NewBuilder(
conf,
cdb,
localDB,
mpub,
nb,
clock,
syncer,
logger,
activation.WithPoetConfig(poetCfg),
)
for _, sig := range signers {
tab.Register(sig)
}

require.NoError(t, tab.StartSmeshing(types.Address{}))

<-endChan

require.NoError(t, tab.StopSmeshing(false))

verifier, err := activation.NewPostVerifier(cfg, logger.Named("verifier"))
require.NoError(t, err)
t.Cleanup(func() { assert.NoError(t, verifier.Close()) })

v := activation.NewValidator(nil, poetDb, cfg, opts.Scrypt, verifier)
for _, sig := range signers {
atx := atxs[sig.NodeID()]

_, err = v.NIPost(
context.Background(),
sig.NodeID(),
*atx.CommitmentATX,
atx.NIPost,
atx.NIPostChallenge.Hash(),
atx.NumUnits,
)
require.NoError(t, err)

err := v.VRFNonce(
sig.NodeID(),
*atx.CommitmentATX,
atx.VRFNonce,
atx.NIPost.PostMetadata,
atx.NumUnits,
)
require.NoError(t, err)

require.Equal(t, postGenesisEpoch, atx.NIPostChallenge.TargetEpoch())
require.Equal(t, types.EmptyATXID, atx.NIPostChallenge.PrevATXID)
require.Equal(t, goldenATX, atx.NIPostChallenge.PositioningATX)
require.Equal(t, uint64(0), atx.NIPostChallenge.Sequence)

require.Equal(t, types.Address{}, atx.Coinbase)
require.Equal(t, sig.NodeID(), *atx.NodeID)
}
}
Loading
Loading