@@ -265,6 +265,100 @@ static bool CreateSig(const BaseSignatureCreator& creator, SignatureData& sigdat
265265 return false ;
266266}
267267
268+ static bool SignMuSig2 (const BaseSignatureCreator& creator, SignatureData& sigdata, const SigningProvider& provider, std::vector<unsigned char >& sig_out, const XOnlyPubKey& script_pubkey, const uint256* merkle_root, const uint256* leaf_hash, SigVersion sigversion)
269+ {
270+ Assert (sigversion == SigVersion::TAPROOT || sigversion == SigVersion::TAPSCRIPT);
271+
272+ // Lookup derivation paths for the script pubkey
273+ KeyOriginInfo agg_info;
274+ auto misc_pk_it = sigdata.taproot_misc_pubkeys .find (script_pubkey);
275+ if (misc_pk_it != sigdata.taproot_misc_pubkeys .end ()) {
276+ agg_info = misc_pk_it->second .second ;
277+ }
278+
279+ for (const auto & [agg_pub, part_pks] : sigdata.musig2_pubkeys ) {
280+ if (part_pks.empty ()) continue ;
281+
282+ // Fill participant derivation path info
283+ for (const auto & part_pk : part_pks) {
284+ KeyOriginInfo part_info;
285+ if (provider.GetKeyOrigin (part_pk.GetID (), part_info)) {
286+ XOnlyPubKey xonly_part (part_pk);
287+ auto it = sigdata.taproot_misc_pubkeys .find (xonly_part);
288+ if (it == sigdata.taproot_misc_pubkeys .end ()) {
289+ it = sigdata.taproot_misc_pubkeys .emplace (xonly_part, std::make_pair (std::set<uint256>(), part_info)).first ;
290+ }
291+ if (leaf_hash) it->second .first .insert (*leaf_hash);
292+ }
293+ }
294+
295+ // The pubkey in the script may not be the actual aggregate of the participants, but derived from it.
296+ // Check the derivation, and compute the BIP 32 derivation tweaks
297+ std::vector<std::pair<uint256, bool >> tweaks;
298+ CPubKey plain_pub = agg_pub;
299+ if (XOnlyPubKey (agg_pub) != script_pubkey) {
300+ if (agg_info.path .empty ()) continue ;
301+ // Compute and compare fingerprint
302+ CKeyID keyid = agg_pub.GetID ();
303+ if (!std::equal (agg_info.fingerprint , agg_info.fingerprint + sizeof (agg_info.fingerprint ), keyid.data ())) {
304+ continue ;
305+ }
306+ // Get the BIP32 derivation tweaks
307+ CExtPubKey extpub = CreateMuSig2SyntheticXpub (agg_pub);
308+ for (const int i : agg_info.path ) {
309+ auto & [t, xonly] = tweaks.emplace_back ();
310+ xonly = false ;
311+ if (!extpub.Derive (extpub, i, &t)) {
312+ return false ;
313+ }
314+ }
315+ Assert (XOnlyPubKey (extpub.pubkey ) == script_pubkey);
316+ plain_pub = extpub.pubkey ;
317+ }
318+
319+ // Add the merkle root tweak
320+ if (sigversion == SigVersion::TAPROOT && merkle_root) {
321+ tweaks.emplace_back (script_pubkey.ComputeTapTweakHash (merkle_root->IsNull () ? nullptr : merkle_root), true );
322+ std::optional<std::pair<XOnlyPubKey, bool >> tweaked = script_pubkey.CreateTapTweak (merkle_root->IsNull () ? nullptr : merkle_root);
323+ if (!Assume (tweaked)) return false ;
324+ plain_pub = tweaked->first .GetCPubKeys ().at (tweaked->second ? 1 : 0 );
325+ }
326+
327+ // First try to aggregate
328+ if (creator.CreateMuSig2AggregateSig (part_pks, sig_out, agg_pub, plain_pub, leaf_hash, tweaks, sigversion, sigdata)) {
329+ if (sigversion == SigVersion::TAPROOT) {
330+ sigdata.taproot_key_path_sig = sig_out;
331+ } else {
332+ auto lookup_key = std::make_pair (script_pubkey, leaf_hash ? *leaf_hash : uint256 ());
333+ sigdata.taproot_script_sigs [lookup_key] = sig_out;
334+ }
335+ continue ;
336+ }
337+ // Cannot aggregate, try making partial sigs for every participant
338+ auto pub_key_leaf_hash = std::make_pair (plain_pub, leaf_hash ? *leaf_hash : uint256 ());
339+ for (const CPubKey& part_pk : part_pks) {
340+ uint256 partial_sig;
341+ if (creator.CreateMuSig2PartialSig (provider, partial_sig, agg_pub, plain_pub, part_pk, leaf_hash, tweaks, sigversion, sigdata) && Assume (!partial_sig.IsNull ())) {
342+ sigdata.musig2_partial_sigs [pub_key_leaf_hash].emplace (part_pk, partial_sig);
343+ }
344+ }
345+ // If there are any partial signatures, exit early
346+ auto partial_sigs_it = sigdata.musig2_partial_sigs .find (pub_key_leaf_hash);
347+ if (partial_sigs_it != sigdata.musig2_partial_sigs .end () && !partial_sigs_it->second .empty ()) {
348+ continue ;
349+ }
350+ // No partial sigs, try to make pubnonces
351+ std::map<CPubKey, std::vector<uint8_t >>& pubnonces = sigdata.musig2_pubnonces [pub_key_leaf_hash];
352+ for (const CPubKey& part_pk : part_pks) {
353+ if (pubnonces.contains (part_pk)) continue ;
354+ std::vector<uint8_t > pubnonce = creator.CreateMuSig2Nonce (provider, agg_pub, plain_pub, part_pk, leaf_hash, merkle_root, sigversion, sigdata);
355+ if (pubnonce.empty ()) continue ;
356+ pubnonces[part_pk] = std::move (pubnonce);
357+ }
358+ }
359+ return true ;
360+ }
361+
268362static bool CreateTaprootScriptSig (const BaseSignatureCreator& creator, SignatureData& sigdata, const SigningProvider& provider, std::vector<unsigned char >& sig_out, const XOnlyPubKey& pubkey, const uint256& leaf_hash, SigVersion sigversion)
269363{
270364 KeyOriginInfo info;
@@ -283,11 +377,14 @@ static bool CreateTaprootScriptSig(const BaseSignatureCreator& creator, Signatur
283377 sig_out = it->second ;
284378 return true ;
285379 }
380+
286381 if (creator.CreateSchnorrSig (provider, sig_out, pubkey, &leaf_hash, nullptr , sigversion)) {
287382 sigdata.taproot_script_sigs [lookup_key] = sig_out;
288- return true ;
383+ } else if (!SignMuSig2 (creator, sigdata, provider, sig_out, pubkey, /* merkle_root=*/ nullptr , &leaf_hash, sigversion)) {
384+ return false ;
289385 }
290- return false ;
386+
387+ return sigdata.taproot_script_sigs .contains (lookup_key);
291388}
292389
293390template <typename M, typename K, typename V>
@@ -456,6 +553,10 @@ static bool SignTaproot(const SigningProvider& provider, const BaseSignatureCrea
456553 if (provider.GetTaprootBuilder (output, builder)) {
457554 sigdata.tr_builder = builder;
458555 }
556+ if (auto agg_keys = provider.GetAllMuSig2ParticipantPubkeys (); !agg_keys.empty ()) {
557+ sigdata.musig2_pubkeys .insert (agg_keys.begin (), agg_keys.end ());
558+ }
559+
459560
460561 // Try key path spending.
461562 {
@@ -475,16 +576,22 @@ static bool SignTaproot(const SigningProvider& provider, const BaseSignatureCrea
475576 }
476577 }
477578
478- std::vector< unsigned char > sig;
479- if (sigdata. taproot_key_path_sig . size () == 0 ) {
480- if (creator.CreateSchnorrSig (provider, sig, sigdata. tr_spenddata . internal_key , nullptr , &sigdata. tr_spenddata . merkle_root , SigVersion::TAPROOT)) {
579+ auto make_keypath_sig = [&]( const XOnlyPubKey& pk, const uint256* merkle_root) {
580+ std::vector< unsigned char > sig;
581+ if (creator.CreateSchnorrSig (provider, sig, pk , nullptr , merkle_root, SigVersion::TAPROOT)) {
481582 sigdata.taproot_key_path_sig = sig;
583+ } else {
584+ SignMuSig2 (creator, sigdata, provider, sig, pk, merkle_root, /* leaf_hash=*/ nullptr , SigVersion::TAPROOT);
482585 }
586+ };
587+
588+ // First try signing with internal key
589+ if (sigdata.taproot_key_path_sig .size () == 0 ) {
590+ make_keypath_sig (sigdata.tr_spenddata .internal_key , &sigdata.tr_spenddata .merkle_root );
483591 }
592+ // Try signing with output key if still no signature
484593 if (sigdata.taproot_key_path_sig .size () == 0 ) {
485- if (creator.CreateSchnorrSig (provider, sig, output, nullptr , nullptr , SigVersion::TAPROOT)) {
486- sigdata.taproot_key_path_sig = sig;
487- }
594+ make_keypath_sig (output, nullptr );
488595 }
489596 if (sigdata.taproot_key_path_sig .size ()) {
490597 result = Vector (sigdata.taproot_key_path_sig );
0 commit comments