@@ -439,3 +439,79 @@ func (mr *memsetRandReader) Read(buf []byte) (n int, err error) {
439439 }
440440 return len (buf ), nil
441441}
442+
443+ // TestSigningWithAggregatedNonce tests the aggregated nonce signing flow where
444+ // a coordinator aggregates nonces and distributes the combined nonce to
445+ // participants, rather than each participant aggregating nonces themselves.
446+ func TestSigningWithAggregatedNonce (t * testing.T ) {
447+ const numSigners = 5
448+
449+ // Generate signers.
450+ signerKeys := make ([]* btcec.PrivateKey , numSigners )
451+ signSet := make ([]* btcec.PublicKey , numSigners )
452+ for i := 0 ; i < numSigners ; i ++ {
453+ privKey , err := btcec .NewPrivateKey ()
454+ if err != nil {
455+ t .Fatalf ("unable to gen priv key: %v" , err )
456+ }
457+ signerKeys [i ] = privKey
458+ signSet [i ] = privKey .PubKey ()
459+ }
460+
461+ // Each signer creates a context and session.
462+ sessions := make ([]* Session , numSigners )
463+ for i , signerKey := range signerKeys {
464+ signCtx , err := NewContext (
465+ signerKey , false , WithKnownSigners (signSet ),
466+ )
467+ if err != nil {
468+ t .Fatalf ("unable to generate context: %v" , err )
469+ }
470+
471+ session , err := signCtx .NewSession ()
472+ if err != nil {
473+ t .Fatalf ("unable to generate new session: %v" , err )
474+ }
475+ sessions [i ] = session
476+ }
477+
478+ // Phase 1: Coordinator collects all public nonces.
479+ pubNonces := make ([][PubNonceSize ]byte , numSigners )
480+ for i , session := range sessions {
481+ pubNonces [i ] = session .PublicNonce ()
482+ }
483+
484+ // Phase 2: Coordinator aggregates nonces.
485+ combinedNonce , err := AggregateNonces (pubNonces )
486+ if err != nil {
487+ t .Fatalf ("unable to aggregate nonces: %v" , err )
488+ }
489+
490+ // Phase 3: Coordinator distributes combined nonce to all participants.
491+ // Participants sign using the external combined nonce.
492+ msg := sha256 .Sum256 ([]byte ("coordinator-based signing" ))
493+
494+ partialSigs := make ([]* PartialSignature , numSigners )
495+ for i , session := range sessions {
496+ // Participants use WithExternalCombinedNonce instead of
497+ // RegisterPubNonce.
498+ sig , err := session .Sign (msg , WithExternalCombinedNonce (combinedNonce ))
499+ if err != nil {
500+ t .Fatalf ("signer %d unable to sign: %v" , i , err )
501+ }
502+ partialSigs [i ] = sig
503+ }
504+
505+ // Phase 4: Combine all partial signatures (can be done by any party).
506+ finalSig := CombineSigs (partialSigs [0 ].R , partialSigs )
507+
508+ // Verify the final signature.
509+ combinedKey , _ , _ , err := AggregateKeys (signSet , false )
510+ if err != nil {
511+ t .Fatalf ("unable to aggregate keys: %v" , err )
512+ }
513+
514+ if ! finalSig .Verify (msg [:], combinedKey .FinalKey ) {
515+ t .Fatalf ("final signature is invalid" )
516+ }
517+ }
0 commit comments