From 20ea41bad4e168bf31e6765c2eac6cdc60e89e80 Mon Sep 17 00:00:00 2001 From: anhthii Date: Sun, 15 Mar 2026 22:16:50 +0700 Subject: [PATCH 01/11] Improve NATS connection resilience with TCP keepalive and ping intervals Add custom dialer with TCP keepalive (30s), NATS ping interval (20s/3 outstanding), 16MB reconnect buffer, and custom inbox prefix to prevent AWS NAT Gateway idle timeout from silently killing connections. --- cmd/mpcium/main.go | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/cmd/mpcium/main.go b/cmd/mpcium/main.go index ad801ef..0de8f9d 100644 --- a/cmd/mpcium/main.go +++ b/cmd/mpcium/main.go @@ -3,6 +3,7 @@ package main import ( "context" "fmt" + "net" "os" "os/signal" "path/filepath" @@ -582,8 +583,27 @@ func GetNATSConnection(environment string, appConfig *config.AppConfig) (*nats.C opts := []nats.Option{ nats.MaxReconnects(-1), // retry forever nats.ReconnectWait(2 * time.Second), - nats.DisconnectHandler(func(nc *nats.Conn) { - logger.Warn("Disconnected from NATS") + nats.ReconnectBufSize(16 * 1024 * 1024), // 16MB buffer during reconnect + // Use a custom dialer with TCP keepalive to prevent servers from killing idle connections + nats.Dialer(&net.Dialer{ + Timeout: 5 * time.Second, + KeepAlive: 30 * time.Second, // TCP keepalive every 30s — counts as wire activity for AWS + }), + // Ping every 20s, fail after 3 missed pings (60s). + // This detects dead connections well before AWS NAT Gateway's + // 350s idle timeout kills the TCP connection silently. + nats.PingInterval(20 * time.Second), + nats.MaxPingsOutstanding(3), + // Enable TCP keepalive to prevent network gateway from killing idle connections. + // This sends TCP-level keepalive probes that count as wire activity, + // preventing NAT Gateway / NLB idle timeout eviction. + nats.CustomInboxPrefix("_INBOX_mpcium"), + nats.DisconnectErrHandler(func(nc *nats.Conn, err error) { + if err != nil { + logger.Warn("Disconnected from NATS", "error", err.Error()) + } else { + logger.Warn("Disconnected from NATS") + } }), nats.ReconnectHandler(func(nc *nats.Conn) { logger.Info("Reconnected to NATS", "url", nc.ConnectedUrl()) From 4684c767dd0ce25c0bc8acc8f3b4897a02daa061 Mon Sep 17 00:00:00 2001 From: anhthii Date: Sun, 15 Mar 2026 22:17:10 +0700 Subject: [PATCH 02/11] Add consecutive failure threshold before evicting peers from Consul Require 5 consecutive health check failures (~25s) before removing a peer from Consul, preventing transient NATS reconnections from cascading into unnecessary peer eviction and ECDH re-exchange. --- pkg/mpc/registry.go | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/pkg/mpc/registry.go b/pkg/mpc/registry.go index 9c4868a..21afe42 100644 --- a/pkg/mpc/registry.go +++ b/pkg/mpc/registry.go @@ -252,6 +252,12 @@ func (r *registry) WatchPeersReady() { } func (r *registry) checkPeersHealth() { + // Track consecutive failures per peer before evicting from Consul. + // This prevents transient NATS reconnections (e.g. AWS idle timeout kills) + // from immediately cascading into peer removal + ECDH re-exchange. + failureCount := make(map[string]int) + const maxFailures = 5 // require 5 consecutive failures (~25s) before eviction + for { time.Sleep(5 * time.Second) if !r.ArePeersReady() { @@ -266,14 +272,23 @@ func (r *registry) checkPeersHealth() { readyPeerIDs := r.getReadyPeersFromKVStore(pairs) for _, peerID := range readyPeerIDs { err := r.healthCheck.SendToOtherWithRetry(r.composeHealthCheckTopic(peerID), []byte(r.composeHealthData()), messaging.RetryConfig{ - RetryAttempt: 2, + RetryAttempt: 3, + Delay: 1 * time.Second, }) if err != nil && strings.Contains(err.Error(), "no responders") { - logger.Info("No response from peer", "peerID", peerID) - _, err := r.consulKV.Delete(r.readyKey(peerID), nil) - if err != nil { - logger.Error("Delete ready key failed", err) + failureCount[peerID]++ + logger.Warn("No response from peer", "peerID", peerID, "consecutiveFailures", failureCount[peerID], "maxFailures", maxFailures) + if failureCount[peerID] >= maxFailures { + logger.Warn("Evicting unresponsive peer from Consul", "peerID", peerID) + _, err := r.consulKV.Delete(r.readyKey(peerID), nil) + if err != nil { + logger.Error("Delete ready key failed", err) + } + delete(failureCount, peerID) } + } else { + // Reset counter on successful health check + delete(failureCount, peerID) } } } From 25e5059e008c72589fcc7d838b7b7ee706b186b4 Mon Sep 17 00:00:00 2001 From: anhthii Date: Sun, 15 Mar 2026 22:18:11 +0700 Subject: [PATCH 03/11] Add per-client result routing, peer readiness barrier, and session lifecycle improvements - Route MPC results to specific clients via clientID in topic subjects, replacing shared consumers with per-client ephemeral consumers - Replace warmUpSession() sleep with WaitForPeersReady() barrier that verifies all peers have active subscriptions before starting protocol - Add graceful session shutdown with doneCh/sendErr to prevent goroutine leaks and blocking on error channels - Add JetStream MaxAckPending for backpressure and InProgress() to prevent premature redelivery during long MPC operations - Use atomic tryAddSession/removeSession for duplicate session detection --- cmd/mpcium/main.go | 25 ++- pkg/client/client.go | 40 +++-- pkg/event/sign.go | 9 +- pkg/eventconsumer/event_consumer.go | 221 ++++++++++++++++++--------- pkg/eventconsumer/keygen_consumer.go | 30 ++-- pkg/eventconsumer/sign_consumer.go | 24 ++- pkg/messaging/jetstream_broker.go | 16 ++ pkg/messaging/message_queue.go | 40 ++++- pkg/mpc/ecdsa_keygen_session.go | 5 +- pkg/mpc/ecdsa_resharing_session.go | 5 +- pkg/mpc/ecdsa_signing_session.go | 27 +++- pkg/mpc/eddsa_keygen_session.go | 3 +- pkg/mpc/eddsa_resharing_session.go | 3 +- pkg/mpc/eddsa_signing_session.go | 23 +-- pkg/mpc/node.go | 3 + pkg/mpc/session.go | 149 ++++++++++++++---- pkg/types/initiator_msg.go | 3 + 17 files changed, 469 insertions(+), 157 deletions(-) diff --git a/cmd/mpcium/main.go b/cmd/mpcium/main.go index 0de8f9d..5568abb 100644 --- a/cmd/mpcium/main.go +++ b/cmd/mpcium/main.go @@ -189,24 +189,39 @@ func runNode(ctx context.Context, c *cli.Command) error { } pubsub := messaging.NewNATSPubSub(natsConn) + maxConcurrentKeygen := viper.GetInt("max_concurrent_keygen") + if maxConcurrentKeygen == 0 { + maxConcurrentKeygen = eventconsumer.DefaultConcurrentKeygen + } + maxConcurrentSigning := viper.GetInt("max_concurrent_signing") + if maxConcurrentSigning == 0 { + maxConcurrentSigning = eventconsumer.DefaultConcurrentSigning + } + keygenBroker, err := messaging.NewJetStreamBroker(ctx, natsConn, event.KeygenBrokerStream, []string{ event.KeygenRequestTopic, - }) + }, + messaging.WithMaxAge(24*time.Hour), + messaging.WithMaxAckPending(maxConcurrentKeygen), + ) if err != nil { logger.Fatal("Failed to create keygen jetstream broker", err) } signingBroker, err := messaging.NewJetStreamBroker(ctx, natsConn, event.SigningPublisherStream, []string{ event.SigningRequestTopic, - }) + }, + messaging.WithMaxAge(24*time.Hour), + messaging.WithMaxAckPending(maxConcurrentSigning), + ) if err != nil { logger.Fatal("Failed to create signing jetstream broker", err) } directMessaging := messaging.NewNatsDirectMessaging(natsConn) mqManager := messaging.NewNATsMessageQueueManager("mpc", []string{ - "mpc.mpc_keygen_result.*", - event.SigningResultTopic, - "mpc.mpc_reshare_result.*", + "mpc.mpc_keygen_result.>", + "mpc.mpc_signing_result.>", + "mpc.mpc_reshare_result.>", }, natsConn) genKeyResultQueue := mqManager.NewMessageQueue("mpc_keygen_result") diff --git a/pkg/client/client.go b/pkg/client/client.go index 2ed4dc4..c7c2436 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -10,6 +10,7 @@ import ( "github.com/fystack/mpcium/pkg/logger" "github.com/fystack/mpcium/pkg/messaging" "github.com/fystack/mpcium/pkg/types" + "github.com/google/uuid" "github.com/nats-io/nats.go" ) @@ -31,6 +32,7 @@ type MPCClient interface { } type mpcClient struct { + clientID string signingBroker messaging.MessageBroker keygenBroker messaging.MessageBroker pubsub messaging.PubSub @@ -47,6 +49,10 @@ type Options struct { // Signer for signing messages Signer Signer + + // ClientID uniquely identifies this client instance for result routing. + // If empty, a UUID is generated automatically. + ClientID string } // NewMPCClient creates a new MPC client using the provided options. @@ -56,6 +62,13 @@ func NewMPCClient(opts Options) MPCClient { logger.Fatal("Signer is required", nil) } + clientID := opts.ClientID + if clientID == "" { + clientID = uuid.New().String() + } + + logger.Info("Creating MPC client", "clientID", clientID) + // 2) Create the PubSub for both publish & subscribe signingBroker, err := messaging.NewJetStreamBroker( context.Background(), @@ -83,16 +96,18 @@ func NewMPCClient(opts Options) MPCClient { pubsub := messaging.NewNATSPubSub(opts.NatsConn) manager := messaging.NewNATsMessageQueueManager("mpc", []string{ - "mpc.mpc_keygen_result.*", - "mpc.mpc_signing_result.*", - "mpc.mpc_reshare_result.*", + "mpc.mpc_keygen_result.>", + "mpc.mpc_signing_result.>", + "mpc.mpc_reshare_result.>", }, opts.NatsConn) - genKeySuccessQueue := manager.NewMessageQueue("mpc_keygen_result") - signResultQueue := manager.NewMessageQueue("mpc_signing_result") - reshareSuccessQueue := manager.NewMessageQueue("mpc_reshare_result") + // Per-client consumers: each client only receives results addressed to its clientID. + genKeySuccessQueue := manager.NewClientMessageQueue("mpc_keygen_result", clientID) + signResultQueue := manager.NewClientMessageQueue("mpc_signing_result", clientID) + reshareSuccessQueue := manager.NewClientMessageQueue("mpc_reshare_result", clientID) return &mpcClient{ + clientID: clientID, signingBroker: signingBroker, keygenBroker: keygenBroker, pubsub: pubsub, @@ -113,6 +128,7 @@ func (c *mpcClient) CreateWalletWithAuthorizers(walletID string, authorizerSigna // build the message msg := &types.GenerateKeyMessage{ WalletID: walletID, + ClientID: c.clientID, AuthorizerSignatures: authorizerSignatures, } // compute the canonical raw bytes @@ -139,7 +155,8 @@ func (c *mpcClient) CreateWalletWithAuthorizers(walletID string, authorizerSigna // The callback will be invoked whenever a wallet creation result is received. func (c *mpcClient) OnWalletCreationResult(callback func(event event.KeygenResultEvent)) error { - err := c.genKeySuccessQueue.Dequeue(GenerateWalletSuccessTopic, func(msg []byte) error { + topic := fmt.Sprintf("mpc.mpc_keygen_result.%s.*", c.clientID) + err := c.genKeySuccessQueue.Dequeue(topic, func(msg []byte) error { var event event.KeygenResultEvent err := json.Unmarshal(msg, &event) if err != nil { @@ -158,6 +175,7 @@ func (c *mpcClient) OnWalletCreationResult(callback func(event event.KeygenResul // SignTransaction builds a SignTxMessage, signs it, and publishes it. func (c *mpcClient) SignTransaction(msg *types.SignTxMessage) error { + msg.ClientID = c.clientID // compute the canonical raw bytes (omitting Signature field) raw, err := msg.Raw() if err != nil { @@ -181,7 +199,8 @@ func (c *mpcClient) SignTransaction(msg *types.SignTxMessage) error { } func (c *mpcClient) OnSignResult(callback func(event event.SigningResultEvent)) error { - err := c.signResultQueue.Dequeue(event.SigningResultCompleteTopic, func(msg []byte) error { + topic := fmt.Sprintf("mpc.mpc_signing_result.%s.*", c.clientID) + err := c.signResultQueue.Dequeue(topic, func(msg []byte) error { var event event.SigningResultEvent err := json.Unmarshal(msg, &event) if err != nil { @@ -199,6 +218,7 @@ func (c *mpcClient) OnSignResult(callback func(event event.SigningResultEvent)) } func (c *mpcClient) Resharing(msg *types.ResharingMessage) error { + msg.ClientID = c.clientID // compute the canonical raw bytes raw, err := msg.Raw() if err != nil { @@ -222,8 +242,8 @@ func (c *mpcClient) Resharing(msg *types.ResharingMessage) error { } func (c *mpcClient) OnResharingResult(callback func(event event.ResharingResultEvent)) error { - - err := c.reshareSuccessQueue.Dequeue(ResharingSuccessTopic, func(msg []byte) error { + topic := fmt.Sprintf("mpc.mpc_reshare_result.%s.*", c.clientID) + err := c.reshareSuccessQueue.Dequeue(topic, func(msg []byte) error { logger.Info("Received reshare success message", "raw", string(msg)) var event event.ResharingResultEvent err := json.Unmarshal(msg, &event) diff --git a/pkg/event/sign.go b/pkg/event/sign.go index ebbd077..da72d34 100644 --- a/pkg/event/sign.go +++ b/pkg/event/sign.go @@ -1,11 +1,10 @@ package event const ( - SigningPublisherStream = "mpc-signing" - SigningConsumerStream = "mpc-signing-consumer" - SigningRequestTopic = "mpc.signing_request.*" - SigningResultTopic = "mpc.mpc_signing_result.*" - SigningResultCompleteTopic = "mpc.mpc_signing_result.complete" + SigningPublisherStream = "mpc-signing" + SigningConsumerStream = "mpc-signing-consumer" + SigningRequestTopic = "mpc.signing_request.*" + SigningResultTopic = "mpc.mpc_signing_result.>" ) type SigningResultEvent struct { diff --git a/pkg/eventconsumer/event_consumer.go b/pkg/eventconsumer/event_consumer.go index 087ac67..ad8b70b 100644 --- a/pkg/eventconsumer/event_consumer.go +++ b/pkg/eventconsumer/event_consumer.go @@ -156,31 +156,43 @@ func (ec *eventConsumer) handleKeyGenEvent(natMsg *nats.Msg) { var msg types.GenerateKeyMessage if err := json.Unmarshal(raw, &msg); err != nil { logger.Error("Failed to unmarshal keygen message", err) - ec.handleKeygenSessionError(msg.WalletID, err, "Failed to unmarshal keygen message", natMsg) + ec.handleKeygenSessionError(msg.ClientID, msg.WalletID, err, "Failed to unmarshal keygen message", natMsg) return } if err := ec.identityStore.VerifyInitiatorMessage(&msg); err != nil { logger.Error("Failed to verify initiator message", err) - ec.handleKeygenSessionError(msg.WalletID, err, "Failed to verify initiator message", natMsg) + ec.handleKeygenSessionError(msg.ClientID, msg.WalletID, err, "Failed to verify initiator message", natMsg) return } if err := ec.identityStore.AuthorizeInitiatorMessage(&msg); err != nil { logger.Error("Failed to authorize initiator message", err) - ec.handleKeygenSessionError(msg.WalletID, err, "Failed to authorize initiator message", natMsg) + ec.handleKeygenSessionError(msg.ClientID, msg.WalletID, err, "Failed to authorize initiator message", natMsg) return } + clientID := msg.ClientID walletID := msg.WalletID + + // Guard against duplicate keygen sessions for the same walletID. + // Under heavy load, the keygen consumer may NAK and JetStream redelivers, + // creating a second session on the same NATS topics which causes VSS verify failures. + if !ec.tryAddSession(walletID, "keygen") { + duplicateErr := fmt.Errorf("duplicate keygen request detected for walletID=%s", walletID) + ec.handleKeygenSessionError(clientID, walletID, duplicateErr, "Duplicate keygen session", natMsg) + return + } + defer ec.removeSession(walletID, "keygen") + ecdsaSession, err := ec.node.CreateKeyGenSession(mpc.SessionTypeECDSA, walletID, ec.mpcThreshold, ec.genKeyResultQueue) if err != nil { - ec.handleKeygenSessionError(walletID, err, "Failed to create ECDSA key generation session", natMsg) + ec.handleKeygenSessionError(clientID, walletID, err, "Failed to create ECDSA key generation session", natMsg) return } eddsaSession, err := ec.node.CreateKeyGenSession(mpc.SessionTypeEDDSA, walletID, ec.mpcThreshold, ec.genKeyResultQueue) if err != nil { - ec.handleKeygenSessionError(walletID, err, "Failed to create EdDSA key generation session", natMsg) + ec.handleKeygenSessionError(clientID, walletID, err, "Failed to create EdDSA key generation session", natMsg) return } ecdsaSession.Init() @@ -203,7 +215,7 @@ func (ec *eventConsumer) handleKeyGenEvent(natMsg *nats.Msg) { successEvent.ECDSAPubKey = ecdsaSession.GetPubKeyResult() case err := <-ecdsaSession.ErrChan(): logger.Error("ECDSA keygen session error", err) - ec.handleKeygenSessionError(walletID, err, "ECDSA keygen session error", natMsg) + ec.handleKeygenSessionError(clientID, walletID, err, "ECDSA keygen session error", natMsg) errorChan <- err doneEcdsa() } @@ -215,7 +227,7 @@ func (ec *eventConsumer) handleKeyGenEvent(natMsg *nats.Msg) { successEvent.EDDSAPubKey = eddsaSession.GetPubKeyResult() case err := <-eddsaSession.ErrChan(): logger.Error("EdDSA keygen session error", err) - ec.handleKeygenSessionError(walletID, err, "EdDSA keygen session error", natMsg) + ec.handleKeygenSessionError(clientID, walletID, err, "EdDSA keygen session error", natMsg) errorChan <- err doneEddsa() } @@ -224,8 +236,25 @@ func (ec *eventConsumer) handleKeyGenEvent(natMsg *nats.Msg) { ecdsaSession.ListenToIncomingMessageAsync() eddsaSession.ListenToIncomingMessageAsync() - // Temporary delay for peer setup - ec.warmUpSession() + // Verify all peers have their subscriptions active before starting. + // Run both barriers in parallel since they use independent topics. + var barrierErr error + var barrierWg sync.WaitGroup + barrierWg.Go(func() { + if err := ecdsaSession.WaitForPeersReady(); err != nil { + barrierErr = fmt.Errorf("ECDSA: %w", err) + } + }) + barrierWg.Go(func() { + if err := eddsaSession.WaitForPeersReady(); err != nil { + barrierErr = fmt.Errorf("EDDSA: %w", err) + } + }) + barrierWg.Wait() + if barrierErr != nil { + ec.handleKeygenSessionError(clientID, walletID, barrierErr, "Peers not ready before keygen", natMsg) + return + } go ecdsaSession.GenerateKey(doneEcdsa) go eddsaSession.GenerateKey(doneEddsa) @@ -249,25 +278,25 @@ func (ec *eventConsumer) handleKeyGenEvent(natMsg *nats.Msg) { case <-baseCtx.Done(): // timeout occurred logger.Warn("Key generation timed out", "walletID", walletID, "timeout", KeyGenTimeOut) - ec.handleKeygenSessionError(walletID, fmt.Errorf("keygen session timed out after %v", KeyGenTimeOut), "Key generation timed out", natMsg) + ec.handleKeygenSessionError(clientID, walletID, fmt.Errorf("keygen session timed out after %v", KeyGenTimeOut), "Key generation timed out", natMsg) return } payload, err := json.Marshal(successEvent) if err != nil { logger.Error("Failed to marshal keygen success event", err) - ec.handleKeygenSessionError(walletID, err, "Failed to marshal keygen success event", natMsg) + ec.handleKeygenSessionError(clientID, walletID, err, "Failed to marshal keygen success event", natMsg) return } - key := fmt.Sprintf(mpc.TypeGenerateWalletResultFmt, walletID) + resultTopic := fmt.Sprintf(mpc.TypeGenerateWalletResultFmt, clientID, walletID) if err := ec.genKeyResultQueue.Enqueue( - key, + resultTopic, payload, &messaging.EnqueueOptions{IdempotententKey: composeKeygenIdempotentKey(walletID, natMsg)}, ); err != nil { logger.Error("Failed to publish key generation success message", err) - ec.handleKeygenSessionError(walletID, err, "Failed to publish key generation success message", natMsg) + ec.handleKeygenSessionError(clientID, walletID, err, "Failed to publish key generation success message", natMsg) return } ec.sendReplyToRemoveMsg(natMsg) @@ -275,7 +304,7 @@ func (ec *eventConsumer) handleKeyGenEvent(natMsg *nats.Msg) { } // handleKeygenSessionError handles errors that occur during key generation -func (ec *eventConsumer) handleKeygenSessionError(walletID string, err error, contextMsg string, natMsg *nats.Msg) { +func (ec *eventConsumer) handleKeygenSessionError(clientID, walletID string, err error, contextMsg string, natMsg *nats.Msg) { fullErrMsg := fmt.Sprintf("%s: %v", contextMsg, err) errorCode := event.GetErrorCodeFromError(err) keygenResult := event.KeygenResultEvent{ @@ -293,8 +322,8 @@ func (ec *eventConsumer) handleKeygenSessionError(walletID string, err error, co return } - key := fmt.Sprintf(mpc.TypeGenerateWalletResultFmt, walletID) - err = ec.genKeyResultQueue.Enqueue(key, keygenResultBytes, &messaging.EnqueueOptions{ + resultTopic := fmt.Sprintf(mpc.TypeGenerateWalletResultFmt, clientID, walletID) + err = ec.genKeyResultQueue.Enqueue(resultTopic, keygenResultBytes, &messaging.EnqueueOptions{ IdempotententKey: composeKeygenIdempotentKey(walletID, natMsg), }) if err != nil { @@ -365,6 +394,9 @@ func (ec *eventConsumer) handleSigningEvent(natMsg *nats.Msg) { return } + // Extract clientID from the message (set by the originating client). + clientID := msg.ClientID + logger.Info( "Received signing event", "waleltID", @@ -373,14 +405,17 @@ func (ec *eventConsumer) handleSigningEvent(natMsg *nats.Msg) { msg.KeyType, "tx", msg.TxID, + "clientID", + clientID, "Id", ec.node.ID(), ) - // Check for duplicate session and track if new - if ec.checkDuplicateSession(msg.WalletID, msg.TxID) { + // Atomically check for duplicate session and track if new + if !ec.tryAddSession(msg.WalletID, msg.TxID) { duplicateErr := fmt.Errorf("duplicate signing request detected for walletID=%s txID=%s", msg.WalletID, msg.TxID) ec.handleSigningSessionError( + clientID, msg.WalletID, msg.TxID, msg.NetworkInternalCode, @@ -400,6 +435,7 @@ func (ec *eventConsumer) handleSigningEvent(natMsg *nats.Msg) { mpc.SessionTypeECDSA, msg.WalletID, msg.TxID, + clientID, msg.NetworkInternalCode, ec.signingResultQueue, msg.DerivationPath, @@ -410,6 +446,7 @@ func (ec *eventConsumer) handleSigningEvent(natMsg *nats.Msg) { mpc.SessionTypeEDDSA, msg.WalletID, msg.TxID, + clientID, msg.NetworkInternalCode, ec.signingResultQueue, msg.DerivationPath, @@ -441,6 +478,7 @@ func (ec *eventConsumer) handleSigningEvent(natMsg *nats.Msg) { } ec.handleSigningSessionError( + clientID, msg.WalletID, msg.TxID, msg.NetworkInternalCode, @@ -455,6 +493,7 @@ func (ec *eventConsumer) handleSigningEvent(natMsg *nats.Msg) { err = session.Init(txBigInt) if err != nil { ec.handleSigningSessionError( + clientID, msg.WalletID, msg.TxID, msg.NetworkInternalCode, @@ -465,9 +504,6 @@ func (ec *eventConsumer) handleSigningEvent(natMsg *nats.Msg) { return } - // Mark session as already processed - ec.addSession(msg.WalletID, msg.TxID) - ctx, done := context.WithCancel(context.Background()) go func() { for { @@ -477,6 +513,7 @@ func (ec *eventConsumer) handleSigningEvent(natMsg *nats.Msg) { case err := <-session.ErrChan(): if err != nil { ec.handleSigningSessionError( + clientID, msg.WalletID, msg.TxID, msg.NetworkInternalCode, @@ -484,6 +521,10 @@ func (ec *eventConsumer) handleSigningEvent(natMsg *nats.Msg) { "Failed to sign tx", natMsg, ) + // Stop the session so Sign() goroutine exits cleanly + // instead of leaking forever on outCh/endCh. + session.Stop() + done() return } } @@ -491,14 +532,21 @@ func (ec *eventConsumer) handleSigningEvent(natMsg *nats.Msg) { }() session.ListenToIncomingMessageAsync() - // TODO: use consul distributed lock here, only sign after all nodes has already completed listing to incoming message async - // The purpose of the sleep is to be ensuring that the node has properly set up its message listeners - // before it starts the signing process. If the signing process starts sending messages before other nodes - // have set up their listeners, those messages might be missed, potentially causing the signing process to fail. - // One solution: - // The messaging includes mechanisms for direct point-to-point communication (in point2point.go). - // The nodes could explicitly coordinate through request-response patterns before starting signing - ec.warmUpSession() + + // Verify all peers have their subscriptions active before starting. + // This replaces the old warmUpSession() sleep with a proper handshake. + if err := session.WaitForPeersReady(); err != nil { + ec.handleSigningSessionError( + clientID, + msg.WalletID, + msg.TxID, + msg.NetworkInternalCode, + err, + "Peers not ready before signing", + natMsg, + ) + return + } onSuccess := func(data []byte) { done() @@ -519,13 +567,14 @@ func (ec *eventConsumer) consumeTxSigningEvent() error { return nil } -func (ec *eventConsumer) handleSigningSessionError(walletID, txID, networkInternalCode string, err error, contextMsg string, natMsg *nats.Msg) { +func (ec *eventConsumer) handleSigningSessionError(clientID, walletID, txID, networkInternalCode string, err error, contextMsg string, natMsg *nats.Msg) { fullErrMsg := fmt.Sprintf("%s: %v", contextMsg, err) errorCode := event.GetErrorCodeFromError(err) logger.Warn("Signing session error", "walletID", walletID, "txID", txID, + "clientID", clientID, "networkInternalCode", networkInternalCode, "error", err.Error(), "errorCode", errorCode, @@ -549,7 +598,8 @@ func (ec *eventConsumer) handleSigningSessionError(walletID, txID, networkIntern ) return } - err = ec.signingResultQueue.Enqueue(event.SigningResultCompleteTopic, signingResultBytes, &messaging.EnqueueOptions{ + resultTopic := fmt.Sprintf(mpc.TypeSigningResultFmt, clientID, txID) + err = ec.signingResultQueue.Enqueue(resultTopic, signingResultBytes, &messaging.EnqueueOptions{ IdempotententKey: composeSigningIdempotentKey(txID, natMsg), }) if err != nil { @@ -582,12 +632,13 @@ func (ec *eventConsumer) consumeReshareEvent() error { var msg types.ResharingMessage if err := json.Unmarshal(natMsg.Data, &msg); err != nil { logger.Error("Failed to unmarshal resharing message", err) - ec.handleReshareSessionError(msg.WalletID, msg.KeyType, msg.NewThreshold, err, "Failed to unmarshal resharing message", natMsg) + ec.handleReshareSessionError(msg.ClientID, msg.WalletID, msg.KeyType, msg.NewThreshold, err, "Failed to unmarshal resharing message", natMsg) return } if msg.SessionID == "" { ec.handleReshareSessionError( + msg.ClientID, msg.WalletID, msg.KeyType, msg.NewThreshold, @@ -600,23 +651,24 @@ func (ec *eventConsumer) consumeReshareEvent() error { if err := ec.identityStore.VerifyInitiatorMessage(&msg); err != nil { logger.Error("Failed to verify initiator message", err) - ec.handleReshareSessionError(msg.WalletID, msg.KeyType, msg.NewThreshold, err, "Failed to verify initiator message", natMsg) + ec.handleReshareSessionError(msg.ClientID, msg.WalletID, msg.KeyType, msg.NewThreshold, err, "Failed to verify initiator message", natMsg) return } if err := ec.identityStore.AuthorizeInitiatorMessage(&msg); err != nil { logger.Error("Failed to authorize initiator message", err) - ec.handleReshareSessionError(msg.WalletID, msg.KeyType, msg.NewThreshold, err, "Failed to authorize initiator message", natMsg) + ec.handleReshareSessionError(msg.ClientID, msg.WalletID, msg.KeyType, msg.NewThreshold, err, "Failed to authorize initiator message", natMsg) return } + clientID := msg.ClientID walletID := msg.WalletID keyType := msg.KeyType sessionType, err := sessionTypeFromKeyType(keyType) if err != nil { logger.Error("Failed to get session type", err) - ec.handleReshareSessionError(walletID, keyType, msg.NewThreshold, err, "Failed to get session type", natMsg) + ec.handleReshareSessionError(clientID, walletID, keyType, msg.NewThreshold, err, "Failed to get session type", natMsg) return } @@ -634,13 +686,13 @@ func (ec *eventConsumer) consumeReshareEvent() error { oldSession, err := createSession(false) if err != nil { logger.Error("Failed to create old reshare session", err, "walletID", walletID) - ec.handleReshareSessionError(walletID, keyType, msg.NewThreshold, err, "Failed to create old reshare session", natMsg) + ec.handleReshareSessionError(clientID, walletID, keyType, msg.NewThreshold, err, "Failed to create old reshare session", natMsg) return } newSession, err := createSession(true) if err != nil { logger.Error("Failed to create new reshare session", err, "walletID", walletID) - ec.handleReshareSessionError(walletID, keyType, msg.NewThreshold, err, "Failed to create new reshare session", natMsg) + ec.handleReshareSessionError(clientID, walletID, keyType, msg.NewThreshold, err, "Failed to create new reshare session", natMsg) return } @@ -662,7 +714,7 @@ func (ec *eventConsumer) consumeReshareEvent() error { if oldSession != nil { err := oldSession.Init() if err != nil { - ec.handleReshareSessionError(walletID, keyType, msg.NewThreshold, err, "Failed to init old reshare session", natMsg) + ec.handleReshareSessionError(clientID, walletID, keyType, msg.NewThreshold, err, "Failed to init old reshare session", natMsg) return } oldSession.ListenToIncomingMessageAsync() @@ -671,7 +723,7 @@ func (ec *eventConsumer) consumeReshareEvent() error { if newSession != nil { err := newSession.Init() if err != nil { - ec.handleReshareSessionError(walletID, keyType, msg.NewThreshold, err, "Failed to init new reshare session", natMsg) + ec.handleReshareSessionError(clientID, walletID, keyType, msg.NewThreshold, err, "Failed to init new reshare session", natMsg) return } newSession.ListenToIncomingMessageAsync() @@ -688,34 +740,53 @@ func (ec *eventConsumer) consumeReshareEvent() error { oldSession.ListenToPeersAsync(msg.NodeIDs) } - ec.warmUpSession() + // Verify all peers have their subscriptions active before starting. + // Run both barriers in parallel since they use independent topics. + var reshareBarrierErr error + var reshareBarrierWg sync.WaitGroup + if oldSession != nil { + reshareBarrierWg.Go(func() { + if err := oldSession.WaitForPeersReady(); err != nil { + reshareBarrierErr = fmt.Errorf("old committee: %w", err) + } + }) + } + if newSession != nil { + reshareBarrierWg.Go(func() { + if err := newSession.WaitForPeersReady(); err != nil { + reshareBarrierErr = fmt.Errorf("new committee: %w", err) + } + }) + } + reshareBarrierWg.Wait() + if reshareBarrierErr != nil { + ec.handleReshareSessionError(clientID, walletID, keyType, msg.NewThreshold, reshareBarrierErr, "Peers not ready before resharing", natMsg) + return + } + if oldSession != nil { ctxOld, doneOld := context.WithCancel(ctx) go oldSession.Reshare(doneOld) - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { for { select { case <-ctxOld.Done(): return case err := <-oldSession.ErrChan(): logger.Error("Old reshare session error", err) - ec.handleReshareSessionError(walletID, keyType, msg.NewThreshold, err, "Old reshare session error", natMsg) + ec.handleReshareSessionError(clientID, walletID, keyType, msg.NewThreshold, err, "Old reshare session error", natMsg) doneOld() return } } - }() + }) } if newSession != nil { ctxNew, doneNew := context.WithCancel(ctx) go newSession.Reshare(doneNew) - wg.Add(1) - go func() { - defer wg.Done() + wg.Go(func() { for { select { case <-ctxNew.Done(): @@ -723,12 +794,12 @@ func (ec *eventConsumer) consumeReshareEvent() error { return case err := <-newSession.ErrChan(): logger.Error("New reshare session error", err) - ec.handleReshareSessionError(walletID, keyType, msg.NewThreshold, err, "New reshare session error", natMsg) + ec.handleReshareSessionError(clientID, walletID, keyType, msg.NewThreshold, err, "New reshare session error", natMsg) doneNew() return } } - }() + }) } wg.Wait() @@ -738,20 +809,20 @@ func (ec *eventConsumer) consumeReshareEvent() error { successBytes, err := json.Marshal(successEvent) if err != nil { logger.Error("Failed to marshal reshare success event", err) - ec.handleReshareSessionError(walletID, keyType, msg.NewThreshold, err, "Failed to marshal reshare success event", natMsg) + ec.handleReshareSessionError(clientID, walletID, keyType, msg.NewThreshold, err, "Failed to marshal reshare success event", natMsg) return } - key := fmt.Sprintf(mpc.TypeReshareWalletResultFmt, msg.SessionID) + resultTopic := fmt.Sprintf(mpc.TypeReshareWalletResultFmt, clientID, msg.SessionID) err = ec.reshareResultQueue.Enqueue( - key, + resultTopic, successBytes, &messaging.EnqueueOptions{ IdempotententKey: composeReshareIdempotentKey(msg.SessionID, natMsg), }) if err != nil { logger.Error("Failed to publish reshare success message", err) - ec.handleReshareSessionError(walletID, keyType, msg.NewThreshold, err, "Failed to publish reshare success message", natMsg) + ec.handleReshareSessionError(clientID, walletID, keyType, msg.NewThreshold, err, "Failed to publish reshare success message", natMsg) return } logger.Info("[COMPLETED RESHARE] Successfully published", "walletID", walletID) @@ -766,6 +837,7 @@ func (ec *eventConsumer) consumeReshareEvent() error { // handleReshareSessionError handles errors that occur during reshare operations func (ec *eventConsumer) handleReshareSessionError( + clientID string, walletID string, keyType types.KeyType, newThreshold int, @@ -778,6 +850,7 @@ func (ec *eventConsumer) handleReshareSessionError( logger.Warn("Reshare session error", "walletID", walletID, + "clientID", clientID, "keyType", keyType, "newThreshold", newThreshold, "error", err.Error(), @@ -802,8 +875,8 @@ func (ec *eventConsumer) handleReshareSessionError( return } - key := fmt.Sprintf(mpc.TypeReshareWalletResultFmt, walletID) - err = ec.reshareResultQueue.Enqueue(key, reshareResultBytes, &messaging.EnqueueOptions{ + resultTopic := fmt.Sprintf(mpc.TypeReshareWalletResultFmt, clientID, walletID) + err = ec.reshareResultQueue.Enqueue(resultTopic, reshareResultBytes, &messaging.EnqueueOptions{ IdempotententKey: composeReshareIdempotentKey(walletID, natMsg), }) if err != nil { @@ -842,30 +915,32 @@ func (ec *eventConsumer) cleanupStaleSessions() { } } -// markSessionAsActive marks a session as active with the current timestamp -func (ec *eventConsumer) addSession(walletID, txID string) { +// tryAddSession atomically checks if a session already exists and adds it if not. +// Returns true if the session was successfully added (not a duplicate). +// Returns false if the session already exists (duplicate). +func (ec *eventConsumer) tryAddSession(walletID, txID string) bool { sessionID := fmt.Sprintf("%s-%s", walletID, txID) + ec.sessionsLock.Lock() + defer ec.sessionsLock.Unlock() + + if _, exists := ec.activeSessions[sessionID]; exists { + logger.Info("Duplicate session detected", "walletID", walletID, "txID", txID) + return false + } + ec.activeSessions[sessionID] = time.Now() - ec.sessionsLock.Unlock() + return true } -// checkAndTrackSession checks if a session already exists and tracks it if new. -// Returns true if the session is a duplicate. -func (ec *eventConsumer) checkDuplicateSession(walletID, txID string) bool { +// removeSession removes a session from the active sessions map so it can be retried. +func (ec *eventConsumer) removeSession(walletID, txID string) { sessionID := fmt.Sprintf("%s-%s", walletID, txID) - // Check for duplicate - ec.sessionsLock.RLock() - _, isDuplicate := ec.activeSessions[sessionID] - ec.sessionsLock.RUnlock() - - if isDuplicate { - logger.Info("Duplicate signing request detected", "walletID", walletID, "txID", txID) - return true - } + ec.sessionsLock.Lock() + defer ec.sessionsLock.Unlock() - return false + delete(ec.activeSessions, sessionID) } // Close and clean up diff --git a/pkg/eventconsumer/keygen_consumer.go b/pkg/eventconsumer/keygen_consumer.go index 8af027d..d4e8cf5 100644 --- a/pkg/eventconsumer/keygen_consumer.go +++ b/pkg/eventconsumer/keygen_consumer.go @@ -18,8 +18,11 @@ import ( ) const ( - // Maximum time to wait for a signing response. - keygenResponseTimeout = 30 * time.Second + // Maximum time to wait for a keygen response. + // Must be longer than KeyGenTimeOut in event_consumer.go (30s) so the + // event consumer always finishes first and sends a reply (success or error) + // before the keygen consumer gives up and NAKs. + keygenResponseTimeout = 45 * time.Second // How often to poll for the reply message. keygenPollingInterval = 500 * time.Millisecond ) @@ -161,23 +164,28 @@ func (sc *keygenConsumer) handleKeygenEvent(msg jetstream.Msg) { } }() - // Publish the signing event with the reply inbox. + // Publish the keygen event with the reply inbox. headers := map[string]string{ "SessionID": uuid.New().String(), } if err := sc.pubsub.PublishWithReply(MPCGenerateEvent, replyInbox, msg.Data(), headers); err != nil { - logger.Error("KeygenConsumer: Failed to publish signing event with reply", err) + logger.Error("KeygenConsumer: Failed to publish keygen event with reply", err) _ = msg.Nak() return } - // Poll for the reply message until timeout. + // Wait for the MPC operation to complete before ACKing the JetStream message. + // This ensures messages are not lost on restart — unACKed messages will be + // redelivered by JetStream. We use msg.InProgress() to periodically reset + // the ack deadline so JetStream does not redeliver while we're still working. + // MaxAckPending on the consumer limits concurrency: JetStream won't deliver + // new messages until in-flight ones are ACKed, providing natural backpressure. deadline := time.Now().Add(keygenResponseTimeout) for time.Now().Before(deadline) { replyMsg, err := replySub.NextMsg(keygenPollingInterval) if err != nil { - // If timeout occurs, continue trying. if err == nats.ErrTimeout { + _ = msg.InProgress() continue } logger.Error("KeygenConsumer: Error receiving reply message", err) @@ -192,7 +200,9 @@ func (sc *keygenConsumer) handleKeygenEvent(msg jetstream.Msg) { } } - logger.Warn("KeygenConsumer: Timeout waiting for keygen event response") + // Timeout: NAK so JetStream can redeliver when we have capacity. + logger.Warn("KeygenConsumer: Timeout waiting for keygen response, NAK for redelivery", + "walletID", keygenMsg.WalletID) _ = msg.Nak() } @@ -212,9 +222,9 @@ func (sc *keygenConsumer) handleKeygenError(keygenMsg types.GenerateKeyMessage, return } - topic := fmt.Sprintf(mpc.TypeGenerateWalletResultFmt, keygenResult.WalletID) - err = sc.keygenResultQueue.Enqueue(topic, keygenResultBytes, &messaging.EnqueueOptions{ - IdempotententKey: buildIdempotentKey(keygenMsg.WalletID, sessionID, mpc.TypeGenerateWalletResultFmt), + resultTopic := fmt.Sprintf(mpc.TypeGenerateWalletResultFmt, keygenMsg.ClientID, keygenResult.WalletID) + err = sc.keygenResultQueue.Enqueue(resultTopic, keygenResultBytes, &messaging.EnqueueOptions{ + IdempotententKey: buildIdempotentKey(keygenMsg.WalletID, sessionID, resultTopic), }) if err != nil { logger.Error("Failed to enqueue keygen result event", err, diff --git a/pkg/eventconsumer/sign_consumer.go b/pkg/eventconsumer/sign_consumer.go index e0ea23e..4d207ed 100644 --- a/pkg/eventconsumer/sign_consumer.go +++ b/pkg/eventconsumer/sign_consumer.go @@ -19,7 +19,10 @@ import ( const ( // Maximum time to wait for a signing response. - signingResponseTimeout = 30 * time.Second + // Must be longer than the event consumer's processing timeout so that + // the event consumer always finishes first and sends a reply before + // the signing consumer gives up and NAKs. + signingResponseTimeout = 45 * time.Second // How often to poll for the reply message. signingPollingInterval = 500 * time.Millisecond // How often to check if enough peers are ready @@ -191,13 +194,18 @@ func (sc *signingConsumer) handleSigningEvent(msg jetstream.Msg) { return } - // Poll for the reply message until timeout. + // Wait for the MPC operation to complete before ACKing the JetStream message. + // This ensures messages are not lost on restart — unACKed messages will be + // redelivered by JetStream. We use msg.InProgress() to periodically reset + // the ack deadline so JetStream does not redeliver while we're still working. + // MaxAckPending on the consumer limits concurrency: JetStream won't deliver + // new messages until in-flight ones are ACKed, providing natural backpressure. deadline := time.Now().Add(signingResponseTimeout) for time.Now().Before(deadline) { replyMsg, err := replySub.NextMsg(signingPollingInterval) if err != nil { - // If timeout occurs, continue trying. if err == nats.ErrTimeout { + _ = msg.InProgress() continue } logger.Error("SigningConsumer: Error receiving reply message", err) @@ -212,7 +220,10 @@ func (sc *signingConsumer) handleSigningEvent(msg jetstream.Msg) { } } - logger.Warn("SigningConsumer: Timeout waiting for signing event response") + // Timeout: NAK so JetStream can redeliver when we have capacity. + logger.Warn("SigningConsumer: Timeout waiting for signing response, NAK for redelivery", + "walletID", signingMsg.WalletID, + "txID", signingMsg.TxID) _ = msg.Nak() } @@ -235,8 +246,9 @@ func (sc *signingConsumer) handleSigningError(signMsg types.SignTxMessage, error return } - err = sc.signingResultQueue.Enqueue(event.SigningResultCompleteTopic, signingResultBytes, &messaging.EnqueueOptions{ - IdempotententKey: buildIdempotentKey(signMsg.TxID, sessionID, mpc.TypeSigningResultFmt), + resultTopic := fmt.Sprintf(mpc.TypeSigningResultFmt, signMsg.ClientID, signMsg.TxID) + err = sc.signingResultQueue.Enqueue(resultTopic, signingResultBytes, &messaging.EnqueueOptions{ + IdempotententKey: buildIdempotentKey(signMsg.TxID, sessionID, resultTopic), }) if err != nil { logger.Error("Failed to enqueue signing result event", err, diff --git a/pkg/messaging/jetstream_broker.go b/pkg/messaging/jetstream_broker.go index cf738a1..c70df9b 100644 --- a/pkg/messaging/jetstream_broker.go +++ b/pkg/messaging/jetstream_broker.go @@ -58,6 +58,7 @@ type brokerConfiguration struct { consumerNamePrefix string deliverPolicy jetstream.DeliverPolicy backoffDurations []time.Duration + maxAckPending int } func WithStreamDescription(description string) BrokerOption { @@ -120,6 +121,19 @@ func WithBackoffDurations(durations []time.Duration) BrokerOption { } } +// WithMaxAckPending sets the maximum number of unACKed messages the JetStream +// server will deliver to this consumer at once. Once the limit is reached, +// JetStream holds back new messages until existing ones are ACKed or NAKed. +// This provides natural backpressure: messages stay durably in the stream +// instead of being pushed to consumers that have no capacity to process them. +// Set this to match the desired processing concurrency (e.g. 2 for keygen, +// 20 for signing). +func WithMaxAckPending(maxAckPending int) BrokerOption { + return func(cfg *brokerConfiguration) { + cfg.maxAckPending = maxAckPending + } +} + type jetStreamBroker struct { config brokerConfiguration js jetstream.JetStream @@ -221,6 +235,7 @@ func (b *jetStreamBroker) CreateSubscription( DeliverPolicy: b.config.deliverPolicy, FilterSubject: subject, AckWait: b.config.ackWait, + MaxAckPending: b.config.maxAckPending, } consumer, err := b.js.CreateOrUpdateConsumer(ctx, b.config.streamName, consumerConfig) @@ -309,6 +324,7 @@ func (b *jetStreamBroker) FetchMessages( DeliverPolicy: b.config.deliverPolicy, FilterSubject: subject, AckWait: b.config.ackWait, + MaxAckPending: b.config.maxAckPending, } consumer, err := b.js.CreateOrUpdateConsumer(ctx, b.config.streamName, consumerConfig) diff --git a/pkg/messaging/message_queue.go b/pkg/messaging/message_queue.go index 32ed3f9..7745dc5 100644 --- a/pkg/messaging/message_queue.go +++ b/pkg/messaging/message_queue.go @@ -27,9 +27,11 @@ type EnqueueOptions struct { type msgQueue struct { consumerName string + streamName string js jetstream.JetStream consumer jetstream.Consumer consumerContext jetstream.ConsumeContext + ephemeral bool // if true, consumer is deleted on Close } type NATsMessageQueueManager struct { @@ -58,9 +60,9 @@ func NewNATsMessageQueueManager(queueName string, subjectWildCards []string, nc Name: queueName, Description: "Stream for " + queueName, Subjects: subjectWildCards, - MaxBytes: 10_485_760, // Light Production (Low Traffic) (10 MB) + MaxBytes: 104_857_600, // 100 MB Storage: jetstream.FileStorage, - Retention: jetstream.WorkQueuePolicy, + Retention: jetstream.LimitsPolicy, }) if err != nil { logger.Fatal("Error creating JetStream stream: ", err) @@ -101,6 +103,40 @@ func (m *NATsMessageQueueManager) NewMessageQueue(consumerName string) MessageQu return mq } +// NewClientMessageQueue creates a per-client consumer that only receives results +// addressed to this specific clientID. The consumer uses DeliverNewPolicy so it +// only sees messages published after it connects. The consumer is ephemeral +// (no Durable name) and auto-deletes after InactiveThreshold. +func (m *NATsMessageQueueManager) NewClientMessageQueue(consumerName, clientID string) MessageQueue { + mq := &msgQueue{ + consumerName: consumerName + "_" + clientID, + streamName: m.queueName, + js: m.js, + ephemeral: true, + } + // Filter to only this client's results: e.g. mpc.mpc_signing_result..> + consumerFilter := fmt.Sprintf("%s.%s.%s.>", m.queueName, consumerName, clientID) + cfg := jetstream.ConsumerConfig{ + MaxAckPending: 1000, + AckWait: 30 * time.Second, + AckPolicy: jetstream.AckExplicitPolicy, + DeliverPolicy: jetstream.DeliverNewPolicy, + InactiveThreshold: 5 * time.Minute, + FilterSubjects: []string{ + consumerFilter, + }, + MaxDeliver: 3, + } + logger.Info("Creating per-client consumer", "consumerName", mq.consumerName, "queueName", m.queueName, "filterSubject", consumerFilter) + consumer, err := m.js.CreateOrUpdateConsumer(context.Background(), m.queueName, cfg) + if err != nil { + logger.Fatal("Error creating JetStream per-client consumer: ", err) + } + + mq.consumer = consumer + return mq +} + func (mq *msgQueue) Enqueue(topic string, message []byte, options *EnqueueOptions) error { header := nats.Header{} if options != nil { diff --git a/pkg/mpc/ecdsa_keygen_session.go b/pkg/mpc/ecdsa_keygen_session.go index dcaa945..b55e56b 100644 --- a/pkg/mpc/ecdsa_keygen_session.go +++ b/pkg/mpc/ecdsa_keygen_session.go @@ -22,6 +22,7 @@ type KeyGenSession interface { Init() GenerateKey(done func()) GetPubKeyResult() []byte + WaitForPeersReady() error } type ecdsaKeygenSession struct { @@ -54,7 +55,8 @@ func newECDSAKeygenSession( selfPartyID: selfID, partyIDs: partyIDs, outCh: make(chan tss.Message), - ErrCh: make(chan error), + ErrCh: make(chan error, 1), + doneCh: make(chan struct{}), preParams: preParams, kvstore: kvstore, keyinfoStore: keyinfoStore, @@ -151,4 +153,3 @@ func (s *ecdsaKeygenSession) GenerateKey(done func()) { } } } - diff --git a/pkg/mpc/ecdsa_resharing_session.go b/pkg/mpc/ecdsa_resharing_session.go index 39ea715..29f30e6 100644 --- a/pkg/mpc/ecdsa_resharing_session.go +++ b/pkg/mpc/ecdsa_resharing_session.go @@ -23,6 +23,8 @@ type ReshareSession interface { Reshare(done func()) GetPubKeyResult() []byte GetLegacyCommitteePeers() []string + WaitForPeersReady() error + Stop() } type ecdsaReshareSession struct { @@ -68,7 +70,8 @@ func NewECDSAReshareSession( selfPartyID: selfID, partyIDs: realPartyIDs, outCh: make(chan tss.Message), - ErrCh: make(chan error), + ErrCh: make(chan error, 1), + doneCh: make(chan struct{}), preParams: preParams, kvstore: kvstore, keyinfoStore: keyinfoStore, diff --git a/pkg/mpc/ecdsa_signing_session.go b/pkg/mpc/ecdsa_signing_session.go index 4d5e0d5..dcc537a 100644 --- a/pkg/mpc/ecdsa_signing_session.go +++ b/pkg/mpc/ecdsa_signing_session.go @@ -26,6 +26,13 @@ type SigningSession interface { Init(tx *big.Int) error Sign(onSuccess func(data []byte)) + // WaitForPeersReady verifies all peers have their subscriptions active + // before starting the protocol. Replaces the fragile warmup sleep. + WaitForPeersReady() error + // Stop signals the session to terminate, allowing Sign() goroutines to exit. + Stop() + // Close cleans up subscriptions and sensitive data. + Close() error } // Ecdsa signing session @@ -35,6 +42,7 @@ type ecdsaSigningSession struct { data *keygen.LocalPartySaveData tx *big.Int txID string + clientID string networkInternalCode string derivationPath []uint32 ckd *CKD @@ -43,6 +51,7 @@ type ecdsaSigningSession struct { func newECDSASigningSession( walletID string, txID string, + clientID string, networkInternalCode string, pubSub messaging.PubSub, direct messaging.DirectMessaging, @@ -70,7 +79,8 @@ func newECDSASigningSession( selfPartyID: selfID, partyIDs: partyIDs, outCh: make(chan tss.Message), - ErrCh: make(chan error), + ErrCh: make(chan error, 1), + doneCh: make(chan struct{}), preParams: preParams, kvstore: kvstore, keyinfoStore: keyinfoStore, @@ -92,6 +102,7 @@ func newECDSASigningSession( }, endCh: make(chan *common.SignatureData), txID: txID, + clientID: clientID, networkInternalCode: networkInternalCode, derivationPath: derivationPath, ckd: ckd, @@ -166,12 +177,15 @@ func (s *ecdsaSigningSession) Sign(onSuccess func(data []byte)) { logger.Info("Starting signing", "walletID", s.walletID) go func() { if err := s.party.Start(); err != nil { - s.ErrCh <- err + s.sendErr(err) } }() for { select { + case <-s.doneCh: + logger.Info("ECDSA signing session stopped", "walletID", s.walletID) + return case msg := <-s.outCh: s.handleTssMessage(msg) case sig := <-s.endCh: @@ -184,7 +198,7 @@ func (s *ecdsaSigningSession) Sign(onSuccess func(data []byte)) { ok := ecdsa.Verify(&pk, s.tx.Bytes(), new(big.Int).SetBytes(sig.R), new(big.Int).SetBytes(sig.S)) if !ok { - s.ErrCh <- errors.New("Failed to verify signature") + s.sendErr(errors.New("Failed to verify signature")) return } @@ -200,15 +214,16 @@ func (s *ecdsaSigningSession) Sign(onSuccess func(data []byte)) { bytes, err := json.Marshal(r) if err != nil { - s.ErrCh <- errors.Wrap(err, "Failed to marshal raw signature") + s.sendErr(errors.Wrap(err, "Failed to marshal raw signature")) return } - err = s.resultQueue.Enqueue(event.SigningResultCompleteTopic, bytes, &messaging.EnqueueOptions{ + resultTopic := fmt.Sprintf(TypeSigningResultFmt, s.clientID, s.txID) + err = s.resultQueue.Enqueue(resultTopic, bytes, &messaging.EnqueueOptions{ IdempotententKey: s.idempotentKey, }) if err != nil { - s.ErrCh <- errors.Wrap(err, "Failed to publish sign success message") + s.sendErr(errors.Wrap(err, "Failed to publish sign success message")) return } diff --git a/pkg/mpc/eddsa_keygen_session.go b/pkg/mpc/eddsa_keygen_session.go index 485f052..deba0cc 100644 --- a/pkg/mpc/eddsa_keygen_session.go +++ b/pkg/mpc/eddsa_keygen_session.go @@ -43,7 +43,8 @@ func newEDDSAKeygenSession( selfPartyID: selfID, partyIDs: partyIDs, outCh: make(chan tss.Message), - ErrCh: make(chan error), + ErrCh: make(chan error, 1), + doneCh: make(chan struct{}), kvstore: kvstore, keyinfoStore: keyinfoStore, topicComposer: &TopicComposer{ diff --git a/pkg/mpc/eddsa_resharing_session.go b/pkg/mpc/eddsa_resharing_session.go index d394c42..e5a892e 100644 --- a/pkg/mpc/eddsa_resharing_session.go +++ b/pkg/mpc/eddsa_resharing_session.go @@ -59,7 +59,8 @@ func NewEDDSAReshareSession( selfPartyID: selfID, partyIDs: realPartyIDs, outCh: make(chan tss.Message), - ErrCh: make(chan error), + ErrCh: make(chan error, 1), + doneCh: make(chan struct{}), kvstore: kvstore, keyinfoStore: keyinfoStore, topicComposer: &TopicComposer{ diff --git a/pkg/mpc/eddsa_signing_session.go b/pkg/mpc/eddsa_signing_session.go index 4f859e5..01329ed 100644 --- a/pkg/mpc/eddsa_signing_session.go +++ b/pkg/mpc/eddsa_signing_session.go @@ -27,6 +27,7 @@ type eddsaSigningSession struct { data *keygen.LocalPartySaveData tx *big.Int txID string + clientID string networkInternalCode string derivationPath []uint32 ckd *CKD @@ -35,6 +36,7 @@ type eddsaSigningSession struct { func newEDDSASigningSession( walletID string, txID string, + clientID string, networkInternalCode string, pubSub messaging.PubSub, direct messaging.DirectMessaging, @@ -60,8 +62,8 @@ func newEDDSASigningSession( selfPartyID: selfID, partyIDs: partyIDs, outCh: make(chan tss.Message), - ErrCh: make(chan error), - // preParams: preParams, + ErrCh: make(chan error, 1), + doneCh: make(chan struct{}), kvstore: kvstore, keyinfoStore: keyinfoStore, topicComposer: &TopicComposer{ @@ -82,6 +84,7 @@ func newEDDSASigningSession( }, endCh: make(chan *common.SignatureData), txID: txID, + clientID: clientID, networkInternalCode: networkInternalCode, derivationPath: derivationPath, ckd: ckd, @@ -155,13 +158,15 @@ func (s *eddsaSigningSession) Sign(onSuccess func(data []byte)) { logger.Info("Starting signing", "walletID", s.walletID) go func() { if err := s.party.Start(); err != nil { - s.ErrCh <- err + s.sendErr(err) } }() for { - select { + case <-s.doneCh: + logger.Info("EDDSA signing session stopped", "walletID", s.walletID) + return case msg := <-s.outCh: s.handleTssMessage(msg) case sig := <-s.endCh: @@ -174,7 +179,7 @@ func (s *eddsaSigningSession) Sign(onSuccess func(data []byte)) { ok := edwards.Verify(&pk, s.tx.Bytes(), new(big.Int).SetBytes(sig.R), new(big.Int).SetBytes(sig.S)) if !ok { - s.ErrCh <- errors.New("Failed to verify signature") + s.sendErr(errors.New("Failed to verify signature")) return } @@ -188,15 +193,16 @@ func (s *eddsaSigningSession) Sign(onSuccess func(data []byte)) { bytes, err := json.Marshal(r) if err != nil { - s.ErrCh <- errors.Wrap(err, "Failed to marshal raw signature") + s.sendErr(errors.Wrap(err, "Failed to marshal raw signature")) return } - err = s.resultQueue.Enqueue(event.SigningResultCompleteTopic, bytes, &messaging.EnqueueOptions{ + resultTopic := fmt.Sprintf(TypeSigningResultFmt, s.clientID, s.txID) + err = s.resultQueue.Enqueue(resultTopic, bytes, &messaging.EnqueueOptions{ IdempotententKey: s.idempotentKey, }) if err != nil { - s.ErrCh <- errors.Wrap(err, "Failed to publish sign success message") + s.sendErr(errors.Wrap(err, "Failed to publish sign success message")) return } @@ -210,7 +216,6 @@ func (s *eddsaSigningSession) Sign(onSuccess func(data []byte)) { onSuccess(bytes) return } - } } // Close cleans up the EDDSA signing session by zeroing all sensitive data. diff --git a/pkg/mpc/node.go b/pkg/mpc/node.go index faa842a..4769405 100644 --- a/pkg/mpc/node.go +++ b/pkg/mpc/node.go @@ -146,6 +146,7 @@ func (p *Node) CreateSigningSession( sessionType SessionType, walletID string, txID string, + clientID string, networkInternalCode string, resultQueue messaging.MessageQueue, derivationPath []uint32, @@ -184,6 +185,7 @@ func (p *Node) CreateSigningSession( return newECDSASigningSession( walletID, txID, + clientID, networkInternalCode, p.pubSub, p.direct, @@ -205,6 +207,7 @@ func (p *Node) CreateSigningSession( return newEDDSASigningSession( walletID, txID, + clientID, networkInternalCode, p.pubSub, p.direct, diff --git a/pkg/mpc/session.go b/pkg/mpc/session.go index b1a76b5..76ba376 100644 --- a/pkg/mpc/session.go +++ b/pkg/mpc/session.go @@ -5,6 +5,7 @@ import ( "fmt" "strings" "sync" + "time" "github.com/bnb-chain/tss-lib/v2/ecdsa/keygen" "github.com/bnb-chain/tss-lib/v2/tss" @@ -21,12 +22,20 @@ import ( type SessionType string const ( - TypeGenerateWalletResultFmt = "mpc.mpc_keygen_result.%s" - TypeReshareWalletResultFmt = "mpc.mpc_reshare_result.%s" - TypeSigningResultFmt = "mpc.mpc_signing_result.%s" + // Result topic format: mpc.mpc__result.. + // The clientID segment ensures each client only receives its own results. + TypeGenerateWalletResultFmt = "mpc.mpc_keygen_result.%s.%s" + TypeReshareWalletResultFmt = "mpc.mpc_reshare_result.%s.%s" + TypeSigningResultFmt = "mpc.mpc_signing_result.%s.%s" SessionTypeECDSA SessionType = "session_ecdsa" SessionTypeEDDSA SessionType = "session_eddsa" + + // PeerReadyTimeout is the max time to wait for all peers to confirm + // their subscriptions are active before starting the protocol. + PeerReadyTimeout = 10 * time.Second + // PeerReadyPollInterval is how often to retry the readiness check. + PeerReadyPollInterval = 300 * time.Millisecond ) var ( @@ -68,6 +77,8 @@ type session struct { keyinfoStore keyinfo.Store broadcastSub messaging.Subscription directSubs []messaging.Subscription + // barrierSub is the subscription for the readiness barrier + barrierSub messaging.Subscription resultQueue messaging.MessageQueue identityStore identity.Store @@ -80,6 +91,31 @@ type session struct { pubkeyBytes []byte sessionType SessionType idempotentKey string + + // doneCh is closed when the session should stop (error or completion). + // Sign/Reshare goroutines select on this to avoid leaking forever. + doneCh chan struct{} + doneOnce sync.Once +} + +// sendErr sends an error to ErrCh without blocking if the session is stopped. +func (s *session) sendErr(err error) { + select { + case s.ErrCh <- err: + case <-s.doneCh: + } +} + +// Stop signals the session to terminate. Safe to call multiple times. +func (s *session) Stop() { + s.doneOnce.Do(func() { + close(s.doneCh) + }) +} + +// Done returns a channel that is closed when the session should stop. +func (s *session) Done() <-chan struct{} { + return s.doneCh } func (s *session) PartyID() *tss.PartyID { @@ -98,7 +134,7 @@ func (s *session) PartyCount() int { func (s *session) handleTssMessage(keyshare tss.Message) { data, routing, err := keyshare.WireBytes() if err != nil { - s.ErrCh <- err + s.sendErr(err) return } @@ -122,26 +158,26 @@ func (s *session) handleTssMessage(keyshare tss.Message) { if routing.IsBroadcast && len(routing.To) == 0 { signature, err := s.identityStore.SignMessage(&tssMsg) // attach signature if err != nil { - s.ErrCh <- fmt.Errorf("failed to sign message: %w", err) + s.sendErr(fmt.Errorf("failed to sign message: %w", err)) return } tssMsg.Signature = signature msg, err := types.MarshalTssMessage(&tssMsg) if err != nil { - s.ErrCh <- fmt.Errorf("failed to marshal tss message: %w", err) + s.sendErr(fmt.Errorf("failed to marshal tss message: %w", err)) return } err = s.pubSub.Publish(s.topicComposer.ComposeBroadcastTopic(), msg) if err != nil { - s.ErrCh <- err + s.sendErr(err) return } } else { // p2p message msg, err := types.MarshalTssMessage(&tssMsg) // without signature if err != nil { - s.ErrCh <- fmt.Errorf("failed to marshal tss message: %w", err) + s.sendErr(fmt.Errorf("failed to marshal tss message: %w", err)) return } @@ -153,18 +189,18 @@ func (s *session) handleTssMessage(keyshare tss.Message) { err := s.direct.SendToSelf(topic, msg) if err != nil { logger.Error("Failed in SendToSelf direct message", err, "topic", topic) - s.ErrCh <- fmt.Errorf("failed to send direct message to %s", topic) + s.sendErr(fmt.Errorf("failed to send direct message to %s", topic)) } } else { cipher, err := s.identityStore.EncryptMessage(msg, toNodeID) if err != nil { - s.ErrCh <- fmt.Errorf("encrypt tss message error %w", err) + s.sendErr(fmt.Errorf("encrypt tss message error %w", err)) logger.Error("Encrypt tss message error", err, "topic", topic) } err = s.direct.SendToOther(topic, cipher) if err != nil { logger.Error("Failed in SendToOther direct message", err, "topic", topic) - s.ErrCh <- fmt.Errorf("failed to send direct message to %w", err) + s.sendErr(fmt.Errorf("failed to send direct message to %w", err)) } } } @@ -174,7 +210,7 @@ func (s *session) handleTssMessage(keyshare tss.Message) { func (s *session) receiveP2PTssMessage(topic string, cipher []byte) { senderID := extractSenderIDFromDirectTopic(topic) if senderID == "" { - s.ErrCh <- fmt.Errorf("failed to extract senderID from direct topic: the direct topic format is wrong") + s.sendErr(fmt.Errorf("failed to extract senderID from direct topic: the direct topic format is wrong")) return } @@ -186,13 +222,13 @@ func (s *session) receiveP2PTssMessage(topic string, cipher []byte) { } else { plaintext, err = s.identityStore.DecryptMessage(cipher, senderID) if err != nil { - s.ErrCh <- fmt.Errorf("failed to decrypt message: %w, tampered message", err) + s.sendErr(fmt.Errorf("failed to decrypt message: %w, tampered message", err)) return } } msg, err := types.UnmarshalTssMessage(plaintext) if err != nil { - s.ErrCh <- fmt.Errorf("failed to unmarshal message: %w", err) + s.sendErr(fmt.Errorf("failed to unmarshal message: %w", err)) return } @@ -203,13 +239,13 @@ func (s *session) receiveBroadcastTssMessage(rawMsg []byte) { msg, err := types.UnmarshalTssMessage(rawMsg) if err != nil { - s.ErrCh <- fmt.Errorf("failed to unmarshal message: %w", err) + s.sendErr(fmt.Errorf("failed to unmarshal message: %w", err)) return } err = s.identityStore.VerifyMessage(msg) if err != nil { - s.ErrCh <- fmt.Errorf("Failed to verify message: %w, tampered message", err) + s.sendErr(fmt.Errorf("Failed to verify message: %w, tampered message", err)) return } @@ -225,7 +261,7 @@ func (s *session) receiveTssMessage(msg *types.TssMessage) { round, err := s.getRoundFunc(msg.MsgBytes, s.selfPartyID, msg.IsBroadcast) if err != nil { - s.ErrCh <- errors.Wrap(err, "Broken TSS Share") + s.sendErr(errors.Wrap(err, "Broken TSS Share")) return } logger.Debug( @@ -279,7 +315,7 @@ func (s *session) subscribeFromPeersAsync(fromIDs []string) { for _, fromID := range fromIDs { topic := s.topicComposer.ComposeDirectTopic(fromID, toID) if err := s.subscribeDirectTopicAsync(topic); err != nil { - s.ErrCh <- err + s.sendErr(err) } } } @@ -291,7 +327,7 @@ func (s *session) subscribeBroadcastAsync() { s.receiveBroadcastTssMessage(natMsg.Data) }) if err != nil { - s.ErrCh <- fmt.Errorf("Failed to subscribe to broadcast topic %s: %w", topic, err) + s.sendErr(fmt.Errorf("Failed to subscribe to broadcast topic %s: %w", topic, err)) return } s.broadcastSub = sub @@ -310,16 +346,77 @@ func (s *session) ListenToPeersAsync(peerIDs []string) { s.subscribeFromPeersAsync(peerIDs) } -func (s *session) Close() error { - err := s.broadcastSub.Unsubscribe() +// WaitForPeersReady subscribes to a session-specific barrier topic, then verifies each peer has its barrier +// subscription active by sending NATS requests. This guarantees all peers +// have their direct-message subscriptions set up before the protocol starts. +func (s *session) WaitForPeersReady() error { + selfID := partyIDToNodeID(s.selfPartyID) + barrierTopic := fmt.Sprintf("barrier:%s:%s", s.topicComposer.ComposeBroadcastTopic(), selfID) + + // Subscribe to our own barrier topic so peers can verify we're ready + sub, err := s.direct.Listen(barrierTopic, func(data []byte) { + // Just respond — the response itself proves we're subscribed + }) if err != nil { - return err + return fmt.Errorf("failed to subscribe to barrier topic: %w", err) + } + s.barrierSub = sub + + // Now verify each peer is subscribed by sending requests to their barrier topics + peerIDs := partyIDsToNodeIDs(s.partyIDs) + deadline := time.After(PeerReadyTimeout) + + for _, peerID := range peerIDs { + if peerID == selfID { + continue // skip self + } + peerBarrier := fmt.Sprintf("barrier:%s:%s", s.topicComposer.ComposeBroadcastTopic(), peerID) + + // Retry until peer responds or timeout + for { + err := s.direct.SendToOtherWithRetry(peerBarrier, []byte("ready"), messaging.RetryConfig{ + RetryAttempt: 1, + Delay: PeerReadyPollInterval, + }) + if err == nil { + logger.Debug("Peer ready", "peerID", peerID, "session", s.sessionType) + break + } + + select { + case <-deadline: + return fmt.Errorf("timeout waiting for peer %s to be ready", peerID) + case <-s.doneCh: + return fmt.Errorf("session stopped while waiting for peers") + default: + time.Sleep(PeerReadyPollInterval) + } + } + } + + logger.Info("All peers ready", "session", s.sessionType, "walletID", s.walletID) + return nil +} + +func (s *session) Close() error { + // Signal any running goroutines to stop + s.Stop() + + if s.barrierSub != nil { + if err := s.barrierSub.Unsubscribe(); err != nil { + logger.Error("Failed to unsubscribe barrier", err) + } + } + + if s.broadcastSub != nil { + if err := s.broadcastSub.Unsubscribe(); err != nil { + logger.Error("Failed to unsubscribe broadcast", err) + } } for _, sub := range s.directSubs { - err = sub.Unsubscribe() - if err != nil { - return err + if err := sub.Unsubscribe(); err != nil { + logger.Error("Failed to unsubscribe direct", err) } } @@ -339,7 +436,7 @@ func (s *session) GetVersion() int { } // loadOldShareDataGeneric loads the old share data from kvstore with backward compatibility (versioned and unversioned keys) -func (s *session) loadOldShareDataGeneric(walletID string, version int, dest interface{}) error { +func (s *session) loadOldShareDataGeneric(walletID string, version int, dest any) error { var ( key string keyData []byte diff --git a/pkg/types/initiator_msg.go b/pkg/types/initiator_msg.go index 6100492..8ed0f15 100644 --- a/pkg/types/initiator_msg.go +++ b/pkg/types/initiator_msg.go @@ -36,6 +36,7 @@ type InitiatorMessage interface { type GenerateKeyMessage struct { WalletID string `json:"wallet_id"` + ClientID string `json:"client_id,omitempty"` Signature []byte `json:"signature"` AuthorizerSignatures []AuthorizerSignature `json:"authorizer_signatures,omitempty"` } @@ -46,6 +47,7 @@ type SignTxMessage struct { NetworkInternalCode string `json:"network_internal_code"` TxID string `json:"tx_id"` Tx []byte `json:"tx"` + ClientID string `json:"client_id,omitempty"` Signature []byte `json:"signature"` DerivationPath []uint32 `json:"derivation_path"` AuthorizerSignatures []AuthorizerSignature `json:"authorizer_signatures,omitempty"` @@ -57,6 +59,7 @@ type ResharingMessage struct { NewThreshold int `json:"new_threshold"` KeyType KeyType `json:"key_type"` WalletID string `json:"wallet_id"` + ClientID string `json:"client_id,omitempty"` Signature []byte `json:"signature,omitempty"` AuthorizerSignatures []AuthorizerSignature `json:"authorizer_signatures,omitempty"` } From c6e91756cf8ba9759c70d203bcbe73d0baac43f5 Mon Sep 17 00:00:00 2001 From: anhthii Date: Sun, 15 Mar 2026 22:18:35 +0700 Subject: [PATCH 04/11] Update Go module dependencies --- e2e/go.mod | 14 +++++++------- e2e/go.sum | 40 ++++++++++++++++++++++++++-------------- go.mod | 20 +++++++++++++------- go.sum | 41 +++++++++++++++++++++++++++-------------- 4 files changed, 73 insertions(+), 42 deletions(-) diff --git a/e2e/go.mod b/e2e/go.mod index 106d1f5..ebeda78 100644 --- a/e2e/go.mod +++ b/e2e/go.mod @@ -7,7 +7,7 @@ require ( github.com/fystack/mpcium v0.0.0-00010101000000-000000000000 github.com/google/uuid v1.6.0 github.com/hashicorp/consul/api v1.33.2 - github.com/nats-io/nats.go v1.48.0 + github.com/nats-io/nats.go v1.49.0 github.com/stretchr/testify v1.11.1 gopkg.in/yaml.v2 v2.4.0 ) @@ -64,11 +64,11 @@ require ( github.com/hashicorp/serf v0.10.2 // indirect github.com/ipfs/go-log v1.0.5 // indirect github.com/ipfs/go-log/v2 v2.9.0 // indirect - github.com/klauspost/compress v1.18.3 // indirect + github.com/klauspost/compress v1.18.4 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/nats-io/nkeys v0.4.12 // indirect + github.com/nats-io/nkeys v0.4.15 // indirect github.com/nats-io/nuid v1.0.1 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/otiai10/primes v0.4.0 // indirect @@ -90,12 +90,12 @@ require ( go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.1 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/crypto v0.47.0 // indirect + golang.org/x/crypto v0.48.0 // indirect golang.org/x/exp v0.0.0-20260112195511-716be5621a96 // indirect golang.org/x/net v0.49.0 // indirect - golang.org/x/sys v0.40.0 // indirect - golang.org/x/term v0.39.0 // indirect - golang.org/x/text v0.33.0 // indirect + golang.org/x/sys v0.42.0 // indirect + golang.org/x/term v0.40.0 // indirect + golang.org/x/text v0.34.0 // indirect google.golang.org/protobuf v1.36.11 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/e2e/go.sum b/e2e/go.sum index 1f40ea0..59cfec5 100644 --- a/e2e/go.sum +++ b/e2e/go.sum @@ -13,6 +13,8 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/antithesishq/antithesis-sdk-go v0.6.0-default-no-op h1:kpBdlEPbRvff0mDD1gk7o9BhI16b9p5yYAXRlidpqJE= +github.com/antithesishq/antithesis-sdk-go v0.6.0-default-no-op/go.mod h1:IUpT2DPAKh6i/YhSbt6Gl3v2yvUZjmKncl7U91fup7E= github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHSxpiH9JdtuBj0= @@ -161,6 +163,8 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo= +github.com/google/go-tpm v0.9.8/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= @@ -223,8 +227,8 @@ github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8 github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= -github.com/klauspost/compress v1.18.3 h1:9PJRvfbmTabkOX8moIpXPbMMbYN60bWImDDU7L+/6zw= -github.com/klauspost/compress v1.18.3/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= +github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c= +github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -249,6 +253,8 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE= github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY= +github.com/minio/highwayhash v1.0.4-0.20251030100505-070ab1a87a76 h1:KGuD/pM2JpL9FAYvBrnBBeENKZNh6eNtjqytV6TYjnk= +github.com/minio/highwayhash v1.0.4-0.20251030100505-070ab1a87a76/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -257,10 +263,14 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/nats-io/nats.go v1.48.0 h1:pSFyXApG+yWU/TgbKCjmm5K4wrHu86231/w84qRVR+U= -github.com/nats-io/nats.go v1.48.0/go.mod h1:iRWIPokVIFbVijxuMQq4y9ttaBTMe0SFdlZfMDd+33g= -github.com/nats-io/nkeys v0.4.12 h1:nssm7JKOG9/x4J8II47VWCL1Ds29avyiQDRn0ckMvDc= -github.com/nats-io/nkeys v0.4.12/go.mod h1:MT59A1HYcjIcyQDJStTfaOY6vhy9XTUjOFo+SVsvpBg= +github.com/nats-io/jwt/v2 v2.8.0 h1:K7uzyz50+yGZDO5o772eRE7atlcSEENpL7P+b74JV1g= +github.com/nats-io/jwt/v2 v2.8.0/go.mod h1:me11pOkwObtcBNR8AiMrUbtVOUGkqYjMQZ6jnSdVUIA= +github.com/nats-io/nats-server/v2 v2.12.5 h1:EOHLbsLJgUHUwzkj9gBTOlubkX+dmSs0EYWMdBiHivU= +github.com/nats-io/nats-server/v2 v2.12.5/go.mod h1:JQDAKcwdXs0NRhvYO31dzsXkzCyDkOBS7SKU3Nozu14= +github.com/nats-io/nats.go v1.49.0 h1:yh/WvY59gXqYpgl33ZI+XoVPKyut/IcEaqtsiuTJpoE= +github.com/nats-io/nats.go v1.49.0/go.mod h1:fDCn3mN5cY8HooHwE2ukiLb4p4G4ImmzvXyJt+tGwdw= +github.com/nats-io/nkeys v0.4.15 h1:JACV5jRVO9V856KOapQ7x+EY8Jo3qw1vJt/9Jpwzkk4= +github.com/nats-io/nkeys v0.4.15/go.mod h1:CpMchTXC9fxA5zrMo4KpySxNjiDVvr8ANOSZdiNfUrs= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= @@ -391,8 +401,8 @@ golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= -golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= -golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= +golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= +golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= golang.org/x/exp v0.0.0-20260112195511-716be5621a96 h1:Z/6YuSHTLOHfNFdb8zVZomZr7cqNgTJvA8+Qz75D8gU= golang.org/x/exp v0.0.0-20260112195511-716be5621a96/go.mod h1:nzimsREAkjBCIEFtHiYkrJyT+2uy9YZJB7H1k68CXZU= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -468,15 +478,15 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= -golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= +golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= -golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY= -golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww= +golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg= +golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -484,8 +494,10 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 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.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= -golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= +golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= +golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= +golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= +golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= diff --git a/go.mod b/go.mod index e7c90f1..874726c 100644 --- a/go.mod +++ b/go.mod @@ -17,19 +17,21 @@ require ( github.com/google/uuid v1.6.0 github.com/hashicorp/consul/api v1.33.2 github.com/mitchellh/mapstructure v1.5.0 - github.com/nats-io/nats.go v1.48.0 + github.com/nats-io/nats-server/v2 v2.12.5 + github.com/nats-io/nats.go v1.49.0 github.com/rs/zerolog v1.34.0 github.com/samber/lo v1.52.0 github.com/spf13/viper v1.21.0 github.com/stretchr/testify v1.11.1 github.com/urfave/cli/v3 v3.6.2 - golang.org/x/crypto v0.47.0 - golang.org/x/term v0.39.0 + golang.org/x/crypto v0.48.0 + golang.org/x/term v0.40.0 ) require ( filippo.io/hpke v0.4.0 // indirect github.com/agl/ed25519 v0.0.0-20200225211852-fd4d107ace12 // indirect + github.com/antithesishq/antithesis-sdk-go v0.6.0-default-no-op // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/aws/aws-sdk-go-v2 v1.41.1 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17 // indirect @@ -57,6 +59,7 @@ require ( github.com/go-viper/mapstructure/v2 v2.5.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/google/flatbuffers v25.12.19+incompatible // indirect + github.com/google/go-tpm v0.9.8 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-hclog v1.6.3 // indirect @@ -69,11 +72,13 @@ require ( github.com/hashicorp/serf v0.10.2 // indirect github.com/ipfs/go-log v1.0.5 // indirect github.com/ipfs/go-log/v2 v2.9.0 // indirect - github.com/klauspost/compress v1.18.3 // indirect + github.com/klauspost/compress v1.18.4 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect + github.com/minio/highwayhash v1.0.4-0.20251030100505-070ab1a87a76 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/nats-io/nkeys v0.4.12 // indirect + github.com/nats-io/jwt/v2 v2.8.0 // indirect + github.com/nats-io/nkeys v0.4.15 // indirect github.com/nats-io/nuid v1.0.1 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/otiai10/primes v0.4.0 // indirect @@ -95,8 +100,9 @@ require ( go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/exp v0.0.0-20260112195511-716be5621a96 // indirect golang.org/x/net v0.49.0 // indirect - golang.org/x/sys v0.40.0 // indirect - golang.org/x/text v0.33.0 // indirect + golang.org/x/sys v0.42.0 // indirect + golang.org/x/text v0.34.0 // indirect + golang.org/x/time v0.15.0 // indirect google.golang.org/protobuf v1.36.11 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 65fd95a..aebe6da 100644 --- a/go.sum +++ b/go.sum @@ -13,6 +13,8 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/antithesishq/antithesis-sdk-go v0.6.0-default-no-op h1:kpBdlEPbRvff0mDD1gk7o9BhI16b9p5yYAXRlidpqJE= +github.com/antithesishq/antithesis-sdk-go v0.6.0-default-no-op/go.mod h1:IUpT2DPAKh6i/YhSbt6Gl3v2yvUZjmKncl7U91fup7E= github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHSxpiH9JdtuBj0= @@ -161,6 +163,8 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo= +github.com/google/go-tpm v0.9.8/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= @@ -223,8 +227,8 @@ github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8 github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= -github.com/klauspost/compress v1.18.3 h1:9PJRvfbmTabkOX8moIpXPbMMbYN60bWImDDU7L+/6zw= -github.com/klauspost/compress v1.18.3/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= +github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c= +github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -249,6 +253,8 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE= github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY= +github.com/minio/highwayhash v1.0.4-0.20251030100505-070ab1a87a76 h1:KGuD/pM2JpL9FAYvBrnBBeENKZNh6eNtjqytV6TYjnk= +github.com/minio/highwayhash v1.0.4-0.20251030100505-070ab1a87a76/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -259,10 +265,14 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/nats-io/nats.go v1.48.0 h1:pSFyXApG+yWU/TgbKCjmm5K4wrHu86231/w84qRVR+U= -github.com/nats-io/nats.go v1.48.0/go.mod h1:iRWIPokVIFbVijxuMQq4y9ttaBTMe0SFdlZfMDd+33g= -github.com/nats-io/nkeys v0.4.12 h1:nssm7JKOG9/x4J8II47VWCL1Ds29avyiQDRn0ckMvDc= -github.com/nats-io/nkeys v0.4.12/go.mod h1:MT59A1HYcjIcyQDJStTfaOY6vhy9XTUjOFo+SVsvpBg= +github.com/nats-io/jwt/v2 v2.8.0 h1:K7uzyz50+yGZDO5o772eRE7atlcSEENpL7P+b74JV1g= +github.com/nats-io/jwt/v2 v2.8.0/go.mod h1:me11pOkwObtcBNR8AiMrUbtVOUGkqYjMQZ6jnSdVUIA= +github.com/nats-io/nats-server/v2 v2.12.5 h1:EOHLbsLJgUHUwzkj9gBTOlubkX+dmSs0EYWMdBiHivU= +github.com/nats-io/nats-server/v2 v2.12.5/go.mod h1:JQDAKcwdXs0NRhvYO31dzsXkzCyDkOBS7SKU3Nozu14= +github.com/nats-io/nats.go v1.49.0 h1:yh/WvY59gXqYpgl33ZI+XoVPKyut/IcEaqtsiuTJpoE= +github.com/nats-io/nats.go v1.49.0/go.mod h1:fDCn3mN5cY8HooHwE2ukiLb4p4G4ImmzvXyJt+tGwdw= +github.com/nats-io/nkeys v0.4.15 h1:JACV5jRVO9V856KOapQ7x+EY8Jo3qw1vJt/9Jpwzkk4= +github.com/nats-io/nkeys v0.4.15/go.mod h1:CpMchTXC9fxA5zrMo4KpySxNjiDVvr8ANOSZdiNfUrs= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= @@ -395,8 +405,8 @@ golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= -golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= -golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= +golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= +golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= golang.org/x/exp v0.0.0-20260112195511-716be5621a96 h1:Z/6YuSHTLOHfNFdb8zVZomZr7cqNgTJvA8+Qz75D8gU= golang.org/x/exp v0.0.0-20260112195511-716be5621a96/go.mod h1:nzimsREAkjBCIEFtHiYkrJyT+2uy9YZJB7H1k68CXZU= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -472,15 +482,16 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= -golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= +golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= -golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY= -golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww= +golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg= +golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -488,8 +499,10 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 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.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= -golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= +golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= +golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= +golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= +golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= From 575c4125322bdea7a5016e785f08689f57daee22 Mon Sep 17 00:00:00 2001 From: anhthii Date: Sun, 15 Mar 2026 23:00:39 +0700 Subject: [PATCH 05/11] Temp code --- cmd/mpcium/main.go | 6 +- pkg/client/client.go | 39 +++--------- pkg/event/sign.go | 5 +- pkg/eventconsumer/event_consumer.go | 91 +++++++++++----------------- pkg/eventconsumer/keygen_consumer.go | 6 +- pkg/eventconsumer/sign_consumer.go | 5 +- pkg/messaging/message_queue.go | 40 +----------- pkg/mpc/ecdsa_signing_session.go | 6 +- pkg/mpc/eddsa_signing_session.go | 6 +- pkg/mpc/node.go | 3 - pkg/mpc/session.go | 8 +-- pkg/types/initiator_msg.go | 3 - 12 files changed, 63 insertions(+), 155 deletions(-) diff --git a/cmd/mpcium/main.go b/cmd/mpcium/main.go index 5568abb..f9b7b88 100644 --- a/cmd/mpcium/main.go +++ b/cmd/mpcium/main.go @@ -219,9 +219,9 @@ func runNode(ctx context.Context, c *cli.Command) error { directMessaging := messaging.NewNatsDirectMessaging(natsConn) mqManager := messaging.NewNATsMessageQueueManager("mpc", []string{ - "mpc.mpc_keygen_result.>", - "mpc.mpc_signing_result.>", - "mpc.mpc_reshare_result.>", + "mpc.mpc_keygen_result.*", + event.SigningResultTopic, + "mpc.mpc_reshare_result.*", }, natsConn) genKeyResultQueue := mqManager.NewMessageQueue("mpc_keygen_result") diff --git a/pkg/client/client.go b/pkg/client/client.go index c7c2436..6c64c14 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -10,7 +10,6 @@ import ( "github.com/fystack/mpcium/pkg/logger" "github.com/fystack/mpcium/pkg/messaging" "github.com/fystack/mpcium/pkg/types" - "github.com/google/uuid" "github.com/nats-io/nats.go" ) @@ -32,7 +31,6 @@ type MPCClient interface { } type mpcClient struct { - clientID string signingBroker messaging.MessageBroker keygenBroker messaging.MessageBroker pubsub messaging.PubSub @@ -49,10 +47,6 @@ type Options struct { // Signer for signing messages Signer Signer - - // ClientID uniquely identifies this client instance for result routing. - // If empty, a UUID is generated automatically. - ClientID string } // NewMPCClient creates a new MPC client using the provided options. @@ -62,13 +56,6 @@ func NewMPCClient(opts Options) MPCClient { logger.Fatal("Signer is required", nil) } - clientID := opts.ClientID - if clientID == "" { - clientID = uuid.New().String() - } - - logger.Info("Creating MPC client", "clientID", clientID) - // 2) Create the PubSub for both publish & subscribe signingBroker, err := messaging.NewJetStreamBroker( context.Background(), @@ -96,18 +83,16 @@ func NewMPCClient(opts Options) MPCClient { pubsub := messaging.NewNATSPubSub(opts.NatsConn) manager := messaging.NewNATsMessageQueueManager("mpc", []string{ - "mpc.mpc_keygen_result.>", - "mpc.mpc_signing_result.>", - "mpc.mpc_reshare_result.>", + "mpc.mpc_keygen_result.*", + "mpc.mpc_signing_result.*", + "mpc.mpc_reshare_result.*", }, opts.NatsConn) - // Per-client consumers: each client only receives results addressed to its clientID. - genKeySuccessQueue := manager.NewClientMessageQueue("mpc_keygen_result", clientID) - signResultQueue := manager.NewClientMessageQueue("mpc_signing_result", clientID) - reshareSuccessQueue := manager.NewClientMessageQueue("mpc_reshare_result", clientID) + genKeySuccessQueue := manager.NewMessageQueue("mpc_keygen_result") + signResultQueue := manager.NewMessageQueue("mpc_signing_result") + reshareSuccessQueue := manager.NewMessageQueue("mpc_reshare_result") return &mpcClient{ - clientID: clientID, signingBroker: signingBroker, keygenBroker: keygenBroker, pubsub: pubsub, @@ -128,7 +113,6 @@ func (c *mpcClient) CreateWalletWithAuthorizers(walletID string, authorizerSigna // build the message msg := &types.GenerateKeyMessage{ WalletID: walletID, - ClientID: c.clientID, AuthorizerSignatures: authorizerSignatures, } // compute the canonical raw bytes @@ -155,8 +139,7 @@ func (c *mpcClient) CreateWalletWithAuthorizers(walletID string, authorizerSigna // The callback will be invoked whenever a wallet creation result is received. func (c *mpcClient) OnWalletCreationResult(callback func(event event.KeygenResultEvent)) error { - topic := fmt.Sprintf("mpc.mpc_keygen_result.%s.*", c.clientID) - err := c.genKeySuccessQueue.Dequeue(topic, func(msg []byte) error { + err := c.genKeySuccessQueue.Dequeue(GenerateWalletSuccessTopic, func(msg []byte) error { var event event.KeygenResultEvent err := json.Unmarshal(msg, &event) if err != nil { @@ -175,7 +158,6 @@ func (c *mpcClient) OnWalletCreationResult(callback func(event event.KeygenResul // SignTransaction builds a SignTxMessage, signs it, and publishes it. func (c *mpcClient) SignTransaction(msg *types.SignTxMessage) error { - msg.ClientID = c.clientID // compute the canonical raw bytes (omitting Signature field) raw, err := msg.Raw() if err != nil { @@ -199,8 +181,7 @@ func (c *mpcClient) SignTransaction(msg *types.SignTxMessage) error { } func (c *mpcClient) OnSignResult(callback func(event event.SigningResultEvent)) error { - topic := fmt.Sprintf("mpc.mpc_signing_result.%s.*", c.clientID) - err := c.signResultQueue.Dequeue(topic, func(msg []byte) error { + err := c.signResultQueue.Dequeue(event.SigningResultCompleteTopic, func(msg []byte) error { var event event.SigningResultEvent err := json.Unmarshal(msg, &event) if err != nil { @@ -218,7 +199,6 @@ func (c *mpcClient) OnSignResult(callback func(event event.SigningResultEvent)) } func (c *mpcClient) Resharing(msg *types.ResharingMessage) error { - msg.ClientID = c.clientID // compute the canonical raw bytes raw, err := msg.Raw() if err != nil { @@ -242,8 +222,7 @@ func (c *mpcClient) Resharing(msg *types.ResharingMessage) error { } func (c *mpcClient) OnResharingResult(callback func(event event.ResharingResultEvent)) error { - topic := fmt.Sprintf("mpc.mpc_reshare_result.%s.*", c.clientID) - err := c.reshareSuccessQueue.Dequeue(topic, func(msg []byte) error { + err := c.reshareSuccessQueue.Dequeue(ResharingSuccessTopic, func(msg []byte) error { logger.Info("Received reshare success message", "raw", string(msg)) var event event.ResharingResultEvent err := json.Unmarshal(msg, &event) diff --git a/pkg/event/sign.go b/pkg/event/sign.go index da72d34..25449e5 100644 --- a/pkg/event/sign.go +++ b/pkg/event/sign.go @@ -3,8 +3,9 @@ package event const ( SigningPublisherStream = "mpc-signing" SigningConsumerStream = "mpc-signing-consumer" - SigningRequestTopic = "mpc.signing_request.*" - SigningResultTopic = "mpc.mpc_signing_result.>" + SigningRequestTopic = "mpc.signing_request.*" + SigningResultTopic = "mpc.mpc_signing_result.*" + SigningResultCompleteTopic = "mpc.mpc_signing_result.complete" ) type SigningResultEvent struct { diff --git a/pkg/eventconsumer/event_consumer.go b/pkg/eventconsumer/event_consumer.go index ad8b70b..e1c973a 100644 --- a/pkg/eventconsumer/event_consumer.go +++ b/pkg/eventconsumer/event_consumer.go @@ -156,23 +156,22 @@ func (ec *eventConsumer) handleKeyGenEvent(natMsg *nats.Msg) { var msg types.GenerateKeyMessage if err := json.Unmarshal(raw, &msg); err != nil { logger.Error("Failed to unmarshal keygen message", err) - ec.handleKeygenSessionError(msg.ClientID, msg.WalletID, err, "Failed to unmarshal keygen message", natMsg) + ec.handleKeygenSessionError(msg.WalletID, err, "Failed to unmarshal keygen message", natMsg) return } if err := ec.identityStore.VerifyInitiatorMessage(&msg); err != nil { logger.Error("Failed to verify initiator message", err) - ec.handleKeygenSessionError(msg.ClientID, msg.WalletID, err, "Failed to verify initiator message", natMsg) + ec.handleKeygenSessionError(msg.WalletID, err, "Failed to verify initiator message", natMsg) return } if err := ec.identityStore.AuthorizeInitiatorMessage(&msg); err != nil { logger.Error("Failed to authorize initiator message", err) - ec.handleKeygenSessionError(msg.ClientID, msg.WalletID, err, "Failed to authorize initiator message", natMsg) + ec.handleKeygenSessionError(msg.WalletID, err, "Failed to authorize initiator message", natMsg) return } - clientID := msg.ClientID walletID := msg.WalletID // Guard against duplicate keygen sessions for the same walletID. @@ -180,19 +179,19 @@ func (ec *eventConsumer) handleKeyGenEvent(natMsg *nats.Msg) { // creating a second session on the same NATS topics which causes VSS verify failures. if !ec.tryAddSession(walletID, "keygen") { duplicateErr := fmt.Errorf("duplicate keygen request detected for walletID=%s", walletID) - ec.handleKeygenSessionError(clientID, walletID, duplicateErr, "Duplicate keygen session", natMsg) + ec.handleKeygenSessionError(walletID, duplicateErr, "Duplicate keygen session", natMsg) return } defer ec.removeSession(walletID, "keygen") ecdsaSession, err := ec.node.CreateKeyGenSession(mpc.SessionTypeECDSA, walletID, ec.mpcThreshold, ec.genKeyResultQueue) if err != nil { - ec.handleKeygenSessionError(clientID, walletID, err, "Failed to create ECDSA key generation session", natMsg) + ec.handleKeygenSessionError(walletID, err, "Failed to create ECDSA key generation session", natMsg) return } eddsaSession, err := ec.node.CreateKeyGenSession(mpc.SessionTypeEDDSA, walletID, ec.mpcThreshold, ec.genKeyResultQueue) if err != nil { - ec.handleKeygenSessionError(clientID, walletID, err, "Failed to create EdDSA key generation session", natMsg) + ec.handleKeygenSessionError(walletID, err, "Failed to create EdDSA key generation session", natMsg) return } ecdsaSession.Init() @@ -215,7 +214,7 @@ func (ec *eventConsumer) handleKeyGenEvent(natMsg *nats.Msg) { successEvent.ECDSAPubKey = ecdsaSession.GetPubKeyResult() case err := <-ecdsaSession.ErrChan(): logger.Error("ECDSA keygen session error", err) - ec.handleKeygenSessionError(clientID, walletID, err, "ECDSA keygen session error", natMsg) + ec.handleKeygenSessionError(walletID, err, "ECDSA keygen session error", natMsg) errorChan <- err doneEcdsa() } @@ -227,7 +226,7 @@ func (ec *eventConsumer) handleKeyGenEvent(natMsg *nats.Msg) { successEvent.EDDSAPubKey = eddsaSession.GetPubKeyResult() case err := <-eddsaSession.ErrChan(): logger.Error("EdDSA keygen session error", err) - ec.handleKeygenSessionError(clientID, walletID, err, "EdDSA keygen session error", natMsg) + ec.handleKeygenSessionError(walletID, err, "EdDSA keygen session error", natMsg) errorChan <- err doneEddsa() } @@ -252,7 +251,7 @@ func (ec *eventConsumer) handleKeyGenEvent(natMsg *nats.Msg) { }) barrierWg.Wait() if barrierErr != nil { - ec.handleKeygenSessionError(clientID, walletID, barrierErr, "Peers not ready before keygen", natMsg) + ec.handleKeygenSessionError(walletID, barrierErr, "Peers not ready before keygen", natMsg) return } go ecdsaSession.GenerateKey(doneEcdsa) @@ -278,25 +277,25 @@ func (ec *eventConsumer) handleKeyGenEvent(natMsg *nats.Msg) { case <-baseCtx.Done(): // timeout occurred logger.Warn("Key generation timed out", "walletID", walletID, "timeout", KeyGenTimeOut) - ec.handleKeygenSessionError(clientID, walletID, fmt.Errorf("keygen session timed out after %v", KeyGenTimeOut), "Key generation timed out", natMsg) + ec.handleKeygenSessionError(walletID, fmt.Errorf("keygen session timed out after %v", KeyGenTimeOut), "Key generation timed out", natMsg) return } payload, err := json.Marshal(successEvent) if err != nil { logger.Error("Failed to marshal keygen success event", err) - ec.handleKeygenSessionError(clientID, walletID, err, "Failed to marshal keygen success event", natMsg) + ec.handleKeygenSessionError(walletID, err, "Failed to marshal keygen success event", natMsg) return } - resultTopic := fmt.Sprintf(mpc.TypeGenerateWalletResultFmt, clientID, walletID) + key := fmt.Sprintf(mpc.TypeGenerateWalletResultFmt, walletID) if err := ec.genKeyResultQueue.Enqueue( - resultTopic, + key, payload, &messaging.EnqueueOptions{IdempotententKey: composeKeygenIdempotentKey(walletID, natMsg)}, ); err != nil { logger.Error("Failed to publish key generation success message", err) - ec.handleKeygenSessionError(clientID, walletID, err, "Failed to publish key generation success message", natMsg) + ec.handleKeygenSessionError(walletID, err, "Failed to publish key generation success message", natMsg) return } ec.sendReplyToRemoveMsg(natMsg) @@ -304,7 +303,7 @@ func (ec *eventConsumer) handleKeyGenEvent(natMsg *nats.Msg) { } // handleKeygenSessionError handles errors that occur during key generation -func (ec *eventConsumer) handleKeygenSessionError(clientID, walletID string, err error, contextMsg string, natMsg *nats.Msg) { +func (ec *eventConsumer) handleKeygenSessionError(walletID string, err error, contextMsg string, natMsg *nats.Msg) { fullErrMsg := fmt.Sprintf("%s: %v", contextMsg, err) errorCode := event.GetErrorCodeFromError(err) keygenResult := event.KeygenResultEvent{ @@ -322,8 +321,8 @@ func (ec *eventConsumer) handleKeygenSessionError(clientID, walletID string, err return } - resultTopic := fmt.Sprintf(mpc.TypeGenerateWalletResultFmt, clientID, walletID) - err = ec.genKeyResultQueue.Enqueue(resultTopic, keygenResultBytes, &messaging.EnqueueOptions{ + key := fmt.Sprintf(mpc.TypeGenerateWalletResultFmt, walletID) + err = ec.genKeyResultQueue.Enqueue(key, keygenResultBytes, &messaging.EnqueueOptions{ IdempotententKey: composeKeygenIdempotentKey(walletID, natMsg), }) if err != nil { @@ -394,9 +393,6 @@ func (ec *eventConsumer) handleSigningEvent(natMsg *nats.Msg) { return } - // Extract clientID from the message (set by the originating client). - clientID := msg.ClientID - logger.Info( "Received signing event", "waleltID", @@ -405,8 +401,6 @@ func (ec *eventConsumer) handleSigningEvent(natMsg *nats.Msg) { msg.KeyType, "tx", msg.TxID, - "clientID", - clientID, "Id", ec.node.ID(), ) @@ -415,7 +409,6 @@ func (ec *eventConsumer) handleSigningEvent(natMsg *nats.Msg) { if !ec.tryAddSession(msg.WalletID, msg.TxID) { duplicateErr := fmt.Errorf("duplicate signing request detected for walletID=%s txID=%s", msg.WalletID, msg.TxID) ec.handleSigningSessionError( - clientID, msg.WalletID, msg.TxID, msg.NetworkInternalCode, @@ -435,7 +428,6 @@ func (ec *eventConsumer) handleSigningEvent(natMsg *nats.Msg) { mpc.SessionTypeECDSA, msg.WalletID, msg.TxID, - clientID, msg.NetworkInternalCode, ec.signingResultQueue, msg.DerivationPath, @@ -446,7 +438,6 @@ func (ec *eventConsumer) handleSigningEvent(natMsg *nats.Msg) { mpc.SessionTypeEDDSA, msg.WalletID, msg.TxID, - clientID, msg.NetworkInternalCode, ec.signingResultQueue, msg.DerivationPath, @@ -478,7 +469,6 @@ func (ec *eventConsumer) handleSigningEvent(natMsg *nats.Msg) { } ec.handleSigningSessionError( - clientID, msg.WalletID, msg.TxID, msg.NetworkInternalCode, @@ -493,7 +483,6 @@ func (ec *eventConsumer) handleSigningEvent(natMsg *nats.Msg) { err = session.Init(txBigInt) if err != nil { ec.handleSigningSessionError( - clientID, msg.WalletID, msg.TxID, msg.NetworkInternalCode, @@ -513,7 +502,6 @@ func (ec *eventConsumer) handleSigningEvent(natMsg *nats.Msg) { case err := <-session.ErrChan(): if err != nil { ec.handleSigningSessionError( - clientID, msg.WalletID, msg.TxID, msg.NetworkInternalCode, @@ -537,7 +525,6 @@ func (ec *eventConsumer) handleSigningEvent(natMsg *nats.Msg) { // This replaces the old warmUpSession() sleep with a proper handshake. if err := session.WaitForPeersReady(); err != nil { ec.handleSigningSessionError( - clientID, msg.WalletID, msg.TxID, msg.NetworkInternalCode, @@ -567,14 +554,13 @@ func (ec *eventConsumer) consumeTxSigningEvent() error { return nil } -func (ec *eventConsumer) handleSigningSessionError(clientID, walletID, txID, networkInternalCode string, err error, contextMsg string, natMsg *nats.Msg) { +func (ec *eventConsumer) handleSigningSessionError(walletID, txID, networkInternalCode string, err error, contextMsg string, natMsg *nats.Msg) { fullErrMsg := fmt.Sprintf("%s: %v", contextMsg, err) errorCode := event.GetErrorCodeFromError(err) logger.Warn("Signing session error", "walletID", walletID, "txID", txID, - "clientID", clientID, "networkInternalCode", networkInternalCode, "error", err.Error(), "errorCode", errorCode, @@ -598,8 +584,7 @@ func (ec *eventConsumer) handleSigningSessionError(clientID, walletID, txID, net ) return } - resultTopic := fmt.Sprintf(mpc.TypeSigningResultFmt, clientID, txID) - err = ec.signingResultQueue.Enqueue(resultTopic, signingResultBytes, &messaging.EnqueueOptions{ + err = ec.signingResultQueue.Enqueue(event.SigningResultCompleteTopic, signingResultBytes, &messaging.EnqueueOptions{ IdempotententKey: composeSigningIdempotentKey(txID, natMsg), }) if err != nil { @@ -632,13 +617,12 @@ func (ec *eventConsumer) consumeReshareEvent() error { var msg types.ResharingMessage if err := json.Unmarshal(natMsg.Data, &msg); err != nil { logger.Error("Failed to unmarshal resharing message", err) - ec.handleReshareSessionError(msg.ClientID, msg.WalletID, msg.KeyType, msg.NewThreshold, err, "Failed to unmarshal resharing message", natMsg) + ec.handleReshareSessionError(msg.WalletID, msg.KeyType, msg.NewThreshold, err, "Failed to unmarshal resharing message", natMsg) return } if msg.SessionID == "" { ec.handleReshareSessionError( - msg.ClientID, msg.WalletID, msg.KeyType, msg.NewThreshold, @@ -651,24 +635,23 @@ func (ec *eventConsumer) consumeReshareEvent() error { if err := ec.identityStore.VerifyInitiatorMessage(&msg); err != nil { logger.Error("Failed to verify initiator message", err) - ec.handleReshareSessionError(msg.ClientID, msg.WalletID, msg.KeyType, msg.NewThreshold, err, "Failed to verify initiator message", natMsg) + ec.handleReshareSessionError(msg.WalletID, msg.KeyType, msg.NewThreshold, err, "Failed to verify initiator message", natMsg) return } if err := ec.identityStore.AuthorizeInitiatorMessage(&msg); err != nil { logger.Error("Failed to authorize initiator message", err) - ec.handleReshareSessionError(msg.ClientID, msg.WalletID, msg.KeyType, msg.NewThreshold, err, "Failed to authorize initiator message", natMsg) + ec.handleReshareSessionError(msg.WalletID, msg.KeyType, msg.NewThreshold, err, "Failed to authorize initiator message", natMsg) return } - clientID := msg.ClientID walletID := msg.WalletID keyType := msg.KeyType sessionType, err := sessionTypeFromKeyType(keyType) if err != nil { logger.Error("Failed to get session type", err) - ec.handleReshareSessionError(clientID, walletID, keyType, msg.NewThreshold, err, "Failed to get session type", natMsg) + ec.handleReshareSessionError(walletID, keyType, msg.NewThreshold, err, "Failed to get session type", natMsg) return } @@ -686,13 +669,13 @@ func (ec *eventConsumer) consumeReshareEvent() error { oldSession, err := createSession(false) if err != nil { logger.Error("Failed to create old reshare session", err, "walletID", walletID) - ec.handleReshareSessionError(clientID, walletID, keyType, msg.NewThreshold, err, "Failed to create old reshare session", natMsg) + ec.handleReshareSessionError(walletID, keyType, msg.NewThreshold, err, "Failed to create old reshare session", natMsg) return } newSession, err := createSession(true) if err != nil { logger.Error("Failed to create new reshare session", err, "walletID", walletID) - ec.handleReshareSessionError(clientID, walletID, keyType, msg.NewThreshold, err, "Failed to create new reshare session", natMsg) + ec.handleReshareSessionError(walletID, keyType, msg.NewThreshold, err, "Failed to create new reshare session", natMsg) return } @@ -714,7 +697,7 @@ func (ec *eventConsumer) consumeReshareEvent() error { if oldSession != nil { err := oldSession.Init() if err != nil { - ec.handleReshareSessionError(clientID, walletID, keyType, msg.NewThreshold, err, "Failed to init old reshare session", natMsg) + ec.handleReshareSessionError(walletID, keyType, msg.NewThreshold, err, "Failed to init old reshare session", natMsg) return } oldSession.ListenToIncomingMessageAsync() @@ -723,7 +706,7 @@ func (ec *eventConsumer) consumeReshareEvent() error { if newSession != nil { err := newSession.Init() if err != nil { - ec.handleReshareSessionError(clientID, walletID, keyType, msg.NewThreshold, err, "Failed to init new reshare session", natMsg) + ec.handleReshareSessionError(walletID, keyType, msg.NewThreshold, err, "Failed to init new reshare session", natMsg) return } newSession.ListenToIncomingMessageAsync() @@ -760,7 +743,7 @@ func (ec *eventConsumer) consumeReshareEvent() error { } reshareBarrierWg.Wait() if reshareBarrierErr != nil { - ec.handleReshareSessionError(clientID, walletID, keyType, msg.NewThreshold, reshareBarrierErr, "Peers not ready before resharing", natMsg) + ec.handleReshareSessionError(walletID, keyType, msg.NewThreshold, reshareBarrierErr, "Peers not ready before resharing", natMsg) return } @@ -775,7 +758,7 @@ func (ec *eventConsumer) consumeReshareEvent() error { return case err := <-oldSession.ErrChan(): logger.Error("Old reshare session error", err) - ec.handleReshareSessionError(clientID, walletID, keyType, msg.NewThreshold, err, "Old reshare session error", natMsg) + ec.handleReshareSessionError(walletID, keyType, msg.NewThreshold, err, "Old reshare session error", natMsg) doneOld() return } @@ -794,7 +777,7 @@ func (ec *eventConsumer) consumeReshareEvent() error { return case err := <-newSession.ErrChan(): logger.Error("New reshare session error", err) - ec.handleReshareSessionError(clientID, walletID, keyType, msg.NewThreshold, err, "New reshare session error", natMsg) + ec.handleReshareSessionError(walletID, keyType, msg.NewThreshold, err, "New reshare session error", natMsg) doneNew() return } @@ -809,20 +792,20 @@ func (ec *eventConsumer) consumeReshareEvent() error { successBytes, err := json.Marshal(successEvent) if err != nil { logger.Error("Failed to marshal reshare success event", err) - ec.handleReshareSessionError(clientID, walletID, keyType, msg.NewThreshold, err, "Failed to marshal reshare success event", natMsg) + ec.handleReshareSessionError(walletID, keyType, msg.NewThreshold, err, "Failed to marshal reshare success event", natMsg) return } - resultTopic := fmt.Sprintf(mpc.TypeReshareWalletResultFmt, clientID, msg.SessionID) + key := fmt.Sprintf(mpc.TypeReshareWalletResultFmt, msg.SessionID) err = ec.reshareResultQueue.Enqueue( - resultTopic, + key, successBytes, &messaging.EnqueueOptions{ IdempotententKey: composeReshareIdempotentKey(msg.SessionID, natMsg), }) if err != nil { logger.Error("Failed to publish reshare success message", err) - ec.handleReshareSessionError(clientID, walletID, keyType, msg.NewThreshold, err, "Failed to publish reshare success message", natMsg) + ec.handleReshareSessionError(walletID, keyType, msg.NewThreshold, err, "Failed to publish reshare success message", natMsg) return } logger.Info("[COMPLETED RESHARE] Successfully published", "walletID", walletID) @@ -837,7 +820,6 @@ func (ec *eventConsumer) consumeReshareEvent() error { // handleReshareSessionError handles errors that occur during reshare operations func (ec *eventConsumer) handleReshareSessionError( - clientID string, walletID string, keyType types.KeyType, newThreshold int, @@ -850,7 +832,6 @@ func (ec *eventConsumer) handleReshareSessionError( logger.Warn("Reshare session error", "walletID", walletID, - "clientID", clientID, "keyType", keyType, "newThreshold", newThreshold, "error", err.Error(), @@ -875,8 +856,8 @@ func (ec *eventConsumer) handleReshareSessionError( return } - resultTopic := fmt.Sprintf(mpc.TypeReshareWalletResultFmt, clientID, walletID) - err = ec.reshareResultQueue.Enqueue(resultTopic, reshareResultBytes, &messaging.EnqueueOptions{ + key := fmt.Sprintf(mpc.TypeReshareWalletResultFmt, walletID) + err = ec.reshareResultQueue.Enqueue(key, reshareResultBytes, &messaging.EnqueueOptions{ IdempotententKey: composeReshareIdempotentKey(walletID, natMsg), }) if err != nil { diff --git a/pkg/eventconsumer/keygen_consumer.go b/pkg/eventconsumer/keygen_consumer.go index d4e8cf5..e2f0714 100644 --- a/pkg/eventconsumer/keygen_consumer.go +++ b/pkg/eventconsumer/keygen_consumer.go @@ -222,9 +222,9 @@ func (sc *keygenConsumer) handleKeygenError(keygenMsg types.GenerateKeyMessage, return } - resultTopic := fmt.Sprintf(mpc.TypeGenerateWalletResultFmt, keygenMsg.ClientID, keygenResult.WalletID) - err = sc.keygenResultQueue.Enqueue(resultTopic, keygenResultBytes, &messaging.EnqueueOptions{ - IdempotententKey: buildIdempotentKey(keygenMsg.WalletID, sessionID, resultTopic), + topic := fmt.Sprintf(mpc.TypeGenerateWalletResultFmt, keygenResult.WalletID) + err = sc.keygenResultQueue.Enqueue(topic, keygenResultBytes, &messaging.EnqueueOptions{ + IdempotententKey: buildIdempotentKey(keygenMsg.WalletID, sessionID, mpc.TypeGenerateWalletResultFmt), }) if err != nil { logger.Error("Failed to enqueue keygen result event", err, diff --git a/pkg/eventconsumer/sign_consumer.go b/pkg/eventconsumer/sign_consumer.go index 4d207ed..b202a33 100644 --- a/pkg/eventconsumer/sign_consumer.go +++ b/pkg/eventconsumer/sign_consumer.go @@ -246,9 +246,8 @@ func (sc *signingConsumer) handleSigningError(signMsg types.SignTxMessage, error return } - resultTopic := fmt.Sprintf(mpc.TypeSigningResultFmt, signMsg.ClientID, signMsg.TxID) - err = sc.signingResultQueue.Enqueue(resultTopic, signingResultBytes, &messaging.EnqueueOptions{ - IdempotententKey: buildIdempotentKey(signMsg.TxID, sessionID, resultTopic), + err = sc.signingResultQueue.Enqueue(event.SigningResultCompleteTopic, signingResultBytes, &messaging.EnqueueOptions{ + IdempotententKey: buildIdempotentKey(signMsg.TxID, sessionID, mpc.TypeSigningResultFmt), }) if err != nil { logger.Error("Failed to enqueue signing result event", err, diff --git a/pkg/messaging/message_queue.go b/pkg/messaging/message_queue.go index 7745dc5..32ed3f9 100644 --- a/pkg/messaging/message_queue.go +++ b/pkg/messaging/message_queue.go @@ -27,11 +27,9 @@ type EnqueueOptions struct { type msgQueue struct { consumerName string - streamName string js jetstream.JetStream consumer jetstream.Consumer consumerContext jetstream.ConsumeContext - ephemeral bool // if true, consumer is deleted on Close } type NATsMessageQueueManager struct { @@ -60,9 +58,9 @@ func NewNATsMessageQueueManager(queueName string, subjectWildCards []string, nc Name: queueName, Description: "Stream for " + queueName, Subjects: subjectWildCards, - MaxBytes: 104_857_600, // 100 MB + MaxBytes: 10_485_760, // Light Production (Low Traffic) (10 MB) Storage: jetstream.FileStorage, - Retention: jetstream.LimitsPolicy, + Retention: jetstream.WorkQueuePolicy, }) if err != nil { logger.Fatal("Error creating JetStream stream: ", err) @@ -103,40 +101,6 @@ func (m *NATsMessageQueueManager) NewMessageQueue(consumerName string) MessageQu return mq } -// NewClientMessageQueue creates a per-client consumer that only receives results -// addressed to this specific clientID. The consumer uses DeliverNewPolicy so it -// only sees messages published after it connects. The consumer is ephemeral -// (no Durable name) and auto-deletes after InactiveThreshold. -func (m *NATsMessageQueueManager) NewClientMessageQueue(consumerName, clientID string) MessageQueue { - mq := &msgQueue{ - consumerName: consumerName + "_" + clientID, - streamName: m.queueName, - js: m.js, - ephemeral: true, - } - // Filter to only this client's results: e.g. mpc.mpc_signing_result..> - consumerFilter := fmt.Sprintf("%s.%s.%s.>", m.queueName, consumerName, clientID) - cfg := jetstream.ConsumerConfig{ - MaxAckPending: 1000, - AckWait: 30 * time.Second, - AckPolicy: jetstream.AckExplicitPolicy, - DeliverPolicy: jetstream.DeliverNewPolicy, - InactiveThreshold: 5 * time.Minute, - FilterSubjects: []string{ - consumerFilter, - }, - MaxDeliver: 3, - } - logger.Info("Creating per-client consumer", "consumerName", mq.consumerName, "queueName", m.queueName, "filterSubject", consumerFilter) - consumer, err := m.js.CreateOrUpdateConsumer(context.Background(), m.queueName, cfg) - if err != nil { - logger.Fatal("Error creating JetStream per-client consumer: ", err) - } - - mq.consumer = consumer - return mq -} - func (mq *msgQueue) Enqueue(topic string, message []byte, options *EnqueueOptions) error { header := nats.Header{} if options != nil { diff --git a/pkg/mpc/ecdsa_signing_session.go b/pkg/mpc/ecdsa_signing_session.go index dcc537a..9664e08 100644 --- a/pkg/mpc/ecdsa_signing_session.go +++ b/pkg/mpc/ecdsa_signing_session.go @@ -42,7 +42,6 @@ type ecdsaSigningSession struct { data *keygen.LocalPartySaveData tx *big.Int txID string - clientID string networkInternalCode string derivationPath []uint32 ckd *CKD @@ -51,7 +50,6 @@ type ecdsaSigningSession struct { func newECDSASigningSession( walletID string, txID string, - clientID string, networkInternalCode string, pubSub messaging.PubSub, direct messaging.DirectMessaging, @@ -102,7 +100,6 @@ func newECDSASigningSession( }, endCh: make(chan *common.SignatureData), txID: txID, - clientID: clientID, networkInternalCode: networkInternalCode, derivationPath: derivationPath, ckd: ckd, @@ -218,8 +215,7 @@ func (s *ecdsaSigningSession) Sign(onSuccess func(data []byte)) { return } - resultTopic := fmt.Sprintf(TypeSigningResultFmt, s.clientID, s.txID) - err = s.resultQueue.Enqueue(resultTopic, bytes, &messaging.EnqueueOptions{ + err = s.resultQueue.Enqueue(event.SigningResultCompleteTopic, bytes, &messaging.EnqueueOptions{ IdempotententKey: s.idempotentKey, }) if err != nil { diff --git a/pkg/mpc/eddsa_signing_session.go b/pkg/mpc/eddsa_signing_session.go index 01329ed..2c11fda 100644 --- a/pkg/mpc/eddsa_signing_session.go +++ b/pkg/mpc/eddsa_signing_session.go @@ -27,7 +27,6 @@ type eddsaSigningSession struct { data *keygen.LocalPartySaveData tx *big.Int txID string - clientID string networkInternalCode string derivationPath []uint32 ckd *CKD @@ -36,7 +35,6 @@ type eddsaSigningSession struct { func newEDDSASigningSession( walletID string, txID string, - clientID string, networkInternalCode string, pubSub messaging.PubSub, direct messaging.DirectMessaging, @@ -84,7 +82,6 @@ func newEDDSASigningSession( }, endCh: make(chan *common.SignatureData), txID: txID, - clientID: clientID, networkInternalCode: networkInternalCode, derivationPath: derivationPath, ckd: ckd, @@ -197,8 +194,7 @@ func (s *eddsaSigningSession) Sign(onSuccess func(data []byte)) { return } - resultTopic := fmt.Sprintf(TypeSigningResultFmt, s.clientID, s.txID) - err = s.resultQueue.Enqueue(resultTopic, bytes, &messaging.EnqueueOptions{ + err = s.resultQueue.Enqueue(event.SigningResultCompleteTopic, bytes, &messaging.EnqueueOptions{ IdempotententKey: s.idempotentKey, }) if err != nil { diff --git a/pkg/mpc/node.go b/pkg/mpc/node.go index 4769405..faa842a 100644 --- a/pkg/mpc/node.go +++ b/pkg/mpc/node.go @@ -146,7 +146,6 @@ func (p *Node) CreateSigningSession( sessionType SessionType, walletID string, txID string, - clientID string, networkInternalCode string, resultQueue messaging.MessageQueue, derivationPath []uint32, @@ -185,7 +184,6 @@ func (p *Node) CreateSigningSession( return newECDSASigningSession( walletID, txID, - clientID, networkInternalCode, p.pubSub, p.direct, @@ -207,7 +205,6 @@ func (p *Node) CreateSigningSession( return newEDDSASigningSession( walletID, txID, - clientID, networkInternalCode, p.pubSub, p.direct, diff --git a/pkg/mpc/session.go b/pkg/mpc/session.go index 76ba376..dc5651f 100644 --- a/pkg/mpc/session.go +++ b/pkg/mpc/session.go @@ -22,11 +22,9 @@ import ( type SessionType string const ( - // Result topic format: mpc.mpc__result.. - // The clientID segment ensures each client only receives its own results. - TypeGenerateWalletResultFmt = "mpc.mpc_keygen_result.%s.%s" - TypeReshareWalletResultFmt = "mpc.mpc_reshare_result.%s.%s" - TypeSigningResultFmt = "mpc.mpc_signing_result.%s.%s" + TypeGenerateWalletResultFmt = "mpc.mpc_keygen_result.%s" + TypeReshareWalletResultFmt = "mpc.mpc_reshare_result.%s" + TypeSigningResultFmt = "mpc.mpc_signing_result.%s" SessionTypeECDSA SessionType = "session_ecdsa" SessionTypeEDDSA SessionType = "session_eddsa" diff --git a/pkg/types/initiator_msg.go b/pkg/types/initiator_msg.go index 8ed0f15..6100492 100644 --- a/pkg/types/initiator_msg.go +++ b/pkg/types/initiator_msg.go @@ -36,7 +36,6 @@ type InitiatorMessage interface { type GenerateKeyMessage struct { WalletID string `json:"wallet_id"` - ClientID string `json:"client_id,omitempty"` Signature []byte `json:"signature"` AuthorizerSignatures []AuthorizerSignature `json:"authorizer_signatures,omitempty"` } @@ -47,7 +46,6 @@ type SignTxMessage struct { NetworkInternalCode string `json:"network_internal_code"` TxID string `json:"tx_id"` Tx []byte `json:"tx"` - ClientID string `json:"client_id,omitempty"` Signature []byte `json:"signature"` DerivationPath []uint32 `json:"derivation_path"` AuthorizerSignatures []AuthorizerSignature `json:"authorizer_signatures,omitempty"` @@ -59,7 +57,6 @@ type ResharingMessage struct { NewThreshold int `json:"new_threshold"` KeyType KeyType `json:"key_type"` WalletID string `json:"wallet_id"` - ClientID string `json:"client_id,omitempty"` Signature []byte `json:"signature,omitempty"` AuthorizerSignatures []AuthorizerSignature `json:"authorizer_signatures,omitempty"` } From 6b8d963645aeff2fe0cec8274bc9845fea69f8d3 Mon Sep 17 00:00:00 2001 From: anhthii Date: Mon, 16 Mar 2026 10:21:10 +0700 Subject: [PATCH 06/11] Update JetStream stream defaults: increase max age to 7 days and max bytes to 100MB - Remove per-broker WithMaxAge overrides in favor of the new default - Add WithMaxBytes broker option for configurable stream size limits - Increase message queue max bytes from 10MB to 100MB --- cmd/mpcium/main.go | 2 -- pkg/messaging/jetstream_broker.go | 12 +++++++++++- pkg/messaging/message_queue.go | 2 +- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/cmd/mpcium/main.go b/cmd/mpcium/main.go index f9b7b88..418caae 100644 --- a/cmd/mpcium/main.go +++ b/cmd/mpcium/main.go @@ -201,7 +201,6 @@ func runNode(ctx context.Context, c *cli.Command) error { keygenBroker, err := messaging.NewJetStreamBroker(ctx, natsConn, event.KeygenBrokerStream, []string{ event.KeygenRequestTopic, }, - messaging.WithMaxAge(24*time.Hour), messaging.WithMaxAckPending(maxConcurrentKeygen), ) if err != nil { @@ -210,7 +209,6 @@ func runNode(ctx context.Context, c *cli.Command) error { signingBroker, err := messaging.NewJetStreamBroker(ctx, natsConn, event.SigningPublisherStream, []string{ event.SigningRequestTopic, }, - messaging.WithMaxAge(24*time.Hour), messaging.WithMaxAckPending(maxConcurrentSigning), ) if err != nil { diff --git a/pkg/messaging/jetstream_broker.go b/pkg/messaging/jetstream_broker.go index c70df9b..8f8a606 100644 --- a/pkg/messaging/jetstream_broker.go +++ b/pkg/messaging/jetstream_broker.go @@ -27,7 +27,8 @@ const ( DefaultAckWait = 30 * time.Second DefaultMaxDeliveryAttempts = 3 DefaultConsumerPrefix = "consumer" - DefaultStreamMaxAge = 3 * time.Minute + DefaultStreamMaxAge = 7 * 24 * time.Hour + DefaultStreamMaxBytes = int64(100_000_000) DefaultBackoffDuration = 30 * time.Second ) @@ -59,6 +60,7 @@ type brokerConfiguration struct { deliverPolicy jetstream.DeliverPolicy backoffDurations []time.Duration maxAckPending int + maxBytes int64 } func WithStreamDescription(description string) BrokerOption { @@ -128,6 +130,12 @@ func WithBackoffDurations(durations []time.Duration) BrokerOption { // instead of being pushed to consumers that have no capacity to process them. // Set this to match the desired processing concurrency (e.g. 2 for keygen, // 20 for signing). +func WithMaxBytes(maxBytes int64) BrokerOption { + return func(cfg *brokerConfiguration) { + cfg.maxBytes = maxBytes + } +} + func WithMaxAckPending(maxAckPending int) BrokerOption { return func(cfg *brokerConfiguration) { cfg.maxAckPending = maxAckPending @@ -154,6 +162,7 @@ func NewJetStreamBroker( retention: nats.InterestPolicy, storage: nats.FileStorage, maxAge: DefaultStreamMaxAge, + maxBytes: DefaultStreamMaxBytes, discard: nats.DiscardOld, ackWait: DefaultAckWait, maxDeliveryAttempts: DefaultMaxDeliveryAttempts, @@ -191,6 +200,7 @@ func (b *jetStreamBroker) ensureStreamExists(ctx context.Context) error { Description: b.config.description, Subjects: b.config.subjects, MaxAge: b.config.maxAge, + MaxBytes: b.config.maxBytes, } _, err := b.js.CreateOrUpdateStream(ctx, streamConfig) diff --git a/pkg/messaging/message_queue.go b/pkg/messaging/message_queue.go index 32ed3f9..6eec56e 100644 --- a/pkg/messaging/message_queue.go +++ b/pkg/messaging/message_queue.go @@ -58,7 +58,7 @@ func NewNATsMessageQueueManager(queueName string, subjectWildCards []string, nc Name: queueName, Description: "Stream for " + queueName, Subjects: subjectWildCards, - MaxBytes: 10_485_760, // Light Production (Low Traffic) (10 MB) + MaxBytes: 100_000_000, // 100 MB Storage: jetstream.FileStorage, Retention: jetstream.WorkQueuePolicy, }) From 5ea0a749986f7e43337ea623504a798edfb1000d Mon Sep 17 00:00:00 2001 From: anhthii Date: Mon, 16 Mar 2026 10:44:29 +0700 Subject: [PATCH 07/11] Remove dead warmUpSession code and config The warmUpSession sleep was replaced by the proper WaitForPeersReady barrier handshake but the old code and config were never cleaned up. --- config.yaml.template | 1 - pkg/eventconsumer/event_consumer.go | 16 ---------------- 2 files changed, 17 deletions(-) diff --git a/config.yaml.template b/config.yaml.template index 1f9ad81..83243b7 100644 --- a/config.yaml.template +++ b/config.yaml.template @@ -21,7 +21,6 @@ backup_period_seconds: 300 # 5 minutes backup_dir: backups max_concurrent_keygen: 2 max_concurrent_signing: 10 -session_warm_up_delay_ms: 100 healthcheck: enabled: false # disabled by default, set to true for cloud deployment address: "0.0.0.0:8080" diff --git a/pkg/eventconsumer/event_consumer.go b/pkg/eventconsumer/event_consumer.go index e1c973a..9e2ecb3 100644 --- a/pkg/eventconsumer/event_consumer.go +++ b/pkg/eventconsumer/event_consumer.go @@ -27,8 +27,6 @@ const ( DefaultConcurrentKeygen = 2 DefaultConcurrentSigning = 20 - DefaultSessionWarmUpDelay = 200 - KeyGenTimeOut = 30 * time.Second ) @@ -55,8 +53,6 @@ type eventConsumer struct { signingMsgBuffer chan *nats.Msg maxConcurrentKeygen int maxConcurrentSigning int - sessionWarmUpDelayMs int - // Track active sessions with timestamps for cleanup activeSessions map[string]time.Time // Maps "walletID-txID" to creation time sessionsLock sync.RWMutex @@ -83,19 +79,12 @@ func NewEventConsumer( maxConcurrentSigning = DefaultConcurrentSigning } - sessionWarmUpDelayMs := viper.GetInt("session_warm_up_delay_ms") - if sessionWarmUpDelayMs == 0 { - sessionWarmUpDelayMs = DefaultSessionWarmUpDelay - } - logger.Info( "Initializing event consumer", "max_concurrent_keygen", maxConcurrentKeygen, "max_concurrent_signing", maxConcurrentSigning, - "session_warm_up_delay_ms", - sessionWarmUpDelayMs, ) ec := &eventConsumer{ @@ -114,7 +103,6 @@ func NewEventConsumer( identityStore: identityStore, keygenMsgBuffer: make(chan *nats.Msg, 100), signingMsgBuffer: make(chan *nats.Msg, 200), // Larger buffer for signing - sessionWarmUpDelayMs: sessionWarmUpDelayMs, } go ec.startKeyGenEventWorker() @@ -144,10 +132,6 @@ func (ec *eventConsumer) Run() { logger.Info("MPC Event consumer started...!") } -func (ec *eventConsumer) warmUpSession() { - time.Sleep(time.Duration(ec.sessionWarmUpDelayMs) * time.Millisecond) -} - func (ec *eventConsumer) handleKeyGenEvent(natMsg *nats.Msg) { baseCtx, baseCancel := context.WithTimeout(context.Background(), KeyGenTimeOut) defer baseCancel() From b78706b0c0db2be034112fa63253e88cb2f31199 Mon Sep 17 00:00:00 2001 From: anhthii Date: Wed, 18 Mar 2026 23:15:25 +0700 Subject: [PATCH 08/11] Fix e2e --- e2e/base_test.go | 73 ++++++++++++++++++++++++++++ e2e/cmd/generate-preparams/main.go | 62 +++++++++++++++++++++++ e2e/fixtures/node0_pre_params_0.json | 1 + e2e/fixtures/node0_pre_params_1.json | 1 + e2e/fixtures/node1_pre_params_0.json | 1 + e2e/fixtures/node1_pre_params_1.json | 1 + e2e/fixtures/node2_pre_params_0.json | 1 + e2e/fixtures/node2_pre_params_1.json | 1 + e2e/go.mod | 4 +- e2e/go.sum | 16 +----- e2e/keygen_test.go | 2 + e2e/reshare_test.go | 1 + e2e/sign_ckd_test.go | 2 + e2e/sign_test.go | 2 + 14 files changed, 152 insertions(+), 16 deletions(-) create mode 100644 e2e/cmd/generate-preparams/main.go create mode 100644 e2e/fixtures/node0_pre_params_0.json create mode 100644 e2e/fixtures/node0_pre_params_1.json create mode 100644 e2e/fixtures/node1_pre_params_0.json create mode 100644 e2e/fixtures/node1_pre_params_1.json create mode 100644 e2e/fixtures/node2_pre_params_0.json create mode 100644 e2e/fixtures/node2_pre_params_1.json diff --git a/e2e/base_test.go b/e2e/base_test.go index 5c209c4..1ad6234 100644 --- a/e2e/base_test.go +++ b/e2e/base_test.go @@ -264,6 +264,79 @@ func (s *E2ETestSuite) RegisterPeers(t *testing.T) { t.Log("Peer listing completed") } +// SeedPreParams loads pre-generated ECDSA pre-parameters from fixture files +// and writes them into each node's BadgerDB. This avoids the expensive safe-prime +// generation at node startup which can take minutes on CI runners. +// +// Each node gets its own unique pre-parameters. Sharing the same pre-parameters +// across nodes causes tss-lib to reject duplicate h1j values during keygen round 2. +func (s *E2ETestSuite) SeedPreParams(t *testing.T) { + t.Log("Seeding pre-generated pre-params into node databases...") + + // Read the badger password from a node config + configPath := filepath.Join(s.testDir, "test_node0", "config.yaml") + configData, err := os.ReadFile(configPath) + require.NoError(t, err, "Failed to read node config for badger password") + + var nodeConfig struct { + BadgerPassword string `yaml:"badger_password"` + DbPath string `yaml:"db_path"` + } + require.NoError(t, yaml.Unmarshal(configData, &nodeConfig), "Failed to parse node config") + + dbBasePath := nodeConfig.DbPath + if dbBasePath == "" { + dbBasePath = "./db" + } + + for i := 0; i < numNodes; i++ { + nodeName := fmt.Sprintf("test_node%d", i) + + // Load per-node fixture files + fixtureData := make([][]byte, 2) + for j := 0; j < 2; j++ { + path := filepath.Join(s.testDir, "fixtures", fmt.Sprintf("node%d_pre_params_%d.json", i, j)) + data, err := os.ReadFile(path) + if err != nil { + t.Logf("Warning: could not read pre-params fixture %s: %v (nodes will generate their own)", path, err) + return + } + fixtureData[j] = data + } + + nodeDir := filepath.Join(s.testDir, nodeName) + dbPath := filepath.Join(nodeDir, dbBasePath, nodeName) + + // Ensure the DB directory exists + require.NoError(t, os.MkdirAll(dbPath, 0755), "Failed to create DB directory for %s", nodeName) + + // Open BadgerDB with the same options the node uses + opts := badger.DefaultOptions(dbPath). + WithCompression(options.ZSTD). + WithEncryptionKey([]byte(nodeConfig.BadgerPassword)). + WithIndexCacheSize(16 << 20). + WithBlockCacheSize(32 << 20). + WithLogger(nil) + + db, err := badger.Open(opts) + require.NoError(t, err, "Failed to open BadgerDB for %s", nodeName) + + // Write pre-params + for j := 0; j < 2; j++ { + key := fmt.Sprintf("pre_params_%d", j) + err := db.Update(func(txn *badger.Txn) error { + return txn.Set([]byte(key), fixtureData[j]) + }) + require.NoError(t, err, "Failed to seed %s for %s", key, nodeName) + } + + require.NoError(t, db.Close(), "Failed to close BadgerDB for %s", nodeName) + t.Logf("Seeded pre-params for %s", nodeName) + } + + t.Log("Pre-params seeding complete") +} + func (s *E2ETestSuite) StartNodes(t *testing.T) { t.Log("Starting MPC nodes...") diff --git a/e2e/cmd/generate-preparams/main.go b/e2e/cmd/generate-preparams/main.go new file mode 100644 index 0000000..9b676d2 --- /dev/null +++ b/e2e/cmd/generate-preparams/main.go @@ -0,0 +1,62 @@ +// generate-preparams pre-computes ECDSA pre-parameters and writes them as +// JSON fixture files. Run once from the e2e directory (or whenever you need +// fresh fixtures): +// +// cd e2e && go run ./cmd/generate-preparams +// +// The output files (fixtures/node{N}_pre_params_{0,1}.json) are checked into +// the repo so that E2E tests can seed them into each node's BadgerDB, avoiding +// the expensive safe-prime generation at node startup. +// +// Each node gets its own unique pre-parameters — sharing pre-parameters across +// nodes causes tss-lib to reject duplicate h1j values during keygen round 2. +package main + +import ( + "encoding/json" + "fmt" + "os" + "path/filepath" + "time" + + "github.com/bnb-chain/tss-lib/v2/ecdsa/keygen" +) + +const numNodes = 3 + +func main() { + outDir := "fixtures" + if err := os.MkdirAll(outDir, 0755); err != nil { + fmt.Fprintf(os.Stderr, "MkdirAll: %v\n", err) + os.Exit(1) + } + + for node := 0; node < numNodes; node++ { + for i := 0; i < 2; i++ { + name := fmt.Sprintf("node%d_pre_params_%d", node, i) + fmt.Printf("Generating %s (this may take a minute)...\n", name) + start := time.Now() + params, err := keygen.GeneratePreParams(5 * time.Minute) + if err != nil { + fmt.Fprintf(os.Stderr, "GeneratePreParams failed: %v\n", err) + os.Exit(1) + } + fmt.Printf(" done in %s\n", time.Since(start).Round(time.Millisecond)) + + data, err := json.Marshal(params) + if err != nil { + fmt.Fprintf(os.Stderr, "json.Marshal failed: %v\n", err) + os.Exit(1) + } + + out := filepath.Join(outDir, name+".json") + if err := os.WriteFile(out, data, 0644); err != nil { + fmt.Fprintf(os.Stderr, "WriteFile: %v\n", err) + os.Exit(1) + } + fmt.Printf(" wrote %s (%d bytes)\n", out, len(data)) + } + } + + fmt.Println("Done – fixture files are ready.") +} diff --git a/e2e/fixtures/node0_pre_params_0.json b/e2e/fixtures/node0_pre_params_0.json new file mode 100644 index 0000000..07139e5 --- /dev/null +++ b/e2e/fixtures/node0_pre_params_0.json @@ -0,0 +1 @@ +{"PaillierSK":{"N":25109905458989267426538098396709244292268478052491606142401927631059547309589820096686160752850851453993269954862157722785497832749590747763498048657298326998614246663577418165062348870047752715587946828268697538707240362115556588690566734463468367738035966139894847035322707324142267773323556186761137815245286107133671739805087255811013031586295490243847907364780089861950020661050135665652634308242677813852667544558248338857621161609240351900427448173029768222001575632458838215952176212099760499457142337257296697872989533954042593416781300987446759163283434834549758294673475634021828407166576040099658920257621,"LambdaN":12554952729494633713269049198354622146134239026245803071200963815529773654794910048343080376425425726996634977431078861392748916374795373881749024328649163499307123331788709082531174435023876357793973414134348769353620181057778294345283367231734183869017983069947423517661353662071133886661778093380568907622483815287472573313869981996945141830785904539940091245166628881243458083037969804010799433231686554261946474351880994949134821871878056856034307960797744282723131340242767426972453275180274077767550552046682961110257121859870941821935679930042899285272996264650765403193220755608371726020019808479577817437766,"PhiN":25109905458989267426538098396709244292268478052491606142401927631059547309589820096686160752850851453993269954862157722785497832749590747763498048657298326998614246663577418165062348870047752715587946828268697538707240362115556588690566734463468367738035966139894847035322707324142267773323556186761137815244967630574945146627739963993890283661571809079880182490333257762486916166075939608021598866463373108523892948703761989898269643743756113712068615921595488565446262680485534853944906550360548155535101104093365922220514243719741883643871359860085798570545992529301530806386441511216743452040039616959155634875532,"P":143524458835047553101016095085255056949895826978649948466577105797616555332180533290925013574387105402281835929733333752421784359939061083571826716455433064229785558292135761469424911609761812416729691598125551827903486840433842452153116452249046851945807909151606623518500660047285227205641580479626952197443,"Q":174952099891545624246275722037492867773785336989074925980254993665487939642015524340110428204917599926492759924753015206929733505545177104787005534978846592325527393681167600537844750129450531505311541565805223824571803393866867320756824675111913740791634396096620864768533462757799727920894842660876333184647},"NTildei":22412835943963862078111908299493686283867322523796478934529170772784964952620945056860020944970432480272095849840432608286715915989040425857202288548977357847057957630988277296130925536518971623587045592210563753985123309662058917060931532173474878070342140630559306731435997656015123532996152143184363151702681426378061527968292390180225169165368787046527767573423215678002965495535369233031611110323072620936359085981819260004298912908582290246574453550724871005084991242188489983582274144201962182265786537868024453172662036363090410693285522499245136535531739261546592298324862130567715636389710771626263941709361,"H1i":4143027230159654260062558934020609421301931174674214924914072966186410493683183047415402217780278454223394982469790805225827794201253462931213504320319949784920933773844274254521019516783231966765104055452373267796306254472622122142413515296451823459442932029496131131847703168532111686717499422455140204466169732750257684318205966413660522683227886097348329395828804830058812726869219939800483987248508854164574030699471887744089198617492568902067236230599525143399437581378425537979329824526536209661047260806499704315343784520331823919390221016950728942168607059464397960826695211107587894675832237441754895140412,"H2i":16301142751627308840085377519543687062320738303322826601668002311767143877911933249144980730948686884409329382404042750916395485901520373278136442005194324843665860819686312108893891323765024710641351760968345808225161879004883474594418460647046182758585529722196283979490026175670386961909484214778413756369680731687128497413812365770507199005426963438584392743642238518315927302844837391312092519867354403333147895168967865999702883424029367641553247519336028961124436086797048778971587656272370960479659069887623087017781378885595334146563079016281969975925156203511268977560676669933680316411531923970756351511879,"Alpha":22292524340989371173869503741332607843011717104933858203042975804190325529167914473354644806098099095313747334964740144791161888111609003604754957992405339765324697376340412414769197356632510965834982303250804275441273908322250510295889168036963828004885243440712595185084508748684699823468951031368898357500155410066416244885782640589393669137055690558995377042413798552759149084114391529775583138807794919164679864483620945554986129898661647360956400895142346512084369986202757677989739391001130152774667434085908354749083101880575477005942875780798079889389844548188780363000595774870843799684383929093092425285069,"Beta":2770962216928678851929416217924560903451762450669438117092852647475182234816423219528767462313090626433952649932915187495988023765357016381902332118693922257242987602625765961736196862283641832849922928381840165378181015055942791637165771035565319178674537524185703345040635205876849528771799665457939033737453245413470607269320878946798975502421336924879535055917285720594848534776087137076144631601448665169053349336761807747131181647286906858539701756378122082092360362375651103648932205969693086630010482259074924000814037290155331227185850739206768454271846978666603564404550486117607554241474094047364427706549,"P":79610937014992579855497200628829420895821793269518938776503350205195796128636858520124936967444328298168672557012256738738125828648795940111067877187220284483328903879197087929088562532305484474709157192045940218446288892140314972170500767162250704965071700709716327824459954457489740939949912652968037725779,"Q":70382402168382363526217323116248764414318909597205231445175392613372657468207798992617936029879270382235441038639607575775691905199522935660272746735426686127090004308204553576636013931192792453766899328260521207105453935195731809208020962086224952281323159476201841506569911958348685440400781893034442485939} \ No newline at end of file diff --git a/e2e/fixtures/node0_pre_params_1.json b/e2e/fixtures/node0_pre_params_1.json new file mode 100644 index 0000000..c7c5006 --- /dev/null +++ b/e2e/fixtures/node0_pre_params_1.json @@ -0,0 +1 @@ +{"PaillierSK":{"N":25097803967897955667661176827061648658245979790175757280091304274394147012277048481614735380079420505996987395584924660090877492515275567744308004694945181130966074210032772302468227792531997221576800873060376993776936488786367881553794773034148551020157650361779547415921853650054817087272414581936459563529678600025487929664606603472021105864865772674175104932834644578522895708383313173480033483918490029216923619564145025370444555521379470824521115455743708876243237271593952597548645430390366525733977565933193462218148924117813373108942793640018392885609903475571881057515975538795345694306924234470062288265081,"LambdaN":12548901983948977833830588413530824329122989895087878640045652137197073506138524240807367690039710252998493697792462330045438746257637783872154002347472590565483037105016386151234113896265998610788400436530188496888468244393183940776897386517074275510078825180889773707960926825027408543636207290968229781764679768966280761407848480452032369172849930176634182374861109336479056933262479974253635087460808521235697331795194134111357833286911376300581241004057649759339491132456042706718787080798900697123392113111840232954518975133872698556367919165813361487512843084212529322420564688827059622564465247312219626558906,"PhiN":25097803967897955667661176827061648658245979790175757280091304274394147012277048481614735380079420505996987395584924660090877492515275567744308004694945181130966074210032772302468227792531997221576800873060376993776936488786367881553794773034148551020157650361779547415921853650054817087272414581936459563529359537932561522815696960904064738345699860353268364749722218672958113866524959948507270174921617042471394663590388268222715666573822752601162482008115299518678982264912085413437574161597801394246784226223680465909037950267745397112735838331626722975025686168425058644841129377654119245128930494624439253117812,"P":140760036427863978847829504206942315107492181142124771662216359190291162949313543007862069658401195839218581284611989938967951743442777333329568578661184235222374080028593678658619134711765049202558398936715549808091698384353326079319239048955912155990892847017855691490823969390648710834642150179469582996623,"Q":178302056498542870061813063749425204058420139764615411450209546374490678909039681964901239338471790906310374689144767208760937204113940890029064868967225122341880926653273505452452134080800082284634940772797446501019275465714649916887716259435757754593324460128966721184022191750577738343351589666153452150647},"NTildei":25515755631084046936019592594381488930581940150493700486250855908857048885946906653163947891309626488788342294244749772106438382892530860939950125535721477079423542239476377255488261268405907428474370031127878055105597625267633842600390777274714763552451158376515788968523698848283395769609561281475793847058098614565947777924247799064437092712772745724692199621831746843492940972193267780631907753599581301274667359192624811774074884836974643999101178015100783614993162192507577273154306020944125341641567370414920582272947639758120992594957037070013751475117189729227259176804247746146914798774515213547650108730249,"H1i":21275609582169210345330956943317845887027642725710153107442434168056764630155585135190799731256053836106824926732598300584662823012088717707266694010140880761466149792897420804955564131999621825011209901133097442215600943546860016511892877857505914499889651191067137435503002475522113354412049779696512435940636507870950155676473346630818137835633791488377017462519942252447804651590558490916968681975610927667268387087886797707976227694120514134356700368447924043392589649016123089763693229400240744109653127720095847619522008173231988560164593895446320372537782385874014584773773954656283059185051044956280257642105,"H2i":13415066556320691063550843028024152348570518847817903435378458408669113129883406922825601020734539155600789765487620903113942696849377917814591048019548668631549230930726169450541363913814446789057345323087915793242819966035379705427247567318746438505877559523687642090826983929030848147000757778340492366699196978061361267896804470003315834644987548587244686079731917945843093793870583739326829113145576671102299094293041714885178830800858429671696832990543026417422424672437400140401044464907310085018583046240119961671522970022454769433999495789713841428055233703631766566494683413156026160466227541159203326262991,"Alpha":23608802783059939400553767537074844618960713717262535580624377650491271232095286753996074743775504564925885854050279255493401735030867224553124958616427167584894399585386600082639517249829640544823956575276654556067880241850078240282310468444318868827386803602358821654090005726169486512506432346207973671093250123801499684249433377428134701457449077591043530879576818559390727738095292836716779109603196907697981263090998359756443658198011057493526601232084971951558012214119005079060659228261112544119573147123179414598064268251835514589212131518210691993083687372077114346215717847742400503111345346689388872599857,"Beta":4762910739028817878131294814065134989371678736907905936548737134903786651855451230209988909332909766982327385084836803260849267495048625769371684631611531524396591400970220628105326722622110357525040355066021176627802809560028019362844930445718088017298293246899236810110401267590856055399929458614055782136750836399150323898483757212305674795114499241411880095409994461961230528154678391900008369447042468229779959362359758472717991068582074218537691097858456493847862685441641671342031442858363847486750290794153405378480016608281817643100155033072531852288797791905012997866773757274528172687653022251646405799836,"P":80307187263583982118401998752866251630113037154758667831070497325796853124490739698988703706710712906597059148160249386033677420339939173149703220533215522192405788957601805363921777908868957428517541860173220507571690858530784928123831858790208273598735363304133997707155308620425498168016465529523867169851,"Q":79431731145483650574387825118019380798206387487280151539711811626750010943060196352142772179599157450147407634183149080408198089075870073068960728676653303185105028027333140077221867282569579103860304755291896216654576868527407538802086558364708550371721976966360758665308798256269994244448543853629506504191} \ No newline at end of file diff --git a/e2e/fixtures/node1_pre_params_0.json b/e2e/fixtures/node1_pre_params_0.json new file mode 100644 index 0000000..b5bf628 --- /dev/null +++ b/e2e/fixtures/node1_pre_params_0.json @@ -0,0 +1 @@ +{"PaillierSK":{"N":24834456718938282039240906047924191778047629152617262664290898041337960900135106045602966799874588769010789535334887300085177972224195435891900976797252067706261038509860691105485874818384099021498555524930020358934191649288105835575760038284063011606197363567889116419881919504971299425881874906555467962182115618293776236692290134912530635858595400795473061620773200793201791277561180949859055393724361289012367700501912314516457643997079545281286070422477011923463407456055100394013478184879138206962169352427826605455724182172911053313972102307587978317426805783559744566298562801425635584632196399955801591644697,"LambdaN":12417228359469141019620453023962095889023814576308631332145449020668980450067553022801483399937294384505394767667443650042588986112097717945950488398626033853130519254930345552742937409192049510749277762465010179467095824644052917787880019142031505803098681783944558209940959752485649712940937453277733981090899706629011217111211865549658766649117050172472707455927109127290904858991507918098295926152840164133204594898046041764332983698720220837265151339853370817615539750544601534807221837508830671452559394014596421764363631123904888943812181021707056886351364226476187232674223421781486011577596950101489580962138,"PhiN":24834456718938282039240906047924191778047629152617262664290898041337960900135106045602966799874588769010789535334887300085177972224195435891900976797252067706261038509860691105485874818384099021498555524930020358934191649288105835575760038284063011606197363567889116419881919504971299425881874906555467962181799413258022434222423731099317533298234100344945414911854218254581809717983015836196591852305680328266409189796092083528665967397440441674530302679706741635231079501089203069614443675017661342905118788029192843528727262247809777887624362043414113772702728452952374465348446843562972023155193900202979161924276,"P":145376582151871325117475350583785126479156652539574637654719729125508773610288238193100208568709158464506341635855848296738029498572187995460549376594504596326182831761284165418132219596237995230974397875460915736161352986820674626052623137847285265556092928644245877635957252607310612631642563267731074478479,"Q":170828453601931144748928462629317433882143797988072071264262809494472785967876875469363332849971802281452169069964382691053647101066915611295218366175765691906145123204613158980902290265238868826076166523172846190835566938280600800295117126326579279167984401963124223314158705255352948845359936485091355241943},"NTildei":28778141825152879515392577237645052503726454821681354946934175729029120618789369287989963187001598593366692565408421238431036657783633634610273148751339605471908001791949550062749372709203450859779301723615399248831199251940842630610043374378396908214438253162709868898622054898634966442071542577771428478523958949602599313871589656501280416058887783514196065293079541480993413978883254437848973067381015176450156518348989083246593791451141553888107227052825618342898665765088597559616758326635100496500679815953899257948330076828658277098482557183714424790101622274329622595510011640183151598687246384742742005266681,"H1i":12648794448592308581295509128245472978815843510148702997035555193867305889693560733037216252304612099408590433035350841336810522230129379328964541718013104319918766504718772033994264308126726315904546300363995372777491444922982483066762489226206057558803419978897804301058117783254028593146107034579499821777648965962238800317158735968358767470401313837534216016433970657668311561140964865913961949905107660713856669278572485233422008996777538250096699628108013563516661593337055049199458706893441382037722978502698144593543779957764293984288771715133371075336421252903212152301666944328952916909306847895128172837745,"H2i":16017574885772078587975839572543159228649178245693610823869184662586667920501158467347837438998183297887119959223837212227570221326674056349120721236143832918334919222664235779575994935797256749407020520421477245310888508207409328345281620643793299173372001171327904039759146551050713836851066951963326931357969689830880778288854790433966342726873595464519147387025956074437350255809529141109405513680215727601968731470004796334634462036039438364326417866796537781334160827220196821952960859016660591129333837563959267656899039186048404117466817773605297734574465394239213715850327250937057447141017263662924967873846,"Alpha":22913061724937015414524380429473207963084578085263568568824250708330219209063524286013277080752712642535387224498992397357061032711221452274647014688598651261112384714676381799757902378498987562076789889390732734315133447874045751798418077287556724174514210779012332631352960694813007959222533945375566216511136065436796842208244285720163265165271903306526485794844568419602978128890060904440875058838578306312437122293608080912544965949979635559845935198569202230581322570005095232528688856575112279730409816391872924641264953988781445355771273068291941920075620962747974212591869415911314341786955209259425587062134,"Beta":770614714378179412879965033969536101198365540786253808363099123724828438666442996117155520620377707296005643169269991210879480119707261179890743875582669217385064094890260303438946395955800678135630443654540388320752203136169567998668326406173812860405297677940972658735591469704174841690714166815095332455812201121811302721138941489246019318428036974516421640504064953323345503135545077306399927561790688941607465264006324017821752890392915833535924150694618105574946111971826234924159015634519021902915327597746656589106548001990897250553168219209444753742277651010873470659295411198567977144384176924496291125561,"P":88875381103078257125830404210002183034773910559839104103036383494835322612735649267145845630483411520052790456640821419217924726434004677003225929008936887634830466321335638043337558643590987193506878313174902050579364409244723446344990094793097881642049792333092895341358315041895725427974598861020540586239,"Q":80950825380359830870859679709100476517169334589308458856761452194905688685195334639120479736898435556275846450117022127712074568627545122497614465937079104371756758627990721210194072597714423485116054629631731768910763265143820515326367450642130459431902362969040206737707600985882092207261919629769702630019} \ No newline at end of file diff --git a/e2e/fixtures/node1_pre_params_1.json b/e2e/fixtures/node1_pre_params_1.json new file mode 100644 index 0000000..cdd169a --- /dev/null +++ b/e2e/fixtures/node1_pre_params_1.json @@ -0,0 +1 @@ +{"PaillierSK":{"N":27009962945051792575149947332094329229405480335492237634399814131043850957716876410500248762912424758463856593877979186630515221671153371296490191185087081879261912860479426624019133157935472496208965897932322197341188049450459297458592410966220672773456775280326227143719562655163946875689647136083555186467066241818097070439333357501671352180126814124320389691822362936716520667672064257636877529947791800835692357173280855371363690942506053835897416157896043012571666266007886649870539568763814653681050714819648057631880266666480681292749311283043255394172226993548741718851519912875782473980950714031180263848797,"LambdaN":13504981472525896287574973666047164614702740167746118817199907065521925478858438205250124381456212379231928296938989593315257610835576685648245095592543540939630956430239713312009566578967736248104482948966161098670594024725229648729296205483110336386728387640163113571859781327581973437844823568041777593233368530714871658122137705879939500880456895429460705965514723855576685387844662200916172574916125234063496007791223255956460669659237093268034506060121808499349688909997793644486649342215604637059331256270211273479986192665540286756303905047096881402362468406379595411905526022602036987553007151486028460289838,"PhiN":27009962945051792575149947332094329229405480335492237634399814131043850957716876410500248762912424758463856593877979186630515221671153371296490191185087081879261912860479426624019133157935472496208965897932322197341188049450459297458592410966220672773456775280326227143719562655163946875689647136083555186466737061429743316244275411759879001760913790858921411931029447711153370775689324401832345149832250468126992015582446511912921339318474186536069012120243616998699377819995587288973298684431209274118662512540422546959972385331080573512607810094193762804724936812759190823811052045204073975106014302972056920579676,"P":155647651242660060791811365180387435459381415273226033701272892074481153409737034954398497412251694369632218685299853742203934741913359409339049034540345746612914099527575334967066483337239487070844048014006916039926480994576120650562323963797302291111167682906677353271769296184836925568915544694668270084443,"Q":173532737111094134266134376611962983753641850125751727091642333488668738573002820850133882703289638339068122905534489716238416882118507890489355003112080267259374346484724025930174400995365892491544154265218594631981400340823987129579177225052190298336122497882873541768698571486871573306020866364455073184679},"NTildei":21804179839966215617323166653114777428295301823312612511460276110963180372502253615762179811422690222839741870787440933544011706828437081613897677503274266414108115438963470133770853495318148988723041613621155070307023056262266363912124380120374363945554068111317281744946272187692857258945318772931935780109425203787273056384444130542270930026597960313499613262040509908102668310364746033555035823992911116922332067658341478269862042041289812342450194587233452541086394169037546301259733296477211152026029160348565211873488345369476052165173513646532741430358518202416220434381486375753675885832705711885830084830621,"H1i":5492054453535336535221261324374241008714967721430359597092507961514078535035009087198497780315242151182658614509887645981855412669412210819065929527745501045046510899734550703052079362762271610221376468576924976799441128877699869411101852559422979490620938824578080796051006243640006587864726402461005912380611209599146476351457442622769895925595447492144202022676331654979841085613772561969537129817222027997027040820170424619891373771003404254016964058400843383655741323802075215911697776147136824281954868677570086903336972488494072036843208069558661786685985815916454480195408012763077363803427345380025121170485,"H2i":1007921844692562326726068738758076534337419028099949343942979569439995346811973833981981012239340512152156829820899300642739833572973473340584013299957494827005145065575501488029191788635008836512282539755244796651792412592878855590775841744406774949199977342361926491442227477919187233534142323500652787600563974337625238215434839172461441770464810641532355234608473389688777787697425032787411676746059650127104684933133374673621802985356052815248882486204755136135531650540219474552829114014409200175736202603225504872272891373862560907011388798653096317084184693578476118724778100405389571674753111282167052167913,"Alpha":6173793023550802921919952319360446980767839085087925334425304709951016330496541373707692166962209138811103631725597897252953048638362130328428502596388918584704705532274949926406891584600605298301402300276101896595484497316364452797012923890972127639950915376441477658442868482845579836317742732868680864600762839905962264477113716212055500804075699103888855137998636481377174310391960693187800764362152540992707950053444165110326890166695682087544284288846964161307597790990600228565501842495901354125917364344265306564019699298157629849499492557108672188552614217720475401048403910907159476546476429016834387621483,"Beta":1794042263680498826877832138506096099944115337632775075430175920268134019941281315479933184844582508967106415494173813941447136157407980212843919769341291727858194348462740828400864829477011808983178417984299364211735590431432206479852318182690456647502508527769346596816443548686108146366605957122923334549511516931345903204478651460318415602674531171061090914726763298932066213503981288378751125036215904448002923475624400466472533210352109524884557256121403451760775591917825869796083690931455743151335082240701714652576347698675362146667919508233405661630752095164760058979593050336706903743030248057895677765653,"P":67881309084513464003043965730792752640014823864294390871991028294179285209801307515880215014425828153412817814753316194468319063119626625476732471695812934784080418397180293601972497028689460389703389740401745287720765644669979348558159468880422665041748034252240264541477749983112032516502290404299123170679,"Q":80302590411226510382414936178133854488585704800021743838347204366291659351915812140049600479360901526952322523014056490441729927264120780897327227223636758045991574812539055563835252660292002691146153222926808870297084236853256293071709585366567508981353452873841632003098660591463213258796347613161097923609} \ No newline at end of file diff --git a/e2e/fixtures/node2_pre_params_0.json b/e2e/fixtures/node2_pre_params_0.json new file mode 100644 index 0000000..5216f24 --- /dev/null +++ b/e2e/fixtures/node2_pre_params_0.json @@ -0,0 +1 @@ +{"PaillierSK":{"N":24065121155263364700559906635699806610370137894084962993989238937604723590285405564993153738708298182782867535996316777370515258862577445825884135678567401667608817428383317373093547663472865102957350488000477881933657941902153153095636663482763709108498745800446142271511742614762440002246377290683583459512077146986793418516059600467334525697178372746481032278489582558468433070472819930466713744586479556402433532898394038536993219154532813674440454946987555534305695730987713596311301536233372283578123554183117272798248708810014337592128613823986969052330059847478321178200526248153794401758493680848918334937417,"LambdaN":12032560577631682350279953317849903305185068947042481496994619468802361795142702782496576869354149091391433767998158388685257629431288722912942067839283700833804408714191658686546773831736432551478675244000238940966828970951076576547818331741381854554249372900223071135755871307381220001123188645341791729755881984679964113292920637471581515043002917571808249264035255768058402847144345724986650430985317815625852909219927754109483343086528355450105150701130963042843803282757589756871709311873565027610439705141216036821865308248359431170760871272471357121133337195195857573406561829196576327358374761028639215869378,"PhiN":24065121155263364700559906635699806610370137894084962993989238937604723590285405564993153738708298182782867535996316777370515258862577445825884135678567401667608817428383317373093547663472865102957350488000477881933657941902153153095636663482763709108498745800446142271511742614762440002246377290683583459511763969359928226585841274943163030086005835143616498528070511536116805694288691449973300861970635631251705818439855508218966686173056710900210301402261926085687606565515179513743418623747130055220879410282432073643730616496718862341521742544942714242266674390391715146813123658393152654716749522057278431738756,"P":135259600203670200144492448043077989977097133925000255527133660348683321998709776426311832872214894122761670449016930245366036514541373414801466060361469227959400145469906047447876384810216832460295359460987128914908323330904493283578810846401942895694264824975561315434147697496124951571802015710813298746819,"Q":177918026661521730073833076128417621195440468939533494891937362002944054185418704067101049743629031027966044009521600072660496466934729359428687484364160220658689020002628035120006527676025395896948784439698070239609768982390981967028060432642311914369120632111044715953254892264516795469942143080826604451843},"NTildei":20905245109116413257587376522856573087094335665258196478096842838302102189443326688925711816219368896814382936616172548093264884605897444816041913654696555118769466151089814909109258044694999804737125246355493934867576891114093438269710579107857101576633708437517454409818249705040152611918716315020861887933945570899984946032397867176339375529383685495947871857542403100442376781252034796313917391498742872981192855482119834320248099961918497070998431241261686386935508585604745599364061623879810910192382277573913543258748005200972400064985916721259167464114066370241813031951901375492896682244245975320229330960121,"H1i":4939948643169577303084711801508900875730159910753535663161000326296137720343920145926556861218872067574072232600282469009961939429879551987584967707119475467531196776107924511195287293590825091232982309495102788808093559309079225464341868239008534335843752937943030801477006605338487890053250601955611399935573868756591663002792412824232333596894748743848578586325421325941557740548741394101073901472090599294087903005070382847396486516879910006172156673263774810954072187612884416354541234029377889074940570378774064424328438477701635250370056709399744440620750434541997102178896108132472233567948952758873003613528,"H2i":6559230442404127167985414973839771058875382650861510750463071094578099858195744888270116870041543327257264980211123446989902900029109777886322773376784524659752322373280798454596519131110757880140293116906867463204974496877905215211870968388341320642780642076465547097712222912924333252518558550960039391925409893077509128747145005713842278813900906459850249412986507030361765140841393046465952856165473086956362311954470668670168070798340007886533246829389586635271239484338616732630030773010989576121949010186504050217683740428671008046302877332515153303464010372549147883621039009607391935164369209777545754356616,"Alpha":4245636611939326530188891617614592572781126052752836737672994271524456467796498013091216833166323128071892715809883987514277285062658685624767701616312903527594910359650292813336204929637902226118853821300750550310344441117369140638395232045637035698241950595332198897481605869446982178168823507120727466093482412368219242381070695298261986158682644897361417176592924337204857245873099659681854674827812897745937737918927707693195529825919651572134829288812448756787298549157219755262576712046164332680377616594150224521128182254710900810880230124265083543728030976347336417178253432069554621290137915412491561123134,"Beta":3374740179755360574325279310615118943433622433149135778081075063919830279187403134779671089342578193106464504052557498716660661973835548882792594179250140850696999593412022211785519650205857956565482451226114964457546917223191337274642485484442160604021338357564847305957839161519623515423948694506485023629798318460811431291838416005570456063151640055096613930331703677204674082176354739034306734361878089239669079898109022375051773835538259207000522618377221616536331981265190345472739250431774349632488646014302197719155758813265554869839653400074474746558297008554756731781519328839480116595179323589179371586847,"P":77507249265120932555810932814126825550883175330185930611735546883987616406484383287200172513569252891993126575563686362964179862223391477179205308729566412558232568864844848062477441840789538212976289158326539126648007404677035085561505054032022112091225694632370038460014408076617687028738212023748531664423,"Q":67429967220253263314190608216523846395778203514790833105518971799374146396928568723286477054734324200202641598111323519322802943108259099850383851553471618192884008202872993085655512933453488504952630577189826203085318183206780796769147190017412669576783364781795471052936805568377361685295926267865759052571} \ No newline at end of file diff --git a/e2e/fixtures/node2_pre_params_1.json b/e2e/fixtures/node2_pre_params_1.json new file mode 100644 index 0000000..b5fa5ad --- /dev/null +++ b/e2e/fixtures/node2_pre_params_1.json @@ -0,0 +1 @@ +{"PaillierSK":{"N":27613157758950303233648871381480443272905727618066441320189830564257301172657089299042523075646887760077350824738431513150640564145773392277886092710931959744027629750523593150104708044172088502855220812778144927895570491982557362746162522301198667591984919677357808268016362676388053439457063731006917342681881222067633068013567413510664515334206644513497217772562661127920359681745123621080191018433734531656132856966924868962057698589161988766374565278974747741728758471202540804596839736367469531632470448560329113962491135700121102995512722063111582550556207559067637833276670770782612017807193044575846073112373,"LambdaN":13806578879475151616824435690740221636452863809033220660094915282128650586328544649521261537823443880038675412369215756575320282072886696138943046355465979872013814875261796575052354022086044251427610406389072463947785245991278681373081261150599333795992459838678904134008181338194026719728531865503458671340774040844732148786432706216823081677049664339378462349715348859500293599173160303678806405689949266672103496585688771953550031451853061659243455923265546803863173564596974202495904984790429515849209003502888397242571431810121011746227489572761152166426493365964973402552522659912712339089672702139989894278614,"PhiN":27613157758950303233648871381480443272905727618066441320189830564257301172657089299042523075646887760077350824738431513150640564145773392277886092710931959744027629750523593150104708044172088502855220812778144927895570491982557362746162522301198667591984919677357808268016362676388053439457063731006917342681548081689464297572865412433646163354099328678756924699430697719000587198346320607357612811379898533344206993171377543907100062903706123318486911846531093607726347129193948404991809969580859031698418007005776794485142863620242023492454979145522304332852986731929946805105045319825424678179345404279979788557228,"P":178079756090034997566150601355853418066244763969213405441805687471805269654588182376828016811144670177944875514550256140483508228165071753983577933785202312786339225692355505707061238582571385174231346854107174194796952474827092742499474237951203018064987863771050382135892058768462052198391491122464684047439,"Q":155060622078735443135850475662498562041071070771079667690157721447967213744214831345750190242691328133980988280997068914474127457290793693904075498658451821216072116316236893897968528204039114759821094700445145282551319605051986760558268679638075199638232963366640646035733392188725287429456149173401600507707},"NTildei":24424899015855591631362566630897843387246705827981363500130970384550922426808263116115834280193416174184613893252243856818560404301363329073090220279425719342771141145577255970637736208064308578798026216615128029975118744981129965564777341511307694619899369126096519273698973991032691180996963875050629340218122548258867120419243351095623962523914481675092085405667633757985691064594787432081173697637152104447319816702844243932427195019029413483563132631572472496735781913974185305237464644239853921862382550388065250071948247282061775592371623750635302238990417914644277077191578603004003067739328914718229096136281,"H1i":13143565323338754287809884681306419149665453288081781113876582997796346431267221668636855772763139440503597526256783221747824096704654085668058506841168222302231263967448252328514966175875367985704410797708461344902695231412091675962471477979561627357758407573979894773078274426759689823471420263358549972311958992900429003361615169633999891240374693127823749877635305142920433581264256875871629243266164034402804907345310574072426079476093119968197019987829077622437559288816488828025005141079955274936337019264511182590014896188527693015148783417697452397739986330966936886044713601676428510366725082678926285357982,"H2i":5169107117554478291884042467450302178776853628358238136251923325825260710709582505475447835678395958255919050475411076589049098264635578378074387690595574872790547983772860121690138581669297699488598630477331864531312080805149698535242017483942058476937330467624413660015766784890711085389227864533545687979018002220356380534535253253771993912434548605406181217146127469452194398733188825347145972235357356391774710437028085203288801282699102240133704255716041119635411247544380696767795189714518601348083864082923548761543526524145232341794558853301047229439915413419949829600635690750659628609137098238995907005337,"Alpha":9656049212010896990557023350016790031377598690077007499224604720136309809901674396160176079563195719988858277097958138959524989351909276698153670750966299947132859625738537806917907921271349300690035249183313856651034858530920717661323430167133218755223623355778650442491536585264882670619314523416159056274468482963568035245731419719502254326700504397042327008084448279478622389310285715202160044366784658124385558732151321427065068905045886810744988884385651173258979370227015979375667336443417476490583967022782559867444839786706838904003043745691018774867487658852353610448698668937375123125579996163905793836257,"Beta":6001765388745521586732881389107782385181601453513087851340316140686271504983358420418612772262050468991101795026742116783856459684444750720589384496972260097053308833077366367596411803881977029159490771224062918852298905152380878878025295317873158140401352410906990802757787510722424777518720173789342357692926017695054181720698442472003665304161365389099042172415762289338965174281995201289249669486984251336731981690586085907839750780769235152336408285588131858855368718303557973370952735142348143227229370491146472609010666525905059558038945441384813960219383234283848326232270029393822879958876734051060917380403,"P":72596485698620344366743337059112948310056512563819753559025717992286459210229986493389466078532835054845242821720811729138585813472409229303165490856188795463369591079314472722662275253571200341764210467804298664522454819100479350754753449146827213437376060906644783426872116535422238637406110622064415086259,"Q":84111850528323071377622966728739473334233133715355880051305570072541610492359414649406582594948545103375334028388010257884307869186368813996908104105157295937347436272036741316243779225888595675352396331714474611065637038218641203082632105251133143627440642885259227330518639961741377015826631965293598797599} \ No newline at end of file diff --git a/e2e/go.mod b/e2e/go.mod index ebeda78..ac74a6d 100644 --- a/e2e/go.mod +++ b/e2e/go.mod @@ -3,6 +3,7 @@ module github.com/fystack/mpcium/e2e go 1.25.5 require ( + github.com/bnb-chain/tss-lib/v2 v2.0.2 github.com/dgraph-io/badger/v4 v4.9.0 github.com/fystack/mpcium v0.0.0-00010101000000-000000000000 github.com/google/uuid v1.6.0 @@ -33,7 +34,6 @@ require ( github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.13 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.41.6 // indirect github.com/aws/smithy-go v1.24.0 // indirect - github.com/bnb-chain/tss-lib/v2 v2.0.2 // indirect github.com/btcsuite/btcd v0.25.0 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.6 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect @@ -104,4 +104,4 @@ replace github.com/fystack/mpcium => ../ replace github.com/agl/ed25519 => github.com/binance-chain/edwards25519 v0.0.0-20200305024217-f36fc4b53d43 -replace github.com/bnb-chain/tss-lib/v2 => github.com/fystack/tss-lib/v2 v2.0.1 +replace github.com/bnb-chain/tss-lib/v2 => github.com/fystack/tss-lib/v2 v2.0.3 diff --git a/e2e/go.sum b/e2e/go.sum index 59cfec5..a9fb670 100644 --- a/e2e/go.sum +++ b/e2e/go.sum @@ -13,8 +13,6 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/antithesishq/antithesis-sdk-go v0.6.0-default-no-op h1:kpBdlEPbRvff0mDD1gk7o9BhI16b9p5yYAXRlidpqJE= -github.com/antithesishq/antithesis-sdk-go v0.6.0-default-no-op/go.mod h1:IUpT2DPAKh6i/YhSbt6Gl3v2yvUZjmKncl7U91fup7E= github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHSxpiH9JdtuBj0= @@ -120,8 +118,8 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= -github.com/fystack/tss-lib/v2 v2.0.1 h1:xnC2+DYShoVWco1geliW0km9IvGD7T2FqFOeXM3/7K0= -github.com/fystack/tss-lib/v2 v2.0.1/go.mod h1:s4LRfEqj89DhfNb+oraW0dURt5LtOHWXb9Gtkghn0L8= +github.com/fystack/tss-lib/v2 v2.0.3 h1:A0HGL5GDPpKbNW+0ZXgv1Ri3+ks88AvxTS7OK40gnUY= +github.com/fystack/tss-lib/v2 v2.0.3/go.mod h1:s4LRfEqj89DhfNb+oraW0dURt5LtOHWXb9Gtkghn0L8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= @@ -163,8 +161,6 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo= -github.com/google/go-tpm v0.9.8/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= @@ -253,8 +249,6 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE= github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY= -github.com/minio/highwayhash v1.0.4-0.20251030100505-070ab1a87a76 h1:KGuD/pM2JpL9FAYvBrnBBeENKZNh6eNtjqytV6TYjnk= -github.com/minio/highwayhash v1.0.4-0.20251030100505-070ab1a87a76/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -263,10 +257,6 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/nats-io/jwt/v2 v2.8.0 h1:K7uzyz50+yGZDO5o772eRE7atlcSEENpL7P+b74JV1g= -github.com/nats-io/jwt/v2 v2.8.0/go.mod h1:me11pOkwObtcBNR8AiMrUbtVOUGkqYjMQZ6jnSdVUIA= -github.com/nats-io/nats-server/v2 v2.12.5 h1:EOHLbsLJgUHUwzkj9gBTOlubkX+dmSs0EYWMdBiHivU= -github.com/nats-io/nats-server/v2 v2.12.5/go.mod h1:JQDAKcwdXs0NRhvYO31dzsXkzCyDkOBS7SKU3Nozu14= github.com/nats-io/nats.go v1.49.0 h1:yh/WvY59gXqYpgl33ZI+XoVPKyut/IcEaqtsiuTJpoE= github.com/nats-io/nats.go v1.49.0/go.mod h1:fDCn3mN5cY8HooHwE2ukiLb4p4G4ImmzvXyJt+tGwdw= github.com/nats-io/nkeys v0.4.15 h1:JACV5jRVO9V856KOapQ7x+EY8Jo3qw1vJt/9Jpwzkk4= @@ -496,8 +486,6 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= -golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= -golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= diff --git a/e2e/keygen_test.go b/e2e/keygen_test.go index 42085ce..e459916 100644 --- a/e2e/keygen_test.go +++ b/e2e/keygen_test.go @@ -43,6 +43,8 @@ func TestKeyGeneration(t *testing.T) { suite.RegisterPeers(t) t.Log("registerPeers completed") + suite.SeedPreParams(t) + t.Log("Starting startNodes...") suite.StartNodes(t) t.Log("startNodes completed") diff --git a/e2e/reshare_test.go b/e2e/reshare_test.go index f865e5d..e70d2be 100644 --- a/e2e/reshare_test.go +++ b/e2e/reshare_test.go @@ -37,6 +37,7 @@ func TestResharing(t *testing.T) { suite.SetupInfrastructure(t) suite.SetupTestNodes(t) suite.RegisterPeers(t) + suite.SeedPreParams(t) suite.StartNodes(t) suite.SetupMPCClient(t) suite.LoadConfig() diff --git a/e2e/sign_ckd_test.go b/e2e/sign_ckd_test.go index 63a9444..8ecd7b4 100644 --- a/e2e/sign_ckd_test.go +++ b/e2e/sign_ckd_test.go @@ -55,6 +55,8 @@ func TestCKDSigning(t *testing.T) { suite.SetupMPCClient(t) t.Log("setupMPCClient completed") + suite.SeedPreParams(t) + t.Log("Starting startNodes...") suite.StartNodes(t) t.Log("startNodes completed") diff --git a/e2e/sign_test.go b/e2e/sign_test.go index fe197c9..dc106b7 100644 --- a/e2e/sign_test.go +++ b/e2e/sign_test.go @@ -95,6 +95,8 @@ func TestSigning(t *testing.T) { suite.SetupMPCClient(t) t.Log("setupMPCClient completed") + suite.SeedPreParams(t) + t.Log("Starting startNodes...") suite.StartNodes(t) t.Log("startNodes completed") From 7fd26b9ca1108886ef53d2f732d5fbf772110656 Mon Sep 17 00:00:00 2001 From: anhthii Date: Thu, 19 Mar 2026 00:05:30 +0700 Subject: [PATCH 09/11] Go mod tidy --- go.mod | 10 ++-------- go.sum | 17 ++--------------- 2 files changed, 4 insertions(+), 23 deletions(-) diff --git a/go.mod b/go.mod index 874726c..2d6dd8f 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/fystack/mpcium -go 1.25.5 +go 1.25.8 require ( filippo.io/age v1.3.1 @@ -17,8 +17,7 @@ require ( github.com/google/uuid v1.6.0 github.com/hashicorp/consul/api v1.33.2 github.com/mitchellh/mapstructure v1.5.0 - github.com/nats-io/nats-server/v2 v2.12.5 - github.com/nats-io/nats.go v1.49.0 + github.com/nats-io/nats.go v1.48.0 github.com/rs/zerolog v1.34.0 github.com/samber/lo v1.52.0 github.com/spf13/viper v1.21.0 @@ -31,7 +30,6 @@ require ( require ( filippo.io/hpke v0.4.0 // indirect github.com/agl/ed25519 v0.0.0-20200225211852-fd4d107ace12 // indirect - github.com/antithesishq/antithesis-sdk-go v0.6.0-default-no-op // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/aws/aws-sdk-go-v2 v1.41.1 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17 // indirect @@ -59,7 +57,6 @@ require ( github.com/go-viper/mapstructure/v2 v2.5.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/google/flatbuffers v25.12.19+incompatible // indirect - github.com/google/go-tpm v0.9.8 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-hclog v1.6.3 // indirect @@ -75,9 +72,7 @@ require ( github.com/klauspost/compress v1.18.4 // indirect github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/minio/highwayhash v1.0.4-0.20251030100505-070ab1a87a76 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/nats-io/jwt/v2 v2.8.0 // indirect github.com/nats-io/nkeys v0.4.15 // indirect github.com/nats-io/nuid v1.0.1 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect @@ -102,7 +97,6 @@ require ( golang.org/x/net v0.49.0 // indirect golang.org/x/sys v0.42.0 // indirect golang.org/x/text v0.34.0 // indirect - golang.org/x/time v0.15.0 // indirect google.golang.org/protobuf v1.36.11 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index aebe6da..91c05d3 100644 --- a/go.sum +++ b/go.sum @@ -13,8 +13,6 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/antithesishq/antithesis-sdk-go v0.6.0-default-no-op h1:kpBdlEPbRvff0mDD1gk7o9BhI16b9p5yYAXRlidpqJE= -github.com/antithesishq/antithesis-sdk-go v0.6.0-default-no-op/go.mod h1:IUpT2DPAKh6i/YhSbt6Gl3v2yvUZjmKncl7U91fup7E= github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHSxpiH9JdtuBj0= @@ -163,8 +161,6 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo= -github.com/google/go-tpm v0.9.8/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= @@ -253,8 +249,6 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE= github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY= -github.com/minio/highwayhash v1.0.4-0.20251030100505-070ab1a87a76 h1:KGuD/pM2JpL9FAYvBrnBBeENKZNh6eNtjqytV6TYjnk= -github.com/minio/highwayhash v1.0.4-0.20251030100505-070ab1a87a76/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -265,12 +259,8 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/nats-io/jwt/v2 v2.8.0 h1:K7uzyz50+yGZDO5o772eRE7atlcSEENpL7P+b74JV1g= -github.com/nats-io/jwt/v2 v2.8.0/go.mod h1:me11pOkwObtcBNR8AiMrUbtVOUGkqYjMQZ6jnSdVUIA= -github.com/nats-io/nats-server/v2 v2.12.5 h1:EOHLbsLJgUHUwzkj9gBTOlubkX+dmSs0EYWMdBiHivU= -github.com/nats-io/nats-server/v2 v2.12.5/go.mod h1:JQDAKcwdXs0NRhvYO31dzsXkzCyDkOBS7SKU3Nozu14= -github.com/nats-io/nats.go v1.49.0 h1:yh/WvY59gXqYpgl33ZI+XoVPKyut/IcEaqtsiuTJpoE= -github.com/nats-io/nats.go v1.49.0/go.mod h1:fDCn3mN5cY8HooHwE2ukiLb4p4G4ImmzvXyJt+tGwdw= +github.com/nats-io/nats.go v1.48.0 h1:pSFyXApG+yWU/TgbKCjmm5K4wrHu86231/w84qRVR+U= +github.com/nats-io/nats.go v1.48.0/go.mod h1:iRWIPokVIFbVijxuMQq4y9ttaBTMe0SFdlZfMDd+33g= github.com/nats-io/nkeys v0.4.15 h1:JACV5jRVO9V856KOapQ7x+EY8Jo3qw1vJt/9Jpwzkk4= github.com/nats-io/nkeys v0.4.15/go.mod h1:CpMchTXC9fxA5zrMo4KpySxNjiDVvr8ANOSZdiNfUrs= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= @@ -482,7 +472,6 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -501,8 +490,6 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= -golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U= -golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= From 83884a75640ff2d02887a1aa0efe32aea364552f Mon Sep 17 00:00:00 2001 From: anhthii Date: Thu, 19 Mar 2026 00:12:34 +0700 Subject: [PATCH 10/11] Bump go version --- .github/workflows/ci.yml | 2 +- .github/workflows/e2e-tests.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 21a72fb..ae3030d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ on: branches: ["*"] env: - GO_VERSION: "1.25.5" + GO_VERSION: "1.25.8" jobs: test: diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index e35378d..dfe7c70 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -7,7 +7,7 @@ on: branches: [master] env: - GO_VERSION: "1.24" + GO_VERSION: "1.25.8" CGO_ENABLED: 0 DOCKER_BUILDKIT: 1 GO_BUILD_FLAGS: -trimpath -ldflags="-s -w" From 349ed99e1aeb37210941f4264d90d30f6c4625be Mon Sep 17 00:00:00 2001 From: vietddude Date: Mon, 16 Mar 2026 17:00:55 +0700 Subject: [PATCH 11/11] Enhance messaging reliability and error handling --- pkg/messaging/point2point.go | 7 ++++--- pkg/mpc/session.go | 12 ++++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/pkg/messaging/point2point.go b/pkg/messaging/point2point.go index 225f090..ca65d51 100644 --- a/pkg/messaging/point2point.go +++ b/pkg/messaging/point2point.go @@ -64,9 +64,10 @@ func (d *natsDirectMessaging) SendToOther(topic string, message []byte) error { } return nil }, - retry.Attempts(3), - retry.Delay(50*time.Millisecond), - retry.DelayType(retry.FixedDelay), + retry.Attempts(10), + retry.Delay(100*time.Millisecond), + retry.MaxDelay(1*time.Second), + retry.DelayType(retry.BackOffDelay), retry.OnRetry(func(n uint, err error) { logger.Error("Failed to send direct message", err, "attempt", n+1, "topic", topic) }), diff --git a/pkg/mpc/session.go b/pkg/mpc/session.go index dc5651f..c75e05b 100644 --- a/pkg/mpc/session.go +++ b/pkg/mpc/session.go @@ -3,6 +3,7 @@ package mpc import ( "encoding/json" "fmt" + "runtime/debug" "strings" "sync" "time" @@ -252,6 +253,17 @@ func (s *session) receiveBroadcastTssMessage(rawMsg []byte) { // update: the logic of receiving message should be modified func (s *session) receiveTssMessage(msg *types.TssMessage) { + defer func() { + if r := recover(); r != nil { + logger.Error("Panic recovered in receiveTssMessage", + fmt.Errorf("%v", r), + "walletID", s.walletID, + "stack", string(debug.Stack()), + ) + s.ErrCh <- fmt.Errorf("panic in receiveTssMessage: %v", r) + } + }() + toIDs := make([]string, len(msg.To)) for i, id := range msg.To { toIDs[i] = id.String()