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] - Simplify switch to different poet services #6116

Closed
wants to merge 31 commits into from
Closed
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
726b49d
check registrations by poet address
ConvallariaMaj Jul 2, 2024
3f68831
Merge branch 'refs/heads/develop' into fix/issue-5563
ConvallariaMaj Jul 9, 2024
5bba175
added:
ConvallariaMaj Jul 10, 2024
8080ed0
fixed:
ConvallariaMaj Jul 11, 2024
7a371a2
fix lint
ConvallariaMaj Jul 11, 2024
89696b1
fix lint2
ConvallariaMaj Jul 11, 2024
189aa4c
- added new test
ConvallariaMaj Jul 14, 2024
97aed33
Merge branch 'refs/heads/develop' into fix/issue-5563
ConvallariaMaj Jul 14, 2024
66ea05e
make linter happy
ConvallariaMaj Jul 15, 2024
f6f2277
fixed review issues
ConvallariaMaj Jul 18, 2024
9a5bad8
refactor tests
ConvallariaMaj Jul 23, 2024
9ffb962
refactored tests
ConvallariaMaj Jul 23, 2024
c4bb081
fix text and make linter happy
ConvallariaMaj Jul 24, 2024
46ce146
fix minor issues
ConvallariaMaj Jul 29, 2024
105e872
final review issues fix
ConvallariaMaj Aug 1, 2024
11a5323
fix test
ConvallariaMaj Aug 1, 2024
0d5dfe8
Merge branch 'refs/heads/develop' into fix/issue-5563
ConvallariaMaj Aug 1, 2024
b245229
fix issues
ConvallariaMaj Aug 2, 2024
8140012
verifying poets configuration
ConvallariaMaj Aug 2, 2024
a02a90c
verifying poets configuration on poet service layer, fixing tests, fi…
ConvallariaMaj Aug 6, 2024
e910e34
test fix
ConvallariaMaj Aug 6, 2024
28f8c17
Merge branch 'refs/heads/develop' into fix/issue-5563
ConvallariaMaj Aug 6, 2024
6d12ab6
review fixes
ConvallariaMaj Aug 6, 2024
71bd472
fix lint
ConvallariaMaj Aug 6, 2024
0ea3dc1
fix merge
ConvallariaMaj Aug 6, 2024
9dc3874
fix mocks
ConvallariaMaj Aug 6, 2024
4c44a49
Fix tests
fasmat Aug 6, 2024
15ebc7b
Fix e2e tests
fasmat Aug 6, 2024
8c8945a
Merge branch 'refs/heads/develop' into fix/issue-5563
ConvallariaMaj Aug 7, 2024
2206f37
fix test
ConvallariaMaj Aug 7, 2024
f9af85a
fix test2
ConvallariaMaj Aug 7, 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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ the build folder you need to ensure that you have the gpu setup dynamic library
binary. The simplest way to do this is just copy the library file to be in the
same directory as the go-spacemesh binary. Alternatively you can modify your
system's library search paths (e.g. LD_LIBRARY_PATH) to ensure that the
library is found._
library is found.

go-spacemesh is p2p software which is designed to form a decentralized network by connecting to other instances of
go-spacemesh running on remote computers.
Expand Down
4 changes: 4 additions & 0 deletions activation/activation_errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ var (
ErrPoetServiceUnstable = &PoetSvcUnstableError{}
// ErrPoetProofNotReceived is returned when no poet proof was received.
ErrPoetProofNotReceived = errors.New("builder: didn't receive any poet proof")
// ErrNoRegistrationForGivenPoetFound is returned when there are existing registrations for given node id
// in current poet round, but for other poet services and poet round has already started.
// So poet proof will not be fetched.
ErrNoRegistrationForGivenPoetFound = errors.New("builder: no registration found for given poet set")
)

// PoetSvcUnstableError means there was a problem communicating
Expand Down
176 changes: 112 additions & 64 deletions activation/nipost.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@
"math/rand/v2"
"time"

"golang.org/x/exp/maps"

Check failure on line 11 in activation/nipost.go

View workflow job for this annotation

GitHub Actions / coverage

other declaration of maps

Check failure on line 11 in activation/nipost.go

View workflow job for this annotation

GitHub Actions / lint

other declaration of maps

Check failure on line 11 in activation/nipost.go

View workflow job for this annotation

GitHub Actions / lint

other declaration of maps

Check failure on line 11 in activation/nipost.go

View workflow job for this annotation

GitHub Actions / unittests (self-hosted, macOS, ARM64, go-spacemesh)

other declaration of maps

Check failure on line 11 in activation/nipost.go

View workflow job for this annotation

GitHub Actions / unittests (self-hosted, macOS, ARM64, go-spacemesh)

