@@ -302,3 +302,70 @@ func (m *MusigSessionManager) MuSig2RegisterNonces(sessionID MuSig2SessionID,
302302
303303 return session .HaveAllNonces , nil
304304}
305+
306+ // MuSig2RegisterCombinedNonce registers a pre-aggregated combined nonce for a
307+ // session identified by its ID. This is an alternative to MuSig2RegisterNonces
308+ // and is used when a coordinator has already aggregated all individual nonces
309+ // and wants to distribute the combined nonce to participants.
310+ //
311+ // NOTE: This method is mutually exclusive with MuSig2RegisterNonces for the
312+ // same session. Once this method is called, MuSig2RegisterNonces will return
313+ // an error if called later for the same session.
314+ func (m * MusigSessionManager ) MuSig2RegisterCombinedNonce (
315+ sessionID MuSig2SessionID ,
316+ combinedNonce [musig2 .PubNonceSize ]byte ) error {
317+
318+ // Hold the lock during the whole operation.
319+ m .sessionMtx .Lock (sessionID )
320+ defer m .sessionMtx .Unlock (sessionID )
321+
322+ // Load the session.
323+ session , ok := m .musig2Sessions .Load (sessionID )
324+ if ! ok {
325+ return fmt .Errorf ("session with ID %x not found" , sessionID [:])
326+ }
327+
328+ // Check if we already have all nonces.
329+ if session .HaveAllNonces {
330+ return fmt .Errorf ("already have all nonces" )
331+ }
332+
333+ // Delegate to the version-specific implementation.
334+ err := session .session .RegisterCombinedNonce (combinedNonce )
335+ if err != nil {
336+ return fmt .Errorf ("error registering combined nonce: %w" , err )
337+ }
338+
339+ // Mark that we have all nonces now.
340+ session .HaveAllNonces = true
341+
342+ return nil
343+ }
344+
345+ // MuSig2GetCombinedNonce retrieves the combined nonce for a session identified
346+ // by its ID. This will be available after either all individual nonces have
347+ // been registered via MuSig2RegisterNonces, or a combined nonce has been
348+ // registered via MuSig2RegisterCombinedNonce.
349+ func (m * MusigSessionManager ) MuSig2GetCombinedNonce (
350+ sessionID MuSig2SessionID ) ([musig2 .PubNonceSize ]byte , error ) {
351+
352+ // Hold the lock during the operation.
353+ m .sessionMtx .Lock (sessionID )
354+ defer m .sessionMtx .Unlock (sessionID )
355+
356+ // Load the session.
357+ session , ok := m .musig2Sessions .Load (sessionID )
358+ if ! ok {
359+ return [musig2 .PubNonceSize ]byte {}, fmt .Errorf ("session with " +
360+ "ID %x not found" , sessionID [:])
361+ }
362+
363+ // Get the combined nonce from the session.
364+ combinedNonce , err := session .session .CombinedNonce ()
365+ if err != nil {
366+ return [musig2 .PubNonceSize ]byte {}, fmt .Errorf ("error getting " +
367+ "combined nonce: %w" , err )
368+ }
369+
370+ return combinedNonce , nil
371+ }
0 commit comments