diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 21a72fbe..ae3030d1 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 e35378d2..dfe7c70d 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" diff --git a/cmd/mpcium/main.go b/cmd/mpcium/main.go index ad801ef8..418caae4 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" @@ -188,15 +189,28 @@ 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.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.WithMaxAckPending(maxConcurrentSigning), + ) if err != nil { logger.Fatal("Failed to create signing jetstream broker", err) } @@ -582,8 +596,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()) diff --git a/config.yaml.template b/config.yaml.template index 1f9ad811..83243b7f 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/e2e/base_test.go b/e2e/base_test.go index 5c209c4f..1ad62347 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 00000000..9b676d2a --- /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 00000000..07139e5d --- /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 00000000..c7c5006f --- /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 00000000..b5bf6285 --- /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 00000000..cdd169af --- /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 00000000..5216f247 --- /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 00000000..b5fa5adb --- /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 106d1f53..ac74a6d1 100644 --- a/e2e/go.mod +++ b/e2e/go.mod @@ -3,11 +3,12 @@ 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 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 ) @@ -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 @@ -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 ) @@ -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 1f40ea0f..a9fb6705 100644 --- a/e2e/go.sum +++ b/e2e/go.sum @@ -118,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= @@ -223,8 +223,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= @@ -257,10 +257,10 @@ 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/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 +391,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 +468,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 +484,8 @@ 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/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 42085cea..e4599161 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 f865e5d6..e70d2be0 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 63a94446..8ecd7b41 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 fe197c9e..dc106b7a 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") diff --git a/go.mod b/go.mod index e7c90f1d..2d6dd8fe 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 @@ -23,8 +23,8 @@ require ( 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 ( @@ -69,11 +69,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 @@ -95,8 +95,8 @@ 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 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 65fd95a0..91c05d3d 100644 --- a/go.sum +++ b/go.sum @@ -223,8 +223,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= @@ -261,8 +261,8 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW 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/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 +395,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 +472,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= @@ -488,8 +488,8 @@ 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/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/pkg/client/client.go b/pkg/client/client.go index 2ed4dc41..6c64c140 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -222,7 +222,6 @@ 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 { logger.Info("Received reshare success message", "raw", string(msg)) var event event.ResharingResultEvent diff --git a/pkg/event/sign.go b/pkg/event/sign.go index ebbd0775..25449e5f 100644 --- a/pkg/event/sign.go +++ b/pkg/event/sign.go @@ -1,8 +1,8 @@ package event const ( - SigningPublisherStream = "mpc-signing" - SigningConsumerStream = "mpc-signing-consumer" + SigningPublisherStream = "mpc-signing" + SigningConsumerStream = "mpc-signing-consumer" SigningRequestTopic = "mpc.signing_request.*" SigningResultTopic = "mpc.mpc_signing_result.*" SigningResultCompleteTopic = "mpc.mpc_signing_result.complete" diff --git a/pkg/eventconsumer/event_consumer.go b/pkg/eventconsumer/event_consumer.go index 087ac67c..9e2ecb30 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() @@ -173,6 +157,17 @@ func (ec *eventConsumer) handleKeyGenEvent(natMsg *nats.Msg) { } 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(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) @@ -224,8 +219,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(walletID, barrierErr, "Peers not ready before keygen", natMsg) + return + } go ecdsaSession.GenerateKey(doneEcdsa) go eddsaSession.GenerateKey(doneEddsa) @@ -377,8 +389,8 @@ func (ec *eventConsumer) handleSigningEvent(natMsg *nats.Msg) { 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( msg.WalletID, @@ -465,9 +477,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 { @@ -484,6 +493,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 +504,20 @@ 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( + msg.WalletID, + msg.TxID, + msg.NetworkInternalCode, + err, + "Peers not ready before signing", + natMsg, + ) + return + } onSuccess := func(data []byte) { done() @@ -688,14 +707,35 @@ 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(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(): @@ -707,15 +747,13 @@ func (ec *eventConsumer) consumeReshareEvent() error { 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(): @@ -728,7 +766,7 @@ func (ec *eventConsumer) consumeReshareEvent() error { return } } - }() + }) } wg.Wait() @@ -842,30 +880,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 8af027d0..e2f07146 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() } diff --git a/pkg/eventconsumer/sign_consumer.go b/pkg/eventconsumer/sign_consumer.go index e0ea23e2..b202a337 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() } diff --git a/pkg/messaging/jetstream_broker.go b/pkg/messaging/jetstream_broker.go index cf738a1d..8f8a6069 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 ) @@ -58,6 +59,8 @@ type brokerConfiguration struct { consumerNamePrefix string deliverPolicy jetstream.DeliverPolicy backoffDurations []time.Duration + maxAckPending int + maxBytes int64 } func WithStreamDescription(description string) BrokerOption { @@ -120,6 +123,25 @@ 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 WithMaxBytes(maxBytes int64) BrokerOption { + return func(cfg *brokerConfiguration) { + cfg.maxBytes = maxBytes + } +} + +func WithMaxAckPending(maxAckPending int) BrokerOption { + return func(cfg *brokerConfiguration) { + cfg.maxAckPending = maxAckPending + } +} + type jetStreamBroker struct { config brokerConfiguration js jetstream.JetStream @@ -140,6 +162,7 @@ func NewJetStreamBroker( retention: nats.InterestPolicy, storage: nats.FileStorage, maxAge: DefaultStreamMaxAge, + maxBytes: DefaultStreamMaxBytes, discard: nats.DiscardOld, ackWait: DefaultAckWait, maxDeliveryAttempts: DefaultMaxDeliveryAttempts, @@ -177,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) @@ -221,6 +245,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 +334,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 32ed3f92..6eec56eb 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, }) diff --git a/pkg/messaging/point2point.go b/pkg/messaging/point2point.go index 225f0901..ca65d513 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/ecdsa_keygen_session.go b/pkg/mpc/ecdsa_keygen_session.go index dcaa945e..b55e56b9 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 39ea715b..29f30e69 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 4d5e0d58..9664e088 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 @@ -70,7 +77,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, @@ -166,12 +174,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 +195,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,7 +211,7 @@ 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 } @@ -208,7 +219,7 @@ func (s *ecdsaSigningSession) Sign(onSuccess func(data []byte)) { 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 485f0523..deba0cc6 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 d394c423..e5a892ec 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 4f859e5d..2c11fda4 100644 --- a/pkg/mpc/eddsa_signing_session.go +++ b/pkg/mpc/eddsa_signing_session.go @@ -60,8 +60,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{ @@ -155,13 +155,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 +176,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,7 +190,7 @@ 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 } @@ -196,7 +198,7 @@ func (s *eddsaSigningSession) Sign(onSuccess func(data []byte)) { 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 +212,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/registry.go b/pkg/mpc/registry.go index 9c4868aa..21afe422 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) } } } diff --git a/pkg/mpc/session.go b/pkg/mpc/session.go index b1a76b57..c75e05b6 100644 --- a/pkg/mpc/session.go +++ b/pkg/mpc/session.go @@ -3,8 +3,10 @@ package mpc import ( "encoding/json" "fmt" + "runtime/debug" "strings" "sync" + "time" "github.com/bnb-chain/tss-lib/v2/ecdsa/keygen" "github.com/bnb-chain/tss-lib/v2/tss" @@ -27,6 +29,12 @@ const ( 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 +76,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 +90,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 +133,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 +157,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 +188,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 +209,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 +221,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 +238,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 } @@ -218,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() @@ -225,7 +271,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 +325,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 +337,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 +356,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 +446,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