other declaration of maps

Check failure on line 11 in activation/nipost.go

View workflow job for this annotation

GitHub Actions / unittests (ubuntu-22.04)

other declaration of maps

Check failure on line 11 in activation/nipost.go

View workflow job for this annotation

GitHub Actions / unittests (ubuntu-latest-arm-8-cores)

other declaration of maps

Check failure on line 11 in activation/nipost.go

View workflow job for this annotation

GitHub Actions / unittests (macos-13)

other declaration of maps

"github.com/spacemeshos/merkle-tree"
"github.com/spacemeshos/poet/shared"
postshared "github.com/spacemeshos/post/shared"
"go.uber.org/zap"
"golang.org/x/exp/maps"

Check failure on line 17 in activation/nipost.go

View workflow job for this annotation

GitHub Actions / coverage

maps redeclared in this block

Check failure on line 17 in activation/nipost.go

View workflow job for this annotation

GitHub Actions / coverage

"golang.org/x/exp/maps" imported and not used

Check failure on line 17 in activation/nipost.go

View workflow job for this annotation

GitHub Actions / lint

maps redeclared in this block

Check failure on line 17 in activation/nipost.go

View workflow job for this annotation

GitHub Actions / lint

"golang.org/x/exp/maps" imported and not used (compile)

Check failure on line 17 in activation/nipost.go

View workflow job for this annotation

GitHub Actions / lint

maps redeclared in this block

Check failure on line 17 in activation/nipost.go

View workflow job for this annotation

GitHub Actions / lint

"golang.org/x/exp/maps" imported and not used (compile)

Check failure on line 17 in activation/nipost.go

View workflow job for this annotation

GitHub Actions / unittests (self-hosted, macOS, ARM64, go-spacemesh)

maps redeclared in this block

Check failure on line 17 in activation/nipost.go

View workflow job for this annotation

GitHub Actions / unittests (self-hosted, macOS, ARM64, go-spacemesh)

"golang.org/x/exp/maps" imported and not used

Check failure on line 17 in activation/nipost.go

View workflow job for this annotation

GitHub Actions / unittests (self-hosted, macOS, ARM64, go-spacemesh)

maps redeclared in this block

Check failure on line 17 in activation/nipost.go

View workflow job for this annotation

GitHub Actions / unittests (self-hosted, macOS, ARM64, go-spacemesh)

"golang.org/x/exp/maps" imported and not used

Check failure on line 17 in activation/nipost.go

View workflow job for this annotation

GitHub Actions / unittests (ubuntu-22.04)

maps redeclared in this block

Check failure on line 17 in activation/nipost.go

View workflow job for this annotation

GitHub Actions / unittests (ubuntu-22.04)

"golang.org/x/exp/maps" imported and not used

Check failure on line 17 in activation/nipost.go

View workflow job for this annotation

GitHub Actions / unittests (ubuntu-latest-arm-8-cores)

maps redeclared in this block

Check failure on line 17 in activation/nipost.go

View workflow job for this annotation

GitHub Actions / unittests (ubuntu-latest-arm-8-cores)

"golang.org/x/exp/maps" imported and not used

Check failure on line 17 in activation/nipost.go

View workflow job for this annotation

GitHub Actions / unittests (macos-13)

maps redeclared in this block

Check failure on line 17 in activation/nipost.go

View workflow job for this annotation

GitHub Actions / unittests (macos-13)

"golang.org/x/exp/maps" imported and not used
"golang.org/x/sync/errgroup"

