public void Process(MusigPubNonce combinedNonce) { if (processed_nonce) { throw new InvalidOperationException($"Nonce already processed"); } var combined_pk = this.SigningPubKey; MusigSessionCache session_cache = new MusigSessionCache(); Span <byte> noncehash = stackalloc byte[32]; Span <byte> sig_template_data = stackalloc byte[32]; Span <byte> combined_pk32 = stackalloc byte[32]; Span <GEJ> summed_nonces = stackalloc GEJ[2]; summed_nonces[0] = combinedNonce.K1.Q.ToGroupElementJacobian(); summed_nonces[1] = combinedNonce.K2.Q.ToGroupElementJacobian(); combined_pk.WriteToSpan(combined_pk32); /* Add public adaptor to nonce */ if (adaptor != null) { summed_nonces[0] = summed_nonces[0].AddVariable(adaptor.Q); } var combined_nonce = secp256k1_musig_process_nonces_internal( this.ctx.EcMultContext, noncehash, summed_nonces, combined_pk32, msg32); session_cache.B = new Scalar(noncehash); ECXOnlyPubKey.secp256k1_xonly_ge_serialize(sig_template_data, ref combined_nonce); var rx = combined_nonce.x; /* Negate nonce if Y coordinate is not square */ combined_nonce = combined_nonce.NormalizeYVariable(); /* Store nonce parity in session cache */ session_cache.CombinedNonceParity = combined_nonce.y.IsOdd; /* Compute messagehash and store in session cache */ ECXOnlyPubKey.secp256k1_musig_compute_messagehash(noncehash, sig_template_data, combined_pk32, msg32); session_cache.E = new Scalar(noncehash); /* If there is a tweak then set `msghash` times `tweak` to the `s`-part of the sig template.*/ Scalar s = Scalar.Zero; if (is_tweaked) { Scalar e = session_cache.E; if (!ECPrivKey.secp256k1_eckey_privkey_tweak_mul(ref e, scalar_tweak)) { throw new InvalidOperationException("Impossible to sign (secp256k1_eckey_privkey_tweak_mul is false)"); } if (pk_parity) { e = e.Negate(); } s = s.Add(e); } SessionCache = session_cache; Template = new SecpSchnorrSignature(rx, s); processed_nonce = true; this.combinedNonce = combinedNonce; }