From 7ec17279163f4ed69738806439c0ddf8da0fb76c Mon Sep 17 00:00:00 2001 From: Kacper Sawicki Date: Wed, 13 Nov 2024 16:53:50 +0100 Subject: [PATCH 1/8] Add smeshing identities endpoint (based on #6266) add post, poet and atx states --- activation/activation.go | 17 ++ activation/identity_states.go | 197 ++++++++++++++++++ activation/interface.go | 6 + activation/nipost.go | 60 ++++-- api/grpcserver/config.go | 49 ++--- api/grpcserver/v2alpha1/interface.go | 9 + .../v2alpha1/smeshing_identities.go | 108 ++++++++++ go.mod | 12 +- go.sum | 24 +-- node/node.go | 23 +- 10 files changed, 448 insertions(+), 57 deletions(-) create mode 100644 activation/identity_states.go create mode 100644 api/grpcserver/v2alpha1/smeshing_identities.go diff --git a/activation/activation.go b/activation/activation.go index 46f7d9ae34..8357b52afb 100644 --- a/activation/activation.go +++ b/activation/activation.go @@ -102,6 +102,9 @@ type Builder struct { // states of each known identity postStates PostStates + // identity states of each known identity + identitiesStates IdentityStates + // smeshingMutex protects methods like `StartSmeshing` and `StopSmeshing` from concurrent execution // since they (can) modify the fields below. smeshingMutex sync.Mutex @@ -158,6 +161,12 @@ func WithPostStates(ps PostStates) BuilderOption { } } +func WithIdentityStates(is IdentityStates) BuilderOption { + return func(b *Builder) { + b.identitiesStates = is + } +} + func BuilderAtxVersions(v AtxVersions) BuilderOption { return func(h *Builder) { h.versions = append([]atxVersion{{0, types.AtxV1}}, v.asSlice()...) @@ -191,6 +200,7 @@ func NewBuilder( logger: log, poetRetryInterval: defaultPoetRetryInterval, postStates: NewPostStates(log), + identitiesStates: NewIdentityStateStorage(), versions: []atxVersion{{0, types.AtxV1}}, posAtxFinder: positioningAtxFinder{ logger: log, @@ -498,6 +508,8 @@ func (b *Builder) run(ctx context.Context, sig *signing.EdSigner) { func (b *Builder) BuildNIPostChallenge(ctx context.Context, nodeID types.NodeID) (*types.NIPostChallenge, error) { logger := b.logger.With(log.ZShortStringer("smesherID", nodeID)) + b.identitiesStates.Set(nodeID, nil, IdentityStateWaitForATXSyncing, "") + select { case <-ctx.Done(): return nil, ctx.Err() @@ -551,6 +563,7 @@ func (b *Builder) BuildNIPostChallenge(ctx context.Context, nodeID types.NodeID) ) events.EmitPoetWaitRound(nodeID, currentEpochId, publishEpochId, wait) events.EmitWaitingForPoETRegistrationWindow(nodeID, currentEpochId, publishEpochId, wait) + b.identitiesStates.Set(nodeID, &publishEpochId, IdentityStateWaitingForPoetRegistrationWindow, "") select { case <-ctx.Done(): return nil, ctx.Err() @@ -715,6 +728,8 @@ func (b *Builder) PublishActivationTx(ctx context.Context, sig *signing.EdSigner zap.Uint32("current_epoch", b.layerClock.CurrentLayer().GetEpoch().Uint32()), zap.Object("challenge", challenge), ) + b.identitiesStates.Set(sig.NodeID(), &challenge.PublishEpoch, IdentityStatePoetChallengeReady, "") + targetEpoch := challenge.PublishEpoch.Add(1) ctx, cancel := context.WithDeadline(ctx, b.layerClock.LayerToTime(targetEpoch.FirstLayer())) defer cancel() @@ -729,6 +744,7 @@ func (b *Builder) PublishActivationTx(ctx context.Context, sig *signing.EdSigner zap.Uint32("current_layer", b.layerClock.CurrentLayer().Uint32()), log.ZShortStringer("smesherID", sig.NodeID()), ) + b.identitiesStates.Set(sig.NodeID(), &challenge.PublishEpoch, IdentityStateATXReady, "") select { case <-ctx.Done(): return fmt.Errorf("wait for publication epoch: %w", ctx.Err()) @@ -774,6 +790,7 @@ func (b *Builder) PublishActivationTx(ctx context.Context, sig *signing.EdSigner atx.ID(), b.layerClock.LayerToTime(target.FirstLayer()), ) + b.identitiesStates.Set(sig.NodeID(), &challenge.PublishEpoch, IdentityStateATXBroadcasted, "") return nil } diff --git a/activation/identity_states.go b/activation/identity_states.go new file mode 100644 index 0000000000..66f3270b6c --- /dev/null +++ b/activation/identity_states.go @@ -0,0 +1,197 @@ +package activation + +import ( + "errors" + "fmt" + "sync" + "time" + + "github.com/spacemeshos/go-spacemesh/common/types" +) + +var ( + ErrIdentityStateUnknown = errors.New("identity state is unknown") + ErrInvalidIdentityStateSwitch = errors.New("invalid identity state switch") +) + +type IdentityState int + +const ( + IdentityStateNotSet IdentityState = iota + + IdentityStateWaitForATXSyncing + + // poet + IdentityStateWaitingForPoetRegistrationWindow + // building nipost challenge + IdentityStatePoetChallengeReady + IdentityStatePoetRegistered + IdentityStatePoetRegistrationFailed + // 2w pass ... + IdentityStateWaitForPoetRoundEnd + IdentityStatePoetProofReceived + IdentityStatePoetProofFailed + + // post + IdentityStateGeneratingPostProof + IdentityStatePostProofReady + IdentityStatePostProofFailed + + // atx + IdentityStateATXExpired + IdentityStateATXReady + IdentityStateATXBroadcasted +) + +func (s IdentityState) String() string { + switch s { + case IdentityStateNotSet: + return "not set" + case IdentityStateWaitForATXSyncing: + return "wait for atx syncing" + case IdentityStatePoetChallengeReady: + return "poet challenge ready" + case IdentityStateWaitingForPoetRegistrationWindow: + return "waiting for poet registration window" + case IdentityStatePoetRegistered: + return "poet registered" + case IdentityStateWaitForPoetRoundEnd: + return "wait for poet round end" + case IdentityStatePoetProofReceived: + return "poet proof received" + case IdentityStatePoetProofFailed: + return "poet proof failed" + case IdentityStateGeneratingPostProof: + return "generating post proof" + case IdentityStatePostProofReady: + return "post proof ready" + case IdentityStatePostProofFailed: + return "post proof failed" + case IdentityStateATXReady: + return "atx ready" + case IdentityStateATXBroadcasted: + return "atx broadcasted" + default: + panic(fmt.Sprintf(ErrIdentityStateUnknown.Error()+" %d", s)) + } +} + +type IdentityStateInfo struct { + Message string + Time time.Time +} + +type IdentityInfo struct { + PublishEpoch types.EpochID + States map[IdentityState]IdentityStateInfo +} + +type Identity struct { + EpochStates map[types.EpochID]*IdentityInfo + States map[IdentityState]IdentityStateInfo +} + +type IdentityStateStorage struct { + mu sync.RWMutex + identities map[types.NodeID]*Identity +} + +func NewIdentityStateStorage() *IdentityStateStorage { + return &IdentityStateStorage{ + identities: make(map[types.NodeID]*Identity), + } +} + +// TODO: validate state switch +//var validStateSwitch = map[IdentityState][]IdentityState{ +// IdentityStateWaitForATXSyncing: { +// IdentityStateWaitForPoetRoundStart, +// }, +// IdentityStatePostProving: { +// IdentityStateWaitForPoetRoundStart, +// }, +// IdentityStateWaitForPoetRoundStart: { +// IdentityStateWaitForPoetRoundEnd, +// IdentityStateWaitForATXSyncing, +// }, +// IdentityStateWaitForPoetRoundEnd: { +// IdentityStateFetchingProofs, +// IdentityStateWaitForPoetRoundStart, +// }, +// IdentityStateFetchingProofs: { +// IdentityStatePostProving, +// IdentityStateWaitForPoetRoundStart, +// }, +//} + +func (s *IdentityStateStorage) Set(id types.NodeID, publishEpoch *types.EpochID, newState IdentityState, message string) { + s.mu.Lock() + defer s.mu.Unlock() + + if _, exists := s.identities[id]; !exists { + s.identities[id] = &Identity{ + EpochStates: map[types.EpochID]*IdentityInfo{}, + States: map[IdentityState]IdentityStateInfo{}, + } + } + + if publishEpoch != nil { + if _, exists := s.identities[id].EpochStates[*publishEpoch]; !exists { + s.identities[id].EpochStates[*publishEpoch] = &IdentityInfo{ + PublishEpoch: *publishEpoch, + States: make(map[IdentityState]IdentityStateInfo), + } + } + s.identities[id].EpochStates[*publishEpoch].States[newState] = IdentityStateInfo{ + Time: time.Now(), + Message: message, + } + } else { + s.identities[id].States[newState] = IdentityStateInfo{ + Time: time.Now(), + Message: message, + } + } + // TODO: validate state switch + //currentState, exists := s.states[id] + //switch { + //case !exists: + // if newState == IdentityStateWaitForATXSyncing { + // s.states[id] = newState + // return nil + // } + //case currentState == newState: + // return nil + // + //default: + // if validNextStates, ok := validStateSwitch[currentState]; ok && + // slices.Contains(validNextStates, newState) { + // s.states[id] = newState + // return nil + // } + //} + // + //return fmt.Errorf( + // "%w: state %v can't be switched to %v", + // ErrInvalidIdentityStateSwitch, + // currentState, + // newState, + //) +} + +func (s *IdentityStateStorage) Get(id types.NodeID) (*Identity, error) { + s.mu.RLock() + defer s.mu.RUnlock() + + state, exists := s.identities[id] + if !exists { + return nil, ErrIdentityStateUnknown + } + return state, nil +} + +func (s *IdentityStateStorage) All() map[types.NodeID]*Identity { + s.mu.RLock() + defer s.mu.RUnlock() + return s.identities +} diff --git a/activation/interface.go b/activation/interface.go index 1593f7adaf..6587108e1f 100644 --- a/activation/interface.go +++ b/activation/interface.go @@ -232,3 +232,9 @@ type PostStates interface { Set(id types.NodeID, state types.PostState) Get() map[types.NodeID]types.PostState } + +type IdentityStates interface { + Set(id types.NodeID, publishEpoch *types.EpochID, newState IdentityState, message string) + Get(id types.NodeID) (*Identity, error) + All() map[types.NodeID]*Identity +} diff --git a/activation/nipost.go b/activation/nipost.go index 6d87393a17..17c6d1acca 100644 --- a/activation/nipost.go +++ b/activation/nipost.go @@ -49,13 +49,14 @@ var ErrInvalidInitialPost = errors.New("invalid initial post") type NIPostBuilder struct { localDB sql.LocalDatabase - poetProvers map[string]PoetService - postService postService - logger *zap.Logger - poetCfg PoetConfig - layerClock layerClock - postStates PostStates - validator nipostValidator + poetProvers map[string]PoetService + postService postService + logger *zap.Logger + poetCfg PoetConfig + layerClock layerClock + postStates PostStates + validator nipostValidator + identityStates IdentityStates } type NIPostBuilderOption func(*NIPostBuilder) @@ -75,6 +76,12 @@ func NipostbuilderWithPostStates(ps PostStates) NIPostBuilderOption { } } +func NipostbuilderWithIdentityStates(is IdentityStates) NIPostBuilderOption { + return func(nb *NIPostBuilder) { + nb.identityStates = is + } +} + // NewNIPostBuilder returns a NIPostBuilder. func NewNIPostBuilder( db sql.LocalDatabase, @@ -86,13 +93,14 @@ func NewNIPostBuilder( opts ...NIPostBuilderOption, ) (*NIPostBuilder, error) { b := &NIPostBuilder{ - localDB: db, - postService: postService, - logger: lg, - poetCfg: poetCfg, - layerClock: layerClock, - postStates: NewPostStates(lg), - validator: validator, + localDB: db, + postService: postService, + logger: lg, + poetCfg: poetCfg, + layerClock: layerClock, + postStates: NewPostStates(lg), + validator: validator, + identityStates: NewIdentityStateStorage(), } for _, opt := range opts { @@ -239,6 +247,8 @@ func (nb *NIPostBuilder) BuildNIPost( regErr := &PoetRegistrationMismatchError{} switch { case errors.As(err, ®Err): + nb.identityStates.Set(signer.NodeID(), &postChallenge.PublishEpoch, IdentityStatePoetRegistrationFailed, + regErr.Error()) logger.Fatal( "None of the poets listed in the config matches the existing registrations. "+ "Verify your config and local database state.", @@ -247,9 +257,12 @@ func (nb *NIPostBuilder) BuildNIPost( ) return nil, err case err != nil: + nb.identityStates.Set(signer.NodeID(), &postChallenge.PublishEpoch, IdentityStatePoetRegistrationFailed, + err.Error()) return nil, fmt.Errorf("submitting to poets: %w", err) } + nb.identityStates.Set(signer.NodeID(), &postChallenge.PublishEpoch, IdentityStatePoetRegistered, "") // Phase 1: query PoET services for proofs poetProofRef, membership, err := nipost.PoetProofRef(nb.localDB, signer.NodeID()) if err != nil && !errors.Is(err, sql.ErrNotFound) { @@ -260,6 +273,11 @@ func (nb *NIPostBuilder) BuildNIPost( // Deadline: the end of the publish epoch minus the cycle gap. A node that is setup correctly (i.e. can // generate a PoST proof within the cycle gap) has enough time left to generate a post proof and publish. if poetProofDeadline.Before(now) { + nb.identityStates.Set(signer.NodeID(), &postChallenge.PublishEpoch, IdentityStateATXExpired, fmt.Sprintf( + "deadline to query poet proof for pub epoch %d exceeded (deadline: %s, now: %s)", + postChallenge.PublishEpoch, + poetProofDeadline, + now)) return nil, fmt.Errorf( "%w: deadline to query poet proof for pub epoch %d exceeded (deadline: %s, now: %s)", ErrATXChallengeExpired, @@ -271,16 +289,21 @@ func (nb *NIPostBuilder) BuildNIPost( events.EmitPoetWaitProof(signer.NodeID(), postChallenge.PublishEpoch, curPoetRoundEnd) events.EmitWaitingForPoETRoundEnd(signer.NodeID(), postChallenge.PublishEpoch, curPoetRoundEnd) + nb.identityStates.Set(signer.NodeID(), &postChallenge.PublishEpoch, IdentityStateWaitForPoetRoundEnd, "") + poetProofRef, membership, err = nb.getBestProof(ctx, signer.NodeID(), challenge, submittedRegistrations) if err != nil { return nil, &PoetSvcUnstableError{msg: "getBestProof failed", source: err} } if poetProofRef == types.EmptyPoetProofRef { + nb.identityStates.Set(signer.NodeID(), &postChallenge.PublishEpoch, IdentityStatePoetProofFailed, + "poet proof not received") return nil, &PoetSvcUnstableError{source: ErrPoetProofNotReceived} } if err := nipost.UpdatePoetProofRef(nb.localDB, signer.NodeID(), poetProofRef, membership); err != nil { nb.logger.Warn("cannot persist poet proof ref", zap.Error(err)) } + nb.identityStates.Set(signer.NodeID(), &postChallenge.PublishEpoch, IdentityStatePoetProofReceived, "") } // Phase 2: Post execution. @@ -293,6 +316,11 @@ func (nb *NIPostBuilder) BuildNIPost( // Deadline: the end of the publish epoch. If we do not publish within // the publish epoch we won't receive any rewards in the target epoch. if publishEpochEnd.Before(now) { + nb.identityStates.Set(signer.NodeID(), &postChallenge.PublishEpoch, IdentityStateATXExpired, fmt.Sprintf( + "deadline to publish ATX for pub epoch %d exceeded (deadline: %s, now: %s)", + postChallenge.PublishEpoch, + publishEpochEnd, + now)) return nil, fmt.Errorf( "%w: deadline to publish ATX for pub epoch %d exceeded (deadline: %s, now: %s)", ErrATXChallengeExpired, @@ -305,12 +333,16 @@ func (nb *NIPostBuilder) BuildNIPost( defer cancel() nb.logger.Info("starting post execution", zap.Binary("challenge", poetProofRef[:])) + nb.identityStates.Set(signer.NodeID(), &postChallenge.PublishEpoch, IdentityStateGeneratingPostProof, "") startTime := time.Now() proof, postInfo, err := nb.Proof(postCtx, signer.NodeID(), poetProofRef[:], postChallenge) if err != nil { + nb.identityStates.Set(signer.NodeID(), &postChallenge.PublishEpoch, IdentityStatePostProofFailed, + fmt.Sprintf("failed to generate Post: %v", err)) return nil, fmt.Errorf("failed to generate Post: %w", err) } + nb.identityStates.Set(signer.NodeID(), &postChallenge.PublishEpoch, IdentityStatePostProofReady, "") postGenDuration := time.Since(startTime) diff --git a/api/grpcserver/config.go b/api/grpcserver/config.go index ac271d2a74..d55862c0d2 100644 --- a/api/grpcserver/config.go +++ b/api/grpcserver/config.go @@ -32,29 +32,30 @@ type Config struct { type Service = string const ( - Admin Service = "admin" - Debug Service = "debug" - GlobalState Service = "global" - Mesh Service = "mesh" - Transaction Service = "transaction" - Activation Service = "activation" - Smesher Service = "smesher" - Post Service = "post" - PostInfo Service = "postInfo" - Node Service = "node" - ActivationV2Alpha1 Service = "activation_v2alpha1" - ActivationStreamV2Alpha1 Service = "activation_stream_v2alpha1" - RewardV2Alpha1 Service = "reward_v2alpha1" - RewardStreamV2Alpha1 Service = "reward_stream_v2alpha1" - NetworkV2Alpha1 Service = "network_v2alpha1" - NodeV2Alpha1 Service = "node_v2alpha1" - LayerV2Alpha1 Service = "layer_v2alpha1" - LayerStreamV2Alpha1 Service = "layer_stream_v2alpha1" - TransactionV2Alpha1 Service = "transaction_v2alpha1" - TransactionStreamV2Alpha1 Service = "transaction_stream_v2alpha1" - AccountV2Alpha1 Service = "account_v2alpha1" - MalfeasanceV2Alpha1 Service = "malfeasance_v2alpha1" - MalfeasanceStreamV2Alpha1 Service = "malfeasance_stream_v2alpha1" + Admin Service = "admin" + Debug Service = "debug" + GlobalState Service = "global" + Mesh Service = "mesh" + Transaction Service = "transaction" + Activation Service = "activation" + Smesher Service = "smesher" + Post Service = "post" + PostInfo Service = "postInfo" + Node Service = "node" + ActivationV2Alpha1 Service = "activation_v2alpha1" + ActivationStreamV2Alpha1 Service = "activation_stream_v2alpha1" + RewardV2Alpha1 Service = "reward_v2alpha1" + RewardStreamV2Alpha1 Service = "reward_stream_v2alpha1" + NetworkV2Alpha1 Service = "network_v2alpha1" + NodeV2Alpha1 Service = "node_v2alpha1" + LayerV2Alpha1 Service = "layer_v2alpha1" + LayerStreamV2Alpha1 Service = "layer_stream_v2alpha1" + TransactionV2Alpha1 Service = "transaction_v2alpha1" + TransactionStreamV2Alpha1 Service = "transaction_stream_v2alpha1" + AccountV2Alpha1 Service = "account_v2alpha1" + MalfeasanceV2Alpha1 Service = "malfeasance_v2alpha1" + MalfeasanceStreamV2Alpha1 Service = "malfeasance_stream_v2alpha1" + SmeshingIdentitiesV2Alpha1 Service = "smeshing_identities_v2alpha1" ) // DefaultConfig defines the default configuration options for api. @@ -63,7 +64,7 @@ func DefaultConfig() Config { PublicServices: []Service{ GlobalState, Mesh, Transaction, Node, Activation, ActivationV2Alpha1, RewardV2Alpha1, NetworkV2Alpha1, NodeV2Alpha1, LayerV2Alpha1, TransactionV2Alpha1, - AccountV2Alpha1, MalfeasanceV2Alpha1, + AccountV2Alpha1, MalfeasanceV2Alpha1, SmeshingIdentitiesV2Alpha1, }, PublicListener: "0.0.0.0:9092", PrivateServices: []Service{ diff --git a/api/grpcserver/v2alpha1/interface.go b/api/grpcserver/v2alpha1/interface.go index d0a03b528c..f1bbb1107c 100644 --- a/api/grpcserver/v2alpha1/interface.go +++ b/api/grpcserver/v2alpha1/interface.go @@ -1,7 +1,16 @@ package v2alpha1 +import ( + "github.com/spacemeshos/go-spacemesh/activation" + "github.com/spacemeshos/go-spacemesh/common/types" +) + //go:generate mockgen -typed -package=v2alpha1 -destination=./mocks.go -source=./interface.go type malfeasanceInfo interface { Info(data []byte) (map[string]string, error) } + +type identityState interface { + All() map[types.NodeID]*activation.Identity +} diff --git a/api/grpcserver/v2alpha1/smeshing_identities.go b/api/grpcserver/v2alpha1/smeshing_identities.go new file mode 100644 index 0000000000..3d2239c334 --- /dev/null +++ b/api/grpcserver/v2alpha1/smeshing_identities.go @@ -0,0 +1,108 @@ +package v2alpha1 + +import ( + "context" + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + pb "github.com/spacemeshos/api/release/go/spacemesh/v2alpha1" + "github.com/spacemeshos/go-spacemesh/activation" + "github.com/spacemeshos/go-spacemesh/common/types" + "github.com/spacemeshos/go-spacemesh/sql" + "golang.org/x/exp/maps" + "google.golang.org/grpc" + "google.golang.org/protobuf/types/known/timestamppb" +) + +const SmeshingIdentities = "smeshing_identities_v2alpha1" + +type SmeshingIdentitiesService struct { + db sql.Database + states identityState + configuredPoetServices map[string]struct{} +} + +func NewSmeshingIdentitiesService( + db sql.Database, + configuredPoetServices map[string]struct{}, + states identityState, +) *SmeshingIdentitiesService { + return &SmeshingIdentitiesService{ + db: db, + configuredPoetServices: configuredPoetServices, + states: states, + } +} + +var statusMap = map[activation.IdentityState]pb.IdentityStatus{ + activation.IdentityStateNotSet: pb.IdentityStatus_UNSPECIFIED, + activation.IdentityStateWaitForATXSyncing: pb.IdentityStatus_WAIT_FOR_ATX_SYNCING, + activation.IdentityStateWaitingForPoetRegistrationWindow: pb.IdentityStatus_WAITING_FOR_POET_REGISTRATION_WINDOW, + activation.IdentityStatePoetChallengeReady: pb.IdentityStatus_POET_CHALLENGE_READY, + activation.IdentityStatePoetRegistered: pb.IdentityStatus_POET_REGISTERED, + activation.IdentityStatePoetRegistrationFailed: pb.IdentityStatus_POET_REGISTRATION_FAILED, + activation.IdentityStateWaitForPoetRoundEnd: pb.IdentityStatus_WAIT_FOR_POET_ROUND_END, + activation.IdentityStatePoetProofReceived: pb.IdentityStatus_POET_PROOF_RECEIVED, + activation.IdentityStatePoetProofFailed: pb.IdentityStatus_POET_PROOF_FAILED, + activation.IdentityStateGeneratingPostProof: pb.IdentityStatus_GENERATING_POST_PROOF, + activation.IdentityStatePostProofReady: pb.IdentityStatus_POST_PROOF_READY, + activation.IdentityStatePostProofFailed: pb.IdentityStatus_POST_PROOF_FAILED, + activation.IdentityStateATXExpired: pb.IdentityStatus_ATX_EXPIRED, + activation.IdentityStateATXReady: pb.IdentityStatus_ATX_READY, + activation.IdentityStateATXBroadcasted: pb.IdentityStatus_ATX_BROADCASTED, +} + +func (s *SmeshingIdentitiesService) RegisterService(server *grpc.Server) { + pb.RegisterSmeshingIdentitiesServiceServer(server, s) +} + +func (s *SmeshingIdentitiesService) RegisterHandlerService(mux *runtime.ServeMux) error { + return pb.RegisterSmeshingIdentitiesServiceHandlerServer(context.Background(), mux, s) +} + +// String returns the name of this service. +func (s *SmeshingIdentitiesService) String() string { + return "SmeshingIdentitiesService" +} + +func (s *SmeshingIdentitiesService) States( + ctx context.Context, + _ *pb.IdentityStatesRequest, +) (*pb.IdentityStatesResponse, error) { + pbIdentities := make(map[types.NodeID]*pb.Identity) + + for desc, state := range s.states.All() { + pbIdentities[desc] = &pb.Identity{ + SmesherId: desc.Bytes(), + Epochs: []*pb.IdentityStateEpoch{}, + States: []*pb.IdentityState{}, + } + + for epoch, info := range state.EpochStates { + pbEpoch := &pb.IdentityStateEpoch{ + Epoch: epoch.Uint32(), + States: []*pb.IdentityState{}, + } + + for status, statusInfo := range info.States { + ts := timestamppb.New(statusInfo.Time) + pbEpoch.States = append(pbEpoch.States, &pb.IdentityState{ + State: statusMap[status], + Time: ts, + Message: statusInfo.Message, + }) + } + + pbIdentities[desc].Epochs = append(pbIdentities[desc].Epochs, pbEpoch) + } + + for status, statusInfo := range state.States { + ts := timestamppb.New(statusInfo.Time) + pbIdentities[desc].States = append(pbIdentities[desc].States, &pb.IdentityState{ + State: statusMap[status], + Time: ts, + Message: statusInfo.Message, + }) + } + } + + return &pb.IdentityStatesResponse{Identities: maps.Values(pbIdentities)}, nil +} diff --git a/go.mod b/go.mod index f76f7123ee..b240fb0061 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/google/uuid v1.6.0 github.com/grafana/pyroscope-go v1.2.0 github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 - github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 github.com/hashicorp/go-retryablehttp v0.7.7 github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/ipfs/go-ds-leveldb v0.5.0 @@ -40,7 +40,7 @@ require ( github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 github.com/seehuhn/mt19937 v1.0.0 github.com/slok/go-http-metrics v0.13.0 - github.com/spacemeshos/api/release/go v1.55.0 + github.com/spacemeshos/api/release/go v1.55.1-0.20241113145453-71c272a89d2e github.com/spacemeshos/economics v0.1.4 github.com/spacemeshos/fixed v0.1.2 github.com/spacemeshos/go-scale v1.2.1 @@ -59,8 +59,8 @@ require ( golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 golang.org/x/sync v0.8.0 golang.org/x/time v0.7.0 - google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f - google.golang.org/grpc v1.67.1 + google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 + google.golang.org/grpc v1.68.0 google.golang.org/protobuf v1.35.1 k8s.io/api v0.31.2 k8s.io/apimachinery v0.31.2 @@ -242,13 +242,13 @@ require ( golang.org/x/oauth2 v0.23.0 // indirect golang.org/x/sys v0.25.0 // indirect golang.org/x/term v0.24.0 // indirect - golang.org/x/text v0.18.0 // indirect + golang.org/x/text v0.19.0 // indirect golang.org/x/tools v0.25.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect gonum.org/v1/gonum v0.15.0 // indirect google.golang.org/api v0.197.0 // indirect google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240930140551-af27646dc61f // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38 // indirect google.golang.org/grpc/stats/opentelemetry v0.0.0-20240907200651-3ffb98b2c93a // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect diff --git a/go.sum b/go.sum index 96d268c8a4..e84a85382c 100644 --- a/go.sum +++ b/go.sum @@ -275,8 +275,8 @@ github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI= github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0 h1:ad0vkEBuk23VJzZR9nkLVG0YAoN9coASF1GusYX6AlU= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.23.0/go.mod h1:igFoXX2ELCW06bol23DWPB5BEWfZISOzSP5K2sbLea0= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -636,8 +636,8 @@ github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:Udh github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= -github.com/spacemeshos/api/release/go v1.55.0 h1:IQ8PmQ1d7CwUiM1r3NH8uZ+JkEyNjSltiAuqEY6dn6o= -github.com/spacemeshos/api/release/go v1.55.0/go.mod h1:qM6GTS2QtUvxPNIJf+2ObH63bGXYrJnapgOd6l6pbpQ= +github.com/spacemeshos/api/release/go v1.55.1-0.20241113145453-71c272a89d2e h1:JZZLVRufNH2o4LOGmDJcGFKM/ihWL6OJH1lhQV2U/2E= +github.com/spacemeshos/api/release/go v1.55.1-0.20241113145453-71c272a89d2e/go.mod h1:6o17nhNyXpbVeijAQqkZfL8Pe/IkMGAWMLSLZni0DOU= github.com/spacemeshos/economics v0.1.4 h1:twlawrcQhYNqPgyDv08+24EL/OgUKz3d7q+PvJIAND0= github.com/spacemeshos/economics v0.1.4/go.mod h1:6HKWKiKdxjVQcGa2z/wA0LR4M/DzKib856bP16yqNmQ= github.com/spacemeshos/fixed v0.1.2 h1:pENQ8pXFAqin3f15ZLoOVVeSgcmcFJ0IFdFm4+9u4SM= @@ -890,8 +890,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= @@ -945,10 +945,10 @@ google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1 h1:BulPr26Jqjnd4eYDVe+YvyR7Yc2vJGkO5/0UxD0/jZU= google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:hL97c3SYopEHblzpxRL4lSs523++l8DYxGM1FQiYmb4= -google.golang.org/genproto/googleapis/api v0.0.0-20240930140551-af27646dc61f h1:jTm13A2itBi3La6yTGqn8bVSrc3ZZ1r8ENHlIXBfnRA= -google.golang.org/genproto/googleapis/api v0.0.0-20240930140551-af27646dc61f/go.mod h1:CLGoBuH1VHxAUXVPP8FfPwPEVJB6lz3URE5mY2SuayE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f h1:cUMEy+8oS78BWIH9OWazBkzbr090Od9tWBNtZHkOhf0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240930140551-af27646dc61f/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38 h1:2oV8dfuIkM1Ti7DwXc0BJfnwr9csz4TDXI9EmiI+Rbw= +google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38/go.mod h1:vuAjtvlwkDKF6L1GQ0SokiRLCGFfeBUXWr/aFFkHACc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 h1:zciRKQ4kBpFgpfC5QQCVtnnNAcLIqweL7plyZRQHVpI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= @@ -958,8 +958,8 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= -google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= +google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0= +google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA= google.golang.org/grpc/stats/opentelemetry v0.0.0-20240907200651-3ffb98b2c93a h1:UIpYSuWdWHSzjwcAFRLjKcPXFZVVLXGEM23W+NWqipw= google.golang.org/grpc/stats/opentelemetry v0.0.0-20240907200651-3ffb98b2c93a/go.mod h1:9i1T9n4ZinTUZGgzENMi8MDDgbGC5mqTS75JAv6xN3A= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= diff --git a/node/node.go b/node/node.go index 0270d7579d..235fc7513b 100644 --- a/node/node.go +++ b/node/node.go @@ -426,7 +426,9 @@ type App struct { postVerifier activation.PostVerifier postSupervisor *activation.PostSupervisor malfeasanceHandler *malfeasance.Handler - errCh chan error + idStates *activation.IdentityStateStorage + + errCh chan error host *p2p.Host @@ -621,6 +623,9 @@ func (app *App) initServices(ctx context.Context) error { return fmt.Errorf("creating poet db: %w", err) } postStates := activation.NewPostStates(app.addLogger(PostLogger, lg).Zap()) + + app.idStates = activation.NewIdentityStateStorage() + opts := []activation.PostVerifierOpt{ activation.WithVerifyingOpts(app.Config.SMESHING.VerifyingOpts), activation.WithAutoscaling(postStates), @@ -1113,6 +1118,7 @@ func (app *App) initServices(ctx context.Context) error { app.clock, app.validator, activation.NipostbuilderWithPostStates(postStates), + activation.NipostbuilderWithIdentityStates(app.idStates), activation.WithPoetServices(poetClients...), ) if err != nil { @@ -1165,6 +1171,7 @@ func (app *App) initServices(ctx context.Context) error { // TODO(dshulyak) makes no sense. how we ended using it? activation.WithPoetRetryInterval(app.Config.HARE3.PreroundDelay), activation.WithPostStates(postStates), + activation.WithIdentityStates(app.idStates), activation.WithPoets(poetClients...), activation.BuilderAtxVersions(app.Config.AtxVersions), ) @@ -1666,6 +1673,20 @@ func (app *App) grpcService(svc grpcserver.Service, lg log.Log) (grpcserver.Serv service := v2alpha1.NewAccountService(app.apiDB, app.conState) app.grpcServices[svc] = service return service, nil + case v2alpha1.SmeshingIdentities: + nodeIds := make(map[types.NodeID]struct{}) + for _, signer := range app.signers { + nodeIds[signer.NodeID()] = struct{}{} + } + + configuredPoets := make(map[string]struct{}) + for _, server := range app.Config.PoetServers { + configuredPoets[server.Address] = struct{}{} + } + + service := v2alpha1.NewSmeshingIdentitiesService(app.db, configuredPoets, app.idStates) + app.grpcServices[svc] = service + return service, nil } return nil, fmt.Errorf("unknown service %s", svc) } From 11c94d64d6aa122503fd970a502ef2aeceb77ad3 Mon Sep 17 00:00:00 2001 From: Kacper Sawicki Date: Fri, 15 Nov 2024 13:11:38 +0100 Subject: [PATCH 2/8] Fix lint --- activation/identity_states.go | 12 ++++++----- .../v2alpha1/smeshing_identities.go | 17 ++++++---------- node/node.go | 20 +++++++++---------- 3 files changed, 23 insertions(+), 26 deletions(-) diff --git a/activation/identity_states.go b/activation/identity_states.go index 66f3270b6c..722c3af32e 100644 --- a/activation/identity_states.go +++ b/activation/identity_states.go @@ -21,9 +21,9 @@ const ( IdentityStateWaitForATXSyncing - // poet + // poet. IdentityStateWaitingForPoetRegistrationWindow - // building nipost challenge + // building nipost challenge. IdentityStatePoetChallengeReady IdentityStatePoetRegistered IdentityStatePoetRegistrationFailed @@ -32,12 +32,12 @@ const ( IdentityStatePoetProofReceived IdentityStatePoetProofFailed - // post + // post. IdentityStateGeneratingPostProof IdentityStatePostProofReady IdentityStatePostProofFailed - // atx + // atx. IdentityStateATXExpired IdentityStateATXReady IdentityStateATXBroadcasted @@ -124,7 +124,9 @@ func NewIdentityStateStorage() *IdentityStateStorage { // }, //} -func (s *IdentityStateStorage) Set(id types.NodeID, publishEpoch *types.EpochID, newState IdentityState, message string) { +func (s *IdentityStateStorage) Set(id types.NodeID, publishEpoch *types.EpochID, newState IdentityState, + message string, +) { s.mu.Lock() defer s.mu.Unlock() diff --git a/api/grpcserver/v2alpha1/smeshing_identities.go b/api/grpcserver/v2alpha1/smeshing_identities.go index 3d2239c334..4c75f6103c 100644 --- a/api/grpcserver/v2alpha1/smeshing_identities.go +++ b/api/grpcserver/v2alpha1/smeshing_identities.go @@ -2,33 +2,28 @@ package v2alpha1 import ( "context" + "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" pb "github.com/spacemeshos/api/release/go/spacemesh/v2alpha1" - "github.com/spacemeshos/go-spacemesh/activation" - "github.com/spacemeshos/go-spacemesh/common/types" - "github.com/spacemeshos/go-spacemesh/sql" "golang.org/x/exp/maps" "google.golang.org/grpc" "google.golang.org/protobuf/types/known/timestamppb" + + "github.com/spacemeshos/go-spacemesh/activation" + "github.com/spacemeshos/go-spacemesh/common/types" ) const SmeshingIdentities = "smeshing_identities_v2alpha1" type SmeshingIdentitiesService struct { - db sql.Database - states identityState - configuredPoetServices map[string]struct{} + states identityState } func NewSmeshingIdentitiesService( - db sql.Database, - configuredPoetServices map[string]struct{}, states identityState, ) *SmeshingIdentitiesService { return &SmeshingIdentitiesService{ - db: db, - configuredPoetServices: configuredPoetServices, - states: states, + states: states, } } diff --git a/node/node.go b/node/node.go index 235fc7513b..cc1c46fc23 100644 --- a/node/node.go +++ b/node/node.go @@ -1674,17 +1674,17 @@ func (app *App) grpcService(svc grpcserver.Service, lg log.Log) (grpcserver.Serv app.grpcServices[svc] = service return service, nil case v2alpha1.SmeshingIdentities: - nodeIds := make(map[types.NodeID]struct{}) - for _, signer := range app.signers { - nodeIds[signer.NodeID()] = struct{}{} - } - - configuredPoets := make(map[string]struct{}) - for _, server := range app.Config.PoetServers { - configuredPoets[server.Address] = struct{}{} - } + //nodeIds := make(map[types.NodeID]struct{}) + //for _, signer := range app.signers { + // nodeIds[signer.NodeID()] = struct{}{} + //} + // + //configuredPoets := make(map[string]struct{}) + //for _, server := range app.Config.PoetServers { + // configuredPoets[server.Address] = struct{}{} + //} - service := v2alpha1.NewSmeshingIdentitiesService(app.db, configuredPoets, app.idStates) + service := v2alpha1.NewSmeshingIdentitiesService(app.idStates) app.grpcServices[svc] = service return service, nil } From 3173a03ef2e15a4ab577e426f81482805dc8e963 Mon Sep 17 00:00:00 2001 From: Kacper Sawicki Date: Fri, 15 Nov 2024 13:23:24 +0100 Subject: [PATCH 3/8] Update mocks --- activation/mocks.go | 137 +++++++++++++++++++++++++++++++ api/grpcserver/v2alpha1/mocks.go | 64 +++++++++++++++ 2 files changed, 201 insertions(+) diff --git a/activation/mocks.go b/activation/mocks.go index 91a53d4c56..99b8626d09 100644 --- a/activation/mocks.go +++ b/activation/mocks.go @@ -2692,3 +2692,140 @@ func (c *MockPostStatesSetCall) DoAndReturn(f func(types.NodeID, types.PostState c.Call = c.Call.DoAndReturn(f) return c } + +// MockIdentityStates is a mock of IdentityStates interface. +type MockIdentityStates struct { + ctrl *gomock.Controller + recorder *MockIdentityStatesMockRecorder + isgomock struct{} +} + +// MockIdentityStatesMockRecorder is the mock recorder for MockIdentityStates. +type MockIdentityStatesMockRecorder struct { + mock *MockIdentityStates +} + +// NewMockIdentityStates creates a new mock instance. +func NewMockIdentityStates(ctrl *gomock.Controller) *MockIdentityStates { + mock := &MockIdentityStates{ctrl: ctrl} + mock.recorder = &MockIdentityStatesMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockIdentityStates) EXPECT() *MockIdentityStatesMockRecorder { + return m.recorder +} + +// All mocks base method. +func (m *MockIdentityStates) All() map[types.NodeID]*Identity { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "All") + ret0, _ := ret[0].(map[types.NodeID]*Identity) + return ret0 +} + +// All indicates an expected call of All. +func (mr *MockIdentityStatesMockRecorder) All() *MockIdentityStatesAllCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "All", reflect.TypeOf((*MockIdentityStates)(nil).All)) + return &MockIdentityStatesAllCall{Call: call} +} + +// MockIdentityStatesAllCall wrap *gomock.Call +type MockIdentityStatesAllCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockIdentityStatesAllCall) Return(arg0 map[types.NodeID]*Identity) *MockIdentityStatesAllCall { + c.Call = c.Call.Return(arg0) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockIdentityStatesAllCall) Do(f func() map[types.NodeID]*Identity) *MockIdentityStatesAllCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockIdentityStatesAllCall) DoAndReturn(f func() map[types.NodeID]*Identity) *MockIdentityStatesAllCall { + c.Call = c.Call.DoAndReturn(f) + return c +} + +// Get mocks base method. +func (m *MockIdentityStates) Get(id types.NodeID) (*Identity, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Get", id) + ret0, _ := ret[0].(*Identity) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Get indicates an expected call of Get. +func (mr *MockIdentityStatesMockRecorder) Get(id any) *MockIdentityStatesGetCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockIdentityStates)(nil).Get), id) + return &MockIdentityStatesGetCall{Call: call} +} + +// MockIdentityStatesGetCall wrap *gomock.Call +type MockIdentityStatesGetCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockIdentityStatesGetCall) Return(arg0 *Identity, arg1 error) *MockIdentityStatesGetCall { + c.Call = c.Call.Return(arg0, arg1) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockIdentityStatesGetCall) Do(f func(types.NodeID) (*Identity, error)) *MockIdentityStatesGetCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockIdentityStatesGetCall) DoAndReturn(f func(types.NodeID) (*Identity, error)) *MockIdentityStatesGetCall { + c.Call = c.Call.DoAndReturn(f) + return c +} + +// Set mocks base method. +func (m *MockIdentityStates) Set(id types.NodeID, publishEpoch *types.EpochID, newState IdentityState, message string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Set", id, publishEpoch, newState, message) +} + +// Set indicates an expected call of Set. +func (mr *MockIdentityStatesMockRecorder) Set(id, publishEpoch, newState, message any) *MockIdentityStatesSetCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Set", reflect.TypeOf((*MockIdentityStates)(nil).Set), id, publishEpoch, newState, message) + return &MockIdentityStatesSetCall{Call: call} +} + +// MockIdentityStatesSetCall wrap *gomock.Call +type MockIdentityStatesSetCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockIdentityStatesSetCall) Return() *MockIdentityStatesSetCall { + c.Call = c.Call.Return() + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockIdentityStatesSetCall) Do(f func(types.NodeID, *types.EpochID, IdentityState, string)) *MockIdentityStatesSetCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockIdentityStatesSetCall) DoAndReturn(f func(types.NodeID, *types.EpochID, IdentityState, string)) *MockIdentityStatesSetCall { + c.Call = c.Call.DoAndReturn(f) + return c +} diff --git a/api/grpcserver/v2alpha1/mocks.go b/api/grpcserver/v2alpha1/mocks.go index 6f7f88adf8..8485ff121f 100644 --- a/api/grpcserver/v2alpha1/mocks.go +++ b/api/grpcserver/v2alpha1/mocks.go @@ -12,6 +12,8 @@ package v2alpha1 import ( reflect "reflect" + activation "github.com/spacemeshos/go-spacemesh/activation" + types "github.com/spacemeshos/go-spacemesh/common/types" gomock "go.uber.org/mock/gomock" ) @@ -77,3 +79,65 @@ func (c *MockmalfeasanceInfoInfoCall) DoAndReturn(f func([]byte) (map[string]str c.Call = c.Call.DoAndReturn(f) return c } + +// MockidentityState is a mock of identityState interface. +type MockidentityState struct { + ctrl *gomock.Controller + recorder *MockidentityStateMockRecorder + isgomock struct{} +} + +// MockidentityStateMockRecorder is the mock recorder for MockidentityState. +type MockidentityStateMockRecorder struct { + mock *MockidentityState +} + +// NewMockidentityState creates a new mock instance. +func NewMockidentityState(ctrl *gomock.Controller) *MockidentityState { + mock := &MockidentityState{ctrl: ctrl} + mock.recorder = &MockidentityStateMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockidentityState) EXPECT() *MockidentityStateMockRecorder { + return m.recorder +} + +// All mocks base method. +func (m *MockidentityState) All() map[types.NodeID]*activation.Identity { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "All") + ret0, _ := ret[0].(map[types.NodeID]*activation.Identity) + return ret0 +} + +// All indicates an expected call of All. +func (mr *MockidentityStateMockRecorder) All() *MockidentityStateAllCall { + mr.mock.ctrl.T.Helper() + call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "All", reflect.TypeOf((*MockidentityState)(nil).All)) + return &MockidentityStateAllCall{Call: call} +} + +// MockidentityStateAllCall wrap *gomock.Call +type MockidentityStateAllCall struct { + *gomock.Call +} + +// Return rewrite *gomock.Call.Return +func (c *MockidentityStateAllCall) Return(arg0 map[types.NodeID]*activation.Identity) *MockidentityStateAllCall { + c.Call = c.Call.Return(arg0) + return c +} + +// Do rewrite *gomock.Call.Do +func (c *MockidentityStateAllCall) Do(f func() map[types.NodeID]*activation.Identity) *MockidentityStateAllCall { + c.Call = c.Call.Do(f) + return c +} + +// DoAndReturn rewrite *gomock.Call.DoAndReturn +func (c *MockidentityStateAllCall) DoAndReturn(f func() map[types.NodeID]*activation.Identity) *MockidentityStateAllCall { + c.Call = c.Call.DoAndReturn(f) + return c +} From 2cd426a86663ae2e955a88f825e45b20eda5aa93 Mon Sep 17 00:00:00 2001 From: Kacper Sawicki Date: Fri, 15 Nov 2024 16:13:41 +0100 Subject: [PATCH 4/8] Change Identity structure, apply review suggestions --- activation/activation.go | 12 ++- activation/identity_states.go | 100 ++++-------------- .../v2alpha1/smeshing_identities.go | 69 +++++------- go.mod | 2 +- go.sum | 4 +- 5 files changed, 63 insertions(+), 124 deletions(-) diff --git a/activation/activation.go b/activation/activation.go index 8357b52afb..c8e73d3f07 100644 --- a/activation/activation.go +++ b/activation/activation.go @@ -508,12 +508,18 @@ func (b *Builder) run(ctx context.Context, sig *signing.EdSigner) { func (b *Builder) BuildNIPostChallenge(ctx context.Context, nodeID types.NodeID) (*types.NIPostChallenge, error) { logger := b.logger.With(log.ZShortStringer("smesherID", nodeID)) - b.identitiesStates.Set(nodeID, nil, IdentityStateWaitForATXSyncing, "") + + atxSyncedCh := b.syncer.RegisterForATXSynced() + select { + case <-atxSyncedCh: + default: + b.identitiesStates.Set(nodeID, nil, IdentityStateWaitForATXSynced, "") + } select { case <-ctx.Done(): return nil, ctx.Err() - case <-b.syncer.RegisterForATXSynced(): + case <-atxSyncedCh: } currentEpochId := b.layerClock.CurrentLayer().GetEpoch() @@ -521,6 +527,8 @@ func (b *Builder) BuildNIPostChallenge(ctx context.Context, nodeID types.NodeID) // Try to get existing challenge existingChallenge, err := b.getExistingChallenge(logger, currentEpochId, nodeID) if err != nil { + b.identitiesStates.Set(nodeID, nil, IdentityStatePostProofFailed, + fmt.Sprintf("getting existing NiPoST challenge: %s", err.Error())) return nil, fmt.Errorf("getting existing NiPoST challenge: %w", err) } diff --git a/activation/identity_states.go b/activation/identity_states.go index 722c3af32e..eee2b77911 100644 --- a/activation/identity_states.go +++ b/activation/identity_states.go @@ -19,7 +19,7 @@ type IdentityState int const ( IdentityStateNotSet IdentityState = iota - IdentityStateWaitForATXSyncing + IdentityStateWaitForATXSynced // poet. IdentityStateWaitingForPoetRegistrationWindow @@ -47,8 +47,8 @@ func (s IdentityState) String() string { switch s { case IdentityStateNotSet: return "not set" - case IdentityStateWaitForATXSyncing: - return "wait for atx syncing" + case IdentityStateWaitForATXSynced: + return "wait for atx synced" case IdentityStatePoetChallengeReady: return "poet challenge ready" case IdentityStateWaitingForPoetRegistrationWindow: @@ -77,18 +77,14 @@ func (s IdentityState) String() string { } type IdentityStateInfo struct { - Message string - Time time.Time -} - -type IdentityInfo struct { - PublishEpoch types.EpochID - States map[IdentityState]IdentityStateInfo + State IdentityState + PublishEpoch *types.EpochID + Message string + Time time.Time } type Identity struct { - EpochStates map[types.EpochID]*IdentityInfo - States map[IdentityState]IdentityStateInfo + History []IdentityStateInfo } type IdentityStateStorage struct { @@ -102,29 +98,10 @@ func NewIdentityStateStorage() *IdentityStateStorage { } } -// TODO: validate state switch -//var validStateSwitch = map[IdentityState][]IdentityState{ -// IdentityStateWaitForATXSyncing: { -// IdentityStateWaitForPoetRoundStart, -// }, -// IdentityStatePostProving: { -// IdentityStateWaitForPoetRoundStart, -// }, -// IdentityStateWaitForPoetRoundStart: { -// IdentityStateWaitForPoetRoundEnd, -// IdentityStateWaitForATXSyncing, -// }, -// IdentityStateWaitForPoetRoundEnd: { -// IdentityStateFetchingProofs, -// IdentityStateWaitForPoetRoundStart, -// }, -// IdentityStateFetchingProofs: { -// IdentityStatePostProving, -// IdentityStateWaitForPoetRoundStart, -// }, -//} - -func (s *IdentityStateStorage) Set(id types.NodeID, publishEpoch *types.EpochID, newState IdentityState, +func (s *IdentityStateStorage) Set( + id types.NodeID, + publishEpoch *types.EpochID, + newState IdentityState, message string, ) { s.mu.Lock() @@ -132,53 +109,20 @@ func (s *IdentityStateStorage) Set(id types.NodeID, publishEpoch *types.EpochID, if _, exists := s.identities[id]; !exists { s.identities[id] = &Identity{ - EpochStates: map[types.EpochID]*IdentityInfo{}, - States: map[IdentityState]IdentityStateInfo{}, + History: []IdentityStateInfo{}, } } - if publishEpoch != nil { - if _, exists := s.identities[id].EpochStates[*publishEpoch]; !exists { - s.identities[id].EpochStates[*publishEpoch] = &IdentityInfo{ - PublishEpoch: *publishEpoch, - States: make(map[IdentityState]IdentityStateInfo), - } - } - s.identities[id].EpochStates[*publishEpoch].States[newState] = IdentityStateInfo{ - Time: time.Now(), - Message: message, - } - } else { - s.identities[id].States[newState] = IdentityStateInfo{ - Time: time.Now(), - Message: message, - } + if len(s.identities[id].History) > 100 { + s.identities[id].History = s.identities[id].History[1:] } - // TODO: validate state switch - //currentState, exists := s.states[id] - //switch { - //case !exists: - // if newState == IdentityStateWaitForATXSyncing { - // s.states[id] = newState - // return nil - // } - //case currentState == newState: - // return nil - // - //default: - // if validNextStates, ok := validStateSwitch[currentState]; ok && - // slices.Contains(validNextStates, newState) { - // s.states[id] = newState - // return nil - // } - //} - // - //return fmt.Errorf( - // "%w: state %v can't be switched to %v", - // ErrInvalidIdentityStateSwitch, - // currentState, - // newState, - //) + + s.identities[id].History = append(s.identities[id].History, IdentityStateInfo{ + State: newState, + PublishEpoch: publishEpoch, + Message: message, + Time: time.Now(), + }) } func (s *IdentityStateStorage) Get(id types.NodeID) (*Identity, error) { diff --git a/api/grpcserver/v2alpha1/smeshing_identities.go b/api/grpcserver/v2alpha1/smeshing_identities.go index 4c75f6103c..81f1551944 100644 --- a/api/grpcserver/v2alpha1/smeshing_identities.go +++ b/api/grpcserver/v2alpha1/smeshing_identities.go @@ -27,22 +27,22 @@ func NewSmeshingIdentitiesService( } } -var statusMap = map[activation.IdentityState]pb.IdentityStatus{ - activation.IdentityStateNotSet: pb.IdentityStatus_UNSPECIFIED, - activation.IdentityStateWaitForATXSyncing: pb.IdentityStatus_WAIT_FOR_ATX_SYNCING, - activation.IdentityStateWaitingForPoetRegistrationWindow: pb.IdentityStatus_WAITING_FOR_POET_REGISTRATION_WINDOW, - activation.IdentityStatePoetChallengeReady: pb.IdentityStatus_POET_CHALLENGE_READY, - activation.IdentityStatePoetRegistered: pb.IdentityStatus_POET_REGISTERED, - activation.IdentityStatePoetRegistrationFailed: pb.IdentityStatus_POET_REGISTRATION_FAILED, - activation.IdentityStateWaitForPoetRoundEnd: pb.IdentityStatus_WAIT_FOR_POET_ROUND_END, - activation.IdentityStatePoetProofReceived: pb.IdentityStatus_POET_PROOF_RECEIVED, - activation.IdentityStatePoetProofFailed: pb.IdentityStatus_POET_PROOF_FAILED, - activation.IdentityStateGeneratingPostProof: pb.IdentityStatus_GENERATING_POST_PROOF, - activation.IdentityStatePostProofReady: pb.IdentityStatus_POST_PROOF_READY, - activation.IdentityStatePostProofFailed: pb.IdentityStatus_POST_PROOF_FAILED, - activation.IdentityStateATXExpired: pb.IdentityStatus_ATX_EXPIRED, - activation.IdentityStateATXReady: pb.IdentityStatus_ATX_READY, - activation.IdentityStateATXBroadcasted: pb.IdentityStatus_ATX_BROADCASTED, +var statusMap = map[activation.IdentityState]pb.IdentityState{ + activation.IdentityStateNotSet: pb.IdentityState_UNSPECIFIED, + activation.IdentityStateWaitForATXSynced: pb.IdentityState_WAIT_FOR_ATX_SYNCED, + activation.IdentityStateWaitingForPoetRegistrationWindow: pb.IdentityState_WAITING_FOR_POET_REGISTRATION_WINDOW, + activation.IdentityStatePoetChallengeReady: pb.IdentityState_POET_CHALLENGE_READY, + activation.IdentityStatePoetRegistered: pb.IdentityState_POET_REGISTERED, + activation.IdentityStatePoetRegistrationFailed: pb.IdentityState_POET_REGISTRATION_FAILED, + activation.IdentityStateWaitForPoetRoundEnd: pb.IdentityState_WAIT_FOR_POET_ROUND_END, + activation.IdentityStatePoetProofReceived: pb.IdentityState_POET_PROOF_RECEIVED, + activation.IdentityStatePoetProofFailed: pb.IdentityState_POET_PROOF_FAILED, + activation.IdentityStateGeneratingPostProof: pb.IdentityState_GENERATING_POST_PROOF, + activation.IdentityStatePostProofReady: pb.IdentityState_POST_PROOF_READY, + activation.IdentityStatePostProofFailed: pb.IdentityState_POST_PROOF_FAILED, + activation.IdentityStateATXExpired: pb.IdentityState_ATX_EXPIRED, + activation.IdentityStateATXReady: pb.IdentityState_ATX_READY, + activation.IdentityStateATXBroadcasted: pb.IdentityState_ATX_BROADCASTED, } func (s *SmeshingIdentitiesService) RegisterService(server *grpc.Server) { @@ -67,35 +67,22 @@ func (s *SmeshingIdentitiesService) States( for desc, state := range s.states.All() { pbIdentities[desc] = &pb.Identity{ SmesherId: desc.Bytes(), - Epochs: []*pb.IdentityStateEpoch{}, - States: []*pb.IdentityState{}, + History: []*pb.IdentityStateInfo{}, } - for epoch, info := range state.EpochStates { - pbEpoch := &pb.IdentityStateEpoch{ - Epoch: epoch.Uint32(), - States: []*pb.IdentityState{}, + for i := len(state.History) - 1; i >= 0; i-- { + info := state.History[i] + ts := timestamppb.New(info.Time) + identityStateInfo := &pb.IdentityStateInfo{ + State: statusMap[info.State], + Time: ts, + Message: info.Message, } - - for status, statusInfo := range info.States { - ts := timestamppb.New(statusInfo.Time) - pbEpoch.States = append(pbEpoch.States, &pb.IdentityState{ - State: statusMap[status], - Time: ts, - Message: statusInfo.Message, - }) + if info.PublishEpoch != nil { + epoch := info.PublishEpoch.Uint32() + identityStateInfo.PublishEpoch = &epoch } - - pbIdentities[desc].Epochs = append(pbIdentities[desc].Epochs, pbEpoch) - } - - for status, statusInfo := range state.States { - ts := timestamppb.New(statusInfo.Time) - pbIdentities[desc].States = append(pbIdentities[desc].States, &pb.IdentityState{ - State: statusMap[status], - Time: ts, - Message: statusInfo.Message, - }) + pbIdentities[desc].History = append(pbIdentities[desc].History, identityStateInfo) } } diff --git a/go.mod b/go.mod index b240fb0061..7b98e12319 100644 --- a/go.mod +++ b/go.mod @@ -40,7 +40,7 @@ require ( github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 github.com/seehuhn/mt19937 v1.0.0 github.com/slok/go-http-metrics v0.13.0 - github.com/spacemeshos/api/release/go v1.55.1-0.20241113145453-71c272a89d2e + github.com/spacemeshos/api/release/go v1.55.1-0.20241115150849-d14c560b5d51 github.com/spacemeshos/economics v0.1.4 github.com/spacemeshos/fixed v0.1.2 github.com/spacemeshos/go-scale v1.2.1 diff --git a/go.sum b/go.sum index e84a85382c..4505eaa1c7 100644 --- a/go.sum +++ b/go.sum @@ -636,8 +636,8 @@ github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:Udh github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= -github.com/spacemeshos/api/release/go v1.55.1-0.20241113145453-71c272a89d2e h1:JZZLVRufNH2o4LOGmDJcGFKM/ihWL6OJH1lhQV2U/2E= -github.com/spacemeshos/api/release/go v1.55.1-0.20241113145453-71c272a89d2e/go.mod h1:6o17nhNyXpbVeijAQqkZfL8Pe/IkMGAWMLSLZni0DOU= +github.com/spacemeshos/api/release/go v1.55.1-0.20241115150849-d14c560b5d51 h1:Z9/mHlh4G8DIUAMGnJMrkcDbMLzRAiRQQnYwWXEZ1BU= +github.com/spacemeshos/api/release/go v1.55.1-0.20241115150849-d14c560b5d51/go.mod h1:6o17nhNyXpbVeijAQqkZfL8Pe/IkMGAWMLSLZni0DOU= github.com/spacemeshos/economics v0.1.4 h1:twlawrcQhYNqPgyDv08+24EL/OgUKz3d7q+PvJIAND0= github.com/spacemeshos/economics v0.1.4/go.mod h1:6HKWKiKdxjVQcGa2z/wA0LR4M/DzKib856bP16yqNmQ= github.com/spacemeshos/fixed v0.1.2 h1:pENQ8pXFAqin3f15ZLoOVVeSgcmcFJ0IFdFm4+9u4SM= From debdbb3f32456e0b59f14e304e2693a57518934f Mon Sep 17 00:00:00 2001 From: Kacper Sawicki Date: Mon, 18 Nov 2024 10:59:20 +0100 Subject: [PATCH 5/8] Add IdentityStateRetrying --- activation/activation.go | 4 ++-- activation/identity_states.go | 11 +++-------- activation/nipost.go | 18 ------------------ api/grpcserver/v2alpha1/smeshing_identities.go | 5 +---- go.mod | 2 +- go.sum | 4 ++-- 6 files changed, 9 insertions(+), 35 deletions(-) diff --git a/activation/activation.go b/activation/activation.go index c8e73d3f07..f54bf412c3 100644 --- a/activation/activation.go +++ b/activation/activation.go @@ -450,6 +450,8 @@ func (b *Builder) run(ctx context.Context, sig *signing.EdSigner) { b.logger.Warn("failed to publish atx", zap.Error(err)) + b.identitiesStates.Set(sig.NodeID(), nil, IdentityStateRetrying, err.Error()) + poetErr := &PoetSvcUnstableError{} switch { case errors.Is(err, ErrATXChallengeExpired): @@ -527,8 +529,6 @@ func (b *Builder) BuildNIPostChallenge(ctx context.Context, nodeID types.NodeID) // Try to get existing challenge existingChallenge, err := b.getExistingChallenge(logger, currentEpochId, nodeID) if err != nil { - b.identitiesStates.Set(nodeID, nil, IdentityStatePostProofFailed, - fmt.Sprintf("getting existing NiPoST challenge: %s", err.Error())) return nil, fmt.Errorf("getting existing NiPoST challenge: %w", err) } diff --git a/activation/identity_states.go b/activation/identity_states.go index eee2b77911..b9cbf907ac 100644 --- a/activation/identity_states.go +++ b/activation/identity_states.go @@ -20,25 +20,22 @@ const ( IdentityStateNotSet IdentityState = iota IdentityStateWaitForATXSynced + IdentityStateRetrying // poet. IdentityStateWaitingForPoetRegistrationWindow // building nipost challenge. IdentityStatePoetChallengeReady IdentityStatePoetRegistered - IdentityStatePoetRegistrationFailed // 2w pass ... IdentityStateWaitForPoetRoundEnd IdentityStatePoetProofReceived - IdentityStatePoetProofFailed // post. IdentityStateGeneratingPostProof IdentityStatePostProofReady - IdentityStatePostProofFailed // atx. - IdentityStateATXExpired IdentityStateATXReady IdentityStateATXBroadcasted ) @@ -49,6 +46,8 @@ func (s IdentityState) String() string { return "not set" case IdentityStateWaitForATXSynced: return "wait for atx synced" + case IdentityStateRetrying: + return "retrying" case IdentityStatePoetChallengeReady: return "poet challenge ready" case IdentityStateWaitingForPoetRegistrationWindow: @@ -59,14 +58,10 @@ func (s IdentityState) String() string { return "wait for poet round end" case IdentityStatePoetProofReceived: return "poet proof received" - case IdentityStatePoetProofFailed: - return "poet proof failed" case IdentityStateGeneratingPostProof: return "generating post proof" case IdentityStatePostProofReady: return "post proof ready" - case IdentityStatePostProofFailed: - return "post proof failed" case IdentityStateATXReady: return "atx ready" case IdentityStateATXBroadcasted: diff --git a/activation/nipost.go b/activation/nipost.go index 17c6d1acca..a5b0ffa9d2 100644 --- a/activation/nipost.go +++ b/activation/nipost.go @@ -247,8 +247,6 @@ func (nb *NIPostBuilder) BuildNIPost( regErr := &PoetRegistrationMismatchError{} switch { case errors.As(err, ®Err): - nb.identityStates.Set(signer.NodeID(), &postChallenge.PublishEpoch, IdentityStatePoetRegistrationFailed, - regErr.Error()) logger.Fatal( "None of the poets listed in the config matches the existing registrations. "+ "Verify your config and local database state.", @@ -257,8 +255,6 @@ func (nb *NIPostBuilder) BuildNIPost( ) return nil, err case err != nil: - nb.identityStates.Set(signer.NodeID(), &postChallenge.PublishEpoch, IdentityStatePoetRegistrationFailed, - err.Error()) return nil, fmt.Errorf("submitting to poets: %w", err) } @@ -273,11 +269,6 @@ func (nb *NIPostBuilder) BuildNIPost( // Deadline: the end of the publish epoch minus the cycle gap. A node that is setup correctly (i.e. can // generate a PoST proof within the cycle gap) has enough time left to generate a post proof and publish. if poetProofDeadline.Before(now) { - nb.identityStates.Set(signer.NodeID(), &postChallenge.PublishEpoch, IdentityStateATXExpired, fmt.Sprintf( - "deadline to query poet proof for pub epoch %d exceeded (deadline: %s, now: %s)", - postChallenge.PublishEpoch, - poetProofDeadline, - now)) return nil, fmt.Errorf( "%w: deadline to query poet proof for pub epoch %d exceeded (deadline: %s, now: %s)", ErrATXChallengeExpired, @@ -296,8 +287,6 @@ func (nb *NIPostBuilder) BuildNIPost( return nil, &PoetSvcUnstableError{msg: "getBestProof failed", source: err} } if poetProofRef == types.EmptyPoetProofRef { - nb.identityStates.Set(signer.NodeID(), &postChallenge.PublishEpoch, IdentityStatePoetProofFailed, - "poet proof not received") return nil, &PoetSvcUnstableError{source: ErrPoetProofNotReceived} } if err := nipost.UpdatePoetProofRef(nb.localDB, signer.NodeID(), poetProofRef, membership); err != nil { @@ -316,11 +305,6 @@ func (nb *NIPostBuilder) BuildNIPost( // Deadline: the end of the publish epoch. If we do not publish within // the publish epoch we won't receive any rewards in the target epoch. if publishEpochEnd.Before(now) { - nb.identityStates.Set(signer.NodeID(), &postChallenge.PublishEpoch, IdentityStateATXExpired, fmt.Sprintf( - "deadline to publish ATX for pub epoch %d exceeded (deadline: %s, now: %s)", - postChallenge.PublishEpoch, - publishEpochEnd, - now)) return nil, fmt.Errorf( "%w: deadline to publish ATX for pub epoch %d exceeded (deadline: %s, now: %s)", ErrATXChallengeExpired, @@ -338,8 +322,6 @@ func (nb *NIPostBuilder) BuildNIPost( startTime := time.Now() proof, postInfo, err := nb.Proof(postCtx, signer.NodeID(), poetProofRef[:], postChallenge) if err != nil { - nb.identityStates.Set(signer.NodeID(), &postChallenge.PublishEpoch, IdentityStatePostProofFailed, - fmt.Sprintf("failed to generate Post: %v", err)) return nil, fmt.Errorf("failed to generate Post: %w", err) } nb.identityStates.Set(signer.NodeID(), &postChallenge.PublishEpoch, IdentityStatePostProofReady, "") diff --git a/api/grpcserver/v2alpha1/smeshing_identities.go b/api/grpcserver/v2alpha1/smeshing_identities.go index 81f1551944..3acc18c208 100644 --- a/api/grpcserver/v2alpha1/smeshing_identities.go +++ b/api/grpcserver/v2alpha1/smeshing_identities.go @@ -30,17 +30,14 @@ func NewSmeshingIdentitiesService( var statusMap = map[activation.IdentityState]pb.IdentityState{ activation.IdentityStateNotSet: pb.IdentityState_UNSPECIFIED, activation.IdentityStateWaitForATXSynced: pb.IdentityState_WAIT_FOR_ATX_SYNCED, + activation.IdentityStateRetrying: pb.IdentityState_RETRYING, activation.IdentityStateWaitingForPoetRegistrationWindow: pb.IdentityState_WAITING_FOR_POET_REGISTRATION_WINDOW, activation.IdentityStatePoetChallengeReady: pb.IdentityState_POET_CHALLENGE_READY, activation.IdentityStatePoetRegistered: pb.IdentityState_POET_REGISTERED, - activation.IdentityStatePoetRegistrationFailed: pb.IdentityState_POET_REGISTRATION_FAILED, activation.IdentityStateWaitForPoetRoundEnd: pb.IdentityState_WAIT_FOR_POET_ROUND_END, activation.IdentityStatePoetProofReceived: pb.IdentityState_POET_PROOF_RECEIVED, - activation.IdentityStatePoetProofFailed: pb.IdentityState_POET_PROOF_FAILED, activation.IdentityStateGeneratingPostProof: pb.IdentityState_GENERATING_POST_PROOF, activation.IdentityStatePostProofReady: pb.IdentityState_POST_PROOF_READY, - activation.IdentityStatePostProofFailed: pb.IdentityState_POST_PROOF_FAILED, - activation.IdentityStateATXExpired: pb.IdentityState_ATX_EXPIRED, activation.IdentityStateATXReady: pb.IdentityState_ATX_READY, activation.IdentityStateATXBroadcasted: pb.IdentityState_ATX_BROADCASTED, } diff --git a/go.mod b/go.mod index 7b98e12319..283602610f 100644 --- a/go.mod +++ b/go.mod @@ -40,7 +40,7 @@ require ( github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 github.com/seehuhn/mt19937 v1.0.0 github.com/slok/go-http-metrics v0.13.0 - github.com/spacemeshos/api/release/go v1.55.1-0.20241115150849-d14c560b5d51 + github.com/spacemeshos/api/release/go v1.55.1-0.20241118094246-cc3dcef1a261 github.com/spacemeshos/economics v0.1.4 github.com/spacemeshos/fixed v0.1.2 github.com/spacemeshos/go-scale v1.2.1 diff --git a/go.sum b/go.sum index 4505eaa1c7..4597a60197 100644 --- a/go.sum +++ b/go.sum @@ -636,8 +636,8 @@ github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:Udh github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= -github.com/spacemeshos/api/release/go v1.55.1-0.20241115150849-d14c560b5d51 h1:Z9/mHlh4G8DIUAMGnJMrkcDbMLzRAiRQQnYwWXEZ1BU= -github.com/spacemeshos/api/release/go v1.55.1-0.20241115150849-d14c560b5d51/go.mod h1:6o17nhNyXpbVeijAQqkZfL8Pe/IkMGAWMLSLZni0DOU= +github.com/spacemeshos/api/release/go v1.55.1-0.20241118094246-cc3dcef1a261 h1:Y3fMqTMt4ewAj7hdMDfJMI30CTXGyfMI7gMwfVYaLk0= +github.com/spacemeshos/api/release/go v1.55.1-0.20241118094246-cc3dcef1a261/go.mod h1:6o17nhNyXpbVeijAQqkZfL8Pe/IkMGAWMLSLZni0DOU= github.com/spacemeshos/economics v0.1.4 h1:twlawrcQhYNqPgyDv08+24EL/OgUKz3d7q+PvJIAND0= github.com/spacemeshos/economics v0.1.4/go.mod h1:6HKWKiKdxjVQcGa2z/wA0LR4M/DzKib856bP16yqNmQ= github.com/spacemeshos/fixed v0.1.2 h1:pENQ8pXFAqin3f15ZLoOVVeSgcmcFJ0IFdFm4+9u4SM= From 5c7d3cd12f7c0e80391eff17588ccc70a74d622d Mon Sep 17 00:00:00 2001 From: Kacper Sawicki Date: Mon, 18 Nov 2024 13:10:39 +0100 Subject: [PATCH 6/8] Update activation/identity_states.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bartosz Różański --- activation/identity_states.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/activation/identity_states.go b/activation/identity_states.go index b9cbf907ac..ed439d8cbc 100644 --- a/activation/identity_states.go +++ b/activation/identity_states.go @@ -78,13 +78,9 @@ type IdentityStateInfo struct { Time time.Time } -type Identity struct { - History []IdentityStateInfo -} - type IdentityStateStorage struct { mu sync.RWMutex - identities map[types.NodeID]*Identity + identities map[types.NodeID][]IdentityStateInfo } func NewIdentityStateStorage() *IdentityStateStorage { From be6c4b1d426dce64bb3facb6e62eb2ff3e988c8e Mon Sep 17 00:00:00 2001 From: Kacper Sawicki Date: Mon, 18 Nov 2024 13:17:20 +0100 Subject: [PATCH 7/8] Remove commented code --- node/node.go | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/node/node.go b/node/node.go index cc1c46fc23..589dc38efd 100644 --- a/node/node.go +++ b/node/node.go @@ -1674,16 +1674,6 @@ func (app *App) grpcService(svc grpcserver.Service, lg log.Log) (grpcserver.Serv app.grpcServices[svc] = service return service, nil case v2alpha1.SmeshingIdentities: - //nodeIds := make(map[types.NodeID]struct{}) - //for _, signer := range app.signers { - // nodeIds[signer.NodeID()] = struct{}{} - //} - // - //configuredPoets := make(map[string]struct{}) - //for _, server := range app.Config.PoetServers { - // configuredPoets[server.Address] = struct{}{} - //} - service := v2alpha1.NewSmeshingIdentitiesService(app.idStates) app.grpcServices[svc] = service return service, nil From 5e802e97aab98a45a22bb5d150ca8d2d58381a2d Mon Sep 17 00:00:00 2001 From: Kacper Sawicki Date: Mon, 18 Nov 2024 13:41:08 +0100 Subject: [PATCH 8/8] Apply review suggestions --- activation/identity_states.go | 16 +++++++-------- activation/interface.go | 4 ++-- activation/mocks.go | 20 +++++++++---------- api/grpcserver/v2alpha1/interface.go | 2 +- api/grpcserver/v2alpha1/mocks.go | 10 +++++----- .../v2alpha1/smeshing_identities.go | 19 ++++++++---------- go.mod | 4 ++-- go.sum | 8 ++++---- 8 files changed, 39 insertions(+), 44 deletions(-) diff --git a/activation/identity_states.go b/activation/identity_states.go index ed439d8cbc..afd7e8d80f 100644 --- a/activation/identity_states.go +++ b/activation/identity_states.go @@ -85,7 +85,7 @@ type IdentityStateStorage struct { func NewIdentityStateStorage() *IdentityStateStorage { return &IdentityStateStorage{ - identities: make(map[types.NodeID]*Identity), + identities: make(map[types.NodeID][]IdentityStateInfo), } } @@ -99,16 +99,14 @@ func (s *IdentityStateStorage) Set( defer s.mu.Unlock() if _, exists := s.identities[id]; !exists { - s.identities[id] = &Identity{ - History: []IdentityStateInfo{}, - } + s.identities[id] = []IdentityStateInfo{} } - if len(s.identities[id].History) > 100 { - s.identities[id].History = s.identities[id].History[1:] + if len(s.identities[id]) > 100 { + s.identities[id] = s.identities[id][1:] } - s.identities[id].History = append(s.identities[id].History, IdentityStateInfo{ + s.identities[id] = append(s.identities[id], IdentityStateInfo{ State: newState, PublishEpoch: publishEpoch, Message: message, @@ -116,7 +114,7 @@ func (s *IdentityStateStorage) Set( }) } -func (s *IdentityStateStorage) Get(id types.NodeID) (*Identity, error) { +func (s *IdentityStateStorage) Get(id types.NodeID) ([]IdentityStateInfo, error) { s.mu.RLock() defer s.mu.RUnlock() @@ -127,7 +125,7 @@ func (s *IdentityStateStorage) Get(id types.NodeID) (*Identity, error) { return state, nil } -func (s *IdentityStateStorage) All() map[types.NodeID]*Identity { +func (s *IdentityStateStorage) All() map[types.NodeID][]IdentityStateInfo { s.mu.RLock() defer s.mu.RUnlock() return s.identities diff --git a/activation/interface.go b/activation/interface.go index 6587108e1f..1f6b0c97cf 100644 --- a/activation/interface.go +++ b/activation/interface.go @@ -235,6 +235,6 @@ type PostStates interface { type IdentityStates interface { Set(id types.NodeID, publishEpoch *types.EpochID, newState IdentityState, message string) - Get(id types.NodeID) (*Identity, error) - All() map[types.NodeID]*Identity + Get(id types.NodeID) ([]IdentityStateInfo, error) + All() map[types.NodeID][]IdentityStateInfo } diff --git a/activation/mocks.go b/activation/mocks.go index 99b8626d09..ec655cc456 100644 --- a/activation/mocks.go +++ b/activation/mocks.go @@ -2718,10 +2718,10 @@ func (m *MockIdentityStates) EXPECT() *MockIdentityStatesMockRecorder { } // All mocks base method. -func (m *MockIdentityStates) All() map[types.NodeID]*Identity { +func (m *MockIdentityStates) All() map[types.NodeID][]IdentityStateInfo { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "All") - ret0, _ := ret[0].(map[types.NodeID]*Identity) + ret0, _ := ret[0].(map[types.NodeID][]IdentityStateInfo) return ret0 } @@ -2738,28 +2738,28 @@ type MockIdentityStatesAllCall struct { } // Return rewrite *gomock.Call.Return -func (c *MockIdentityStatesAllCall) Return(arg0 map[types.NodeID]*Identity) *MockIdentityStatesAllCall { +func (c *MockIdentityStatesAllCall) Return(arg0 map[types.NodeID][]IdentityStateInfo) *MockIdentityStatesAllCall { c.Call = c.Call.Return(arg0) return c } // Do rewrite *gomock.Call.Do -func (c *MockIdentityStatesAllCall) Do(f func() map[types.NodeID]*Identity) *MockIdentityStatesAllCall { +func (c *MockIdentityStatesAllCall) Do(f func() map[types.NodeID][]IdentityStateInfo) *MockIdentityStatesAllCall { c.Call = c.Call.Do(f) return c } // DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *MockIdentityStatesAllCall) DoAndReturn(f func() map[types.NodeID]*Identity) *MockIdentityStatesAllCall { +func (c *MockIdentityStatesAllCall) DoAndReturn(f func() map[types.NodeID][]IdentityStateInfo) *MockIdentityStatesAllCall { c.Call = c.Call.DoAndReturn(f) return c } // Get mocks base method. -func (m *MockIdentityStates) Get(id types.NodeID) (*Identity, error) { +func (m *MockIdentityStates) Get(id types.NodeID) ([]IdentityStateInfo, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Get", id) - ret0, _ := ret[0].(*Identity) + ret0, _ := ret[0].([]IdentityStateInfo) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -2777,19 +2777,19 @@ type MockIdentityStatesGetCall struct { } // Return rewrite *gomock.Call.Return -func (c *MockIdentityStatesGetCall) Return(arg0 *Identity, arg1 error) *MockIdentityStatesGetCall { +func (c *MockIdentityStatesGetCall) Return(arg0 []IdentityStateInfo, arg1 error) *MockIdentityStatesGetCall { c.Call = c.Call.Return(arg0, arg1) return c } // Do rewrite *gomock.Call.Do -func (c *MockIdentityStatesGetCall) Do(f func(types.NodeID) (*Identity, error)) *MockIdentityStatesGetCall { +func (c *MockIdentityStatesGetCall) Do(f func(types.NodeID) ([]IdentityStateInfo, error)) *MockIdentityStatesGetCall { c.Call = c.Call.Do(f) return c } // DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *MockIdentityStatesGetCall) DoAndReturn(f func(types.NodeID) (*Identity, error)) *MockIdentityStatesGetCall { +func (c *MockIdentityStatesGetCall) DoAndReturn(f func(types.NodeID) ([]IdentityStateInfo, error)) *MockIdentityStatesGetCall { c.Call = c.Call.DoAndReturn(f) return c } diff --git a/api/grpcserver/v2alpha1/interface.go b/api/grpcserver/v2alpha1/interface.go index f1bbb1107c..2e1a872f03 100644 --- a/api/grpcserver/v2alpha1/interface.go +++ b/api/grpcserver/v2alpha1/interface.go @@ -12,5 +12,5 @@ type malfeasanceInfo interface { } type identityState interface { - All() map[types.NodeID]*activation.Identity + All() map[types.NodeID][]activation.IdentityStateInfo } diff --git a/api/grpcserver/v2alpha1/mocks.go b/api/grpcserver/v2alpha1/mocks.go index 8485ff121f..9c712042d8 100644 --- a/api/grpcserver/v2alpha1/mocks.go +++ b/api/grpcserver/v2alpha1/mocks.go @@ -105,10 +105,10 @@ func (m *MockidentityState) EXPECT() *MockidentityStateMockRecorder { } // All mocks base method. -func (m *MockidentityState) All() map[types.NodeID]*activation.Identity { +func (m *MockidentityState) All() map[types.NodeID][]activation.IdentityStateInfo { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "All") - ret0, _ := ret[0].(map[types.NodeID]*activation.Identity) + ret0, _ := ret[0].(map[types.NodeID][]activation.IdentityStateInfo) return ret0 } @@ -125,19 +125,19 @@ type MockidentityStateAllCall struct { } // Return rewrite *gomock.Call.Return -func (c *MockidentityStateAllCall) Return(arg0 map[types.NodeID]*activation.Identity) *MockidentityStateAllCall { +func (c *MockidentityStateAllCall) Return(arg0 map[types.NodeID][]activation.IdentityStateInfo) *MockidentityStateAllCall { c.Call = c.Call.Return(arg0) return c } // Do rewrite *gomock.Call.Do -func (c *MockidentityStateAllCall) Do(f func() map[types.NodeID]*activation.Identity) *MockidentityStateAllCall { +func (c *MockidentityStateAllCall) Do(f func() map[types.NodeID][]activation.IdentityStateInfo) *MockidentityStateAllCall { c.Call = c.Call.Do(f) return c } // DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *MockidentityStateAllCall) DoAndReturn(f func() map[types.NodeID]*activation.Identity) *MockidentityStateAllCall { +func (c *MockidentityStateAllCall) DoAndReturn(f func() map[types.NodeID][]activation.IdentityStateInfo) *MockidentityStateAllCall { c.Call = c.Call.DoAndReturn(f) return c } diff --git a/api/grpcserver/v2alpha1/smeshing_identities.go b/api/grpcserver/v2alpha1/smeshing_identities.go index 3acc18c208..9cb521d1bc 100644 --- a/api/grpcserver/v2alpha1/smeshing_identities.go +++ b/api/grpcserver/v2alpha1/smeshing_identities.go @@ -5,12 +5,10 @@ import ( "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" pb "github.com/spacemeshos/api/release/go/spacemesh/v2alpha1" - "golang.org/x/exp/maps" "google.golang.org/grpc" "google.golang.org/protobuf/types/known/timestamppb" "github.com/spacemeshos/go-spacemesh/activation" - "github.com/spacemeshos/go-spacemesh/common/types" ) const SmeshingIdentities = "smeshing_identities_v2alpha1" @@ -59,16 +57,15 @@ func (s *SmeshingIdentitiesService) States( ctx context.Context, _ *pb.IdentityStatesRequest, ) (*pb.IdentityStatesResponse, error) { - pbIdentities := make(map[types.NodeID]*pb.Identity) + pbIdentities := make(map[string]*pb.Identity) - for desc, state := range s.states.All() { - pbIdentities[desc] = &pb.Identity{ - SmesherId: desc.Bytes(), - History: []*pb.IdentityStateInfo{}, + for nodeId, history := range s.states.All() { + pbIdentities[nodeId.String()] = &pb.Identity{ + History: []*pb.IdentityStateInfo{}, } - for i := len(state.History) - 1; i >= 0; i-- { - info := state.History[i] + for i := len(history) - 1; i >= 0; i-- { + info := history[i] ts := timestamppb.New(info.Time) identityStateInfo := &pb.IdentityStateInfo{ State: statusMap[info.State], @@ -79,9 +76,9 @@ func (s *SmeshingIdentitiesService) States( epoch := info.PublishEpoch.Uint32() identityStateInfo.PublishEpoch = &epoch } - pbIdentities[desc].History = append(pbIdentities[desc].History, identityStateInfo) + pbIdentities[nodeId.String()].History = append(pbIdentities[nodeId.String()].History, identityStateInfo) } } - return &pb.IdentityStatesResponse{Identities: maps.Values(pbIdentities)}, nil + return &pb.IdentityStatesResponse{Identities: pbIdentities}, nil } diff --git a/go.mod b/go.mod index 283602610f..f4ebced795 100644 --- a/go.mod +++ b/go.mod @@ -40,7 +40,7 @@ require ( github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 github.com/seehuhn/mt19937 v1.0.0 github.com/slok/go-http-metrics v0.13.0 - github.com/spacemeshos/api/release/go v1.55.1-0.20241118094246-cc3dcef1a261 + github.com/spacemeshos/api/release/go v1.56.1-0.20241118123333-4a30c0bddda2 github.com/spacemeshos/economics v0.1.4 github.com/spacemeshos/fixed v0.1.2 github.com/spacemeshos/go-scale v1.2.1 @@ -61,7 +61,7 @@ require ( golang.org/x/time v0.7.0 google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 google.golang.org/grpc v1.68.0 - google.golang.org/protobuf v1.35.1 + google.golang.org/protobuf v1.35.2 k8s.io/api v0.31.2 k8s.io/apimachinery v0.31.2 k8s.io/client-go v0.31.2 diff --git a/go.sum b/go.sum index 4597a60197..c8148de751 100644 --- a/go.sum +++ b/go.sum @@ -636,8 +636,8 @@ github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:Udh github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= -github.com/spacemeshos/api/release/go v1.55.1-0.20241118094246-cc3dcef1a261 h1:Y3fMqTMt4ewAj7hdMDfJMI30CTXGyfMI7gMwfVYaLk0= -github.com/spacemeshos/api/release/go v1.55.1-0.20241118094246-cc3dcef1a261/go.mod h1:6o17nhNyXpbVeijAQqkZfL8Pe/IkMGAWMLSLZni0DOU= +github.com/spacemeshos/api/release/go v1.56.1-0.20241118123333-4a30c0bddda2 h1:+T5J7rfjQJj8ljfwsWHRO8Gt/wf7Bpo1spFlalYEuAA= +github.com/spacemeshos/api/release/go v1.56.1-0.20241118123333-4a30c0bddda2/go.mod h1:w/WRxR8JVmaeKqEEyL6DCoQxt3oyZOTv4uQSdMXlucM= github.com/spacemeshos/economics v0.1.4 h1:twlawrcQhYNqPgyDv08+24EL/OgUKz3d7q+PvJIAND0= github.com/spacemeshos/economics v0.1.4/go.mod h1:6HKWKiKdxjVQcGa2z/wA0LR4M/DzKib856bP16yqNmQ= github.com/spacemeshos/fixed v0.1.2 h1:pENQ8pXFAqin3f15ZLoOVVeSgcmcFJ0IFdFm4+9u4SM= @@ -971,8 +971,8 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= -google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= +google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=