"github.com/spacemeshos/go-spacemesh/activation/metrics"
Expand Down Expand Up @@ -86,8 +89,7 @@
opts ...NIPostBuilderOption,
) (*NIPostBuilder, error) {
b := &NIPostBuilder{
localDB: db,

localDB: db,
postService: postService,
logger: lg,
poetCfg: poetCfg,
Expand Down Expand Up @@ -210,7 +212,7 @@

poetRoundStart := nb.layerClock.LayerToTime((postChallenge.PublishEpoch - 1).FirstLayer()).
Add(nb.poetCfg.PhaseShift)
poetRoundEnd := nb.layerClock.LayerToTime(postChallenge.PublishEpoch.FirstLayer()).
curPoetRoundEnd := nb.layerClock.LayerToTime(postChallenge.PublishEpoch.FirstLayer()).
Add(nb.poetCfg.PhaseShift).
Add(-nb.poetCfg.CycleGap)

Expand All @@ -224,41 +226,20 @@

logger.Info("building nipost",
zap.Time("poet round start", poetRoundStart),
zap.Time("poet round end", poetRoundEnd),
zap.Time("poet round end", curPoetRoundEnd),
zap.Time("publish epoch end", publishEpochEnd),
zap.Uint32("publish epoch", postChallenge.PublishEpoch.Uint32()),
)

// Phase 0: Submit challenge to PoET services.
count, err := nipost.PoetRegistrationCount(nb.localDB, signer.NodeID())
// Deadline: start of PoET round: we will not accept registrations after that
submitedRegistrations, err := nb.submitPoetChallenges(
fasmat marked this conversation as resolved.
Show resolved Hide resolved
ctx,
signer,
poetProofDeadline,
poetRoundStart, challenge.Bytes())
poszu marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return nil, fmt.Errorf("failed to get poet registration count: %w", err)
}
if count == 0 {
now := time.Now()
// Deadline: start of PoET round for publish epoch. PoET won't accept registrations after that.
if poetRoundStart.Before(now) {
return nil, fmt.Errorf(
"%w: poet round has already started at %s (now: %s)",
ErrATXChallengeExpired,
poetRoundStart,
now,
)
}

submitCtx, cancel := context.WithDeadline(ctx, poetRoundStart)
defer cancel()
err := nb.submitPoetChallenges(submitCtx, signer, poetProofDeadline, challenge.Bytes())
if err != nil {
return nil, fmt.Errorf("submitting to poets: %w", err)
}
count, err := nipost.PoetRegistrationCount(nb.localDB, signer.NodeID())
if err != nil {
return nil, fmt.Errorf("failed to get poet registration count: %w", err)
}
if count == 0 {
return nil, &PoetSvcUnstableError{msg: "failed to submit challenge to any PoET", source: submitCtx.Err()}
}
return nil, fmt.Errorf("submitting to poets: %w", err)
}

// Phase 1: query PoET services for proofs
Expand All @@ -280,8 +261,8 @@
)
}

events.EmitPoetWaitProof(signer.NodeID(), postChallenge.PublishEpoch, poetRoundEnd)
poetProofRef, membership, err = nb.getBestProof(ctx, signer.NodeID(), challenge, postChallenge.PublishEpoch)
events.EmitPoetWaitProof(signer.NodeID(), postChallenge.PublishEpoch, curPoetRoundEnd)
poetProofRef, membership, err = nb.getBestProof(ctx, signer.NodeID(), challenge, submitedRegistrations)
if err != nil {
return nil, &PoetSvcUnstableError{msg: "getBestProof failed", source: err}
}
Expand Down Expand Up @@ -363,7 +344,7 @@
client PoetService,
prefix, challenge []byte,
signature types.EdSignature,
) error {
) (nipost.PoETRegistration, error) {
logger := nb.logger.With(
log.ZContext(ctx),
zap.String("poet", client.Address()),
Expand All @@ -377,34 +358,106 @@

round, err := client.Submit(submitCtx, deadline, prefix, challenge, signature, nodeID)
if err != nil {
return &PoetSvcUnstableError{msg: "failed to submit challenge to poet service", source: err}
return nipost.PoETRegistration{}, &PoetSvcUnstableError{msg: "failed to submit challenge to poet service", source: err}
ConvallariaMaj marked this conversation as resolved.
Show resolved Hide resolved
}
logger.Info("challenge submitted to poet proving service", zap.String("round", round.ID))
return nipost.AddPoetRegistration(nb.localDB, nodeID, nipost.PoETRegistration{

registration := nipost.PoETRegistration{
ChallengeHash: types.Hash32(challenge),
Address: client.Address(),
RoundID: round.ID,
RoundEnd: round.End,
})
}

if err := nipost.AddPoetRegistration(nb.localDB, nodeID, registration); err != nil {
return nipost.PoETRegistration{}, err
}

return registration, err
}

// Submit the challenge to all registered PoETs.
// submitPoetChallenges submit the challenge to registered PoETs
// if some registrations are missing and PoET round didn't start.
func (nb *NIPostBuilder) submitPoetChallenges(
ctx context.Context,
signer *signing.EdSigner,
deadline time.Time,
poetProofDeadline time.Time,
curPoetRoundStartDeadline time.Time,
challenge []byte,
) error {
) ([]nipost.PoETRegistration, error) {
// check if some registrations missing or were removed
nodeID := signer.NodeID()
registrations, err := nipost.PoetRegistrations(nb.localDB, nodeID)
if err != nil {
return nil, fmt.Errorf("failed to get poet registrations from db: %w", err)
}

registrationsMap := make(map[string]nipost.PoETRegistration)
for _, reg := range registrations {
registrationsMap[reg.Address] = reg
}

existingRegistrationsMap := make(map[string]nipost.PoETRegistration)
missingRegistrationsPoETAddresses := make(map[string]struct{})

for addr := range nb.poetProvers {
if val, ok := registrationsMap[addr]; ok {
existingRegistrationsMap[addr] = val
} else {
missingRegistrationsPoETAddresses[addr] = struct{}{}
}
}

existingRegistrations := maps.Values(existingRegistrationsMap)
if len(missingRegistrationsPoETAddresses) == 0 {
return existingRegistrations, nil
}
poszu marked this conversation as resolved.
Show resolved Hide resolved

now := time.Now()

if curPoetRoundStartDeadline.Before(now) {
if len(existingRegistrations) == 0 {
if len(registrations) == 0 {
// no existing registration at all, drop current registration challenge
err = ErrATXChallengeExpired
} else {
// no existing registration for given poets set
err = ErrNoRegistrationForGivenPoetFound
nb.logger.Warn("revert poet configuration to previous is needed immediately",
zap.Error(err), log.ZShortStringer("smesherID", nodeID))
}
return nil, fmt.Errorf(
"%w: poet round has already started at %s (now: %s)",
err,
curPoetRoundStartDeadline,
now,
)
fasmat marked this conversation as resolved.
Show resolved Hide resolved
}
return existingRegistrations, nil
}
fasmat marked this conversation as resolved.
Show resolved Hide resolved

// send registrations to missing addresses
signature := signer.Sign(signing.POET, challenge)
prefix := bytes.Join([][]byte{signer.Prefix(), {byte(signing.POET)}}, nil)
nodeID := signer.NodeID()
g, ctx := errgroup.WithContext(ctx)
errChan := make(chan error, len(nb.poetProvers))

submitCtx, cancel := context.WithDeadline(ctx, curPoetRoundStartDeadline)
defer cancel()

g, ctx := errgroup.WithContext(submitCtx)
fasmat marked this conversation as resolved.
Show resolved Hide resolved
errChan := make(chan error, len(missingRegistrationsPoETAddresses))
submittedRegistrations := make([]nipost.PoETRegistration, 0)

for _, client := range nb.poetProvers {
g.Go(func() error {
errChan <- nb.submitPoetChallenge(ctx, nodeID, deadline, client, prefix, challenge, signature)
return nil
})
if _, ok := missingRegistrationsPoETAddresses[client.Address()]; ok {
poszu marked this conversation as resolved.
Show resolved Hide resolved
g.Go(func() error {
registration, err := nb.submitPoetChallenge(ctx, nodeID, poetProofDeadline, client, prefix, challenge, signature)
if err == nil {
submittedRegistrations = append(submittedRegistrations, registration)
poszu marked this conversation as resolved.
Show resolved Hide resolved
}
errChan <- err
return nil
})
}
}
g.Wait()
close(errChan)
Expand All @@ -423,18 +476,15 @@
}
if allInvalid {
nb.logger.Warn("all poet submits were too late. ATX challenge expires", log.ZShortStringer("smesherID", nodeID))
return ErrATXChallengeExpired
return nil, ErrATXChallengeExpired
}
return nil
}

func (nb *NIPostBuilder) getPoetService(ctx context.Context, address string) PoetService {
for _, service := range nb.poetProvers {
if address == service.Address() {
return service
}
existingRegistrations = append(existingRegistrations, submittedRegistrations...)
if len(existingRegistrations) == 0 {
return nil, &PoetSvcUnstableError{msg: "failed to submit challenge to any PoET", source: ctx.Err()}
}
return nil

return existingRegistrations, nil
}

// membersContainChallenge verifies that the challenge is included in proof's members.
Expand All @@ -451,16 +501,12 @@
ctx context.Context,
nodeID types.NodeID,
challenge types.Hash32,
publishEpoch types.EpochID,
registrations []nipost.PoETRegistration,
) (types.PoetProofRef, *types.MerkleProof, error) {
type poetProof struct {
poet *types.PoetProof
membership *types.MerkleProof
}
registrations, err := nipost.PoetRegistrations(nb.localDB, nodeID)
if err != nil {
return types.PoetProofRef{}, nil, fmt.Errorf("getting poet registrations: %w", err)
}
proofs := make(chan *poetProof, len(registrations))

var eg errgroup.Group
Expand All @@ -471,11 +517,13 @@
zap.String("poet_address", r.Address),
zap.String("round", r.RoundID),
)
client := nb.getPoetService(ctx, r.Address)
if client == nil {

client, ok := nb.poetProvers[r.Address]
if !ok {
logger.Warn("poet client not found")
continue
}

round := r.RoundID
waitDeadline := proofDeadline(r.RoundEnd, nb.poetCfg.CycleGap)
eg.Go(func() error {
Expand Down
Loading
Loading