| 280 | } |
| 281 | |
| 282 | 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) |
| 283 | { |
| 284 | Assert(sigversion == SigVersion::TAPROOT || sigversion == SigVersion::TAPSCRIPT); |
| 285 | |
| 286 | // Lookup derivation paths for the script pubkey |
| 287 | KeyOriginInfo agg_info; |
| 288 | auto misc_pk_it = sigdata.taproot_misc_pubkeys.find(script_pubkey); |
| 289 | if (misc_pk_it != sigdata.taproot_misc_pubkeys.end()) { |
| 290 | agg_info = misc_pk_it->second.second; |
| 291 | } |
| 292 | |
| 293 | for (const auto& [agg_pub, part_pks] : sigdata.musig2_pubkeys) { |
| 294 | if (part_pks.empty()) continue; |
| 295 | |
| 296 | // Fill participant derivation path info |
| 297 | for (const auto& part_pk : part_pks) { |
| 298 | KeyOriginInfo part_info; |
| 299 | if (provider.GetKeyOrigin(part_pk.GetID(), part_info)) { |
| 300 | XOnlyPubKey xonly_part(part_pk); |
| 301 | auto it = sigdata.taproot_misc_pubkeys.find(xonly_part); |
| 302 | if (it == sigdata.taproot_misc_pubkeys.end()) { |
| 303 | it = sigdata.taproot_misc_pubkeys.emplace(xonly_part, std::make_pair(std::set<uint256>(), part_info)).first; |
| 304 | } |
| 305 | if (leaf_hash) it->second.first.insert(*leaf_hash); |
| 306 | } |
| 307 | } |
| 308 | |
| 309 | // The pubkey in the script may not be the actual aggregate of the participants, but derived from it. |
| 310 | // Check the derivation, and compute the BIP 32 derivation tweaks |
| 311 | std::vector<std::pair<uint256, bool>> tweaks; |
| 312 | CPubKey plain_pub = agg_pub; |
| 313 | if (XOnlyPubKey(agg_pub) != script_pubkey) { |
| 314 | if (agg_info.path.empty()) continue; |
| 315 | // Compute and compare fingerprint |
| 316 | CKeyID keyid = agg_pub.GetID(); |
| 317 | if (!std::equal(agg_info.fingerprint, agg_info.fingerprint + sizeof(agg_info.fingerprint), keyid.data())) { |
| 318 | continue; |
| 319 | } |
| 320 | // Get the BIP32 derivation tweaks |
| 321 | CExtPubKey extpub = CreateMuSig2SyntheticXpub(agg_pub); |
| 322 | for (const int i : agg_info.path) { |
| 323 | auto& [t, xonly] = tweaks.emplace_back(); |
| 324 | xonly = false; |
| 325 | if (!extpub.Derive(extpub, i, &t)) { |
| 326 | return false; |
| 327 | } |
| 328 | } |
| 329 | Assert(XOnlyPubKey(extpub.pubkey) == script_pubkey); |
| 330 | plain_pub = extpub.pubkey; |
| 331 | } |
| 332 | |
| 333 | // Add the merkle root tweak |
| 334 | if (sigversion == SigVersion::TAPROOT && merkle_root) { |
| 335 | tweaks.emplace_back(script_pubkey.ComputeTapTweakHash(merkle_root->IsNull() ? nullptr : merkle_root), true); |
| 336 | std::optional<std::pair<XOnlyPubKey, bool>> tweaked = script_pubkey.CreateTapTweak(merkle_root->IsNull() ? nullptr : merkle_root); |
| 337 | if (!Assume(tweaked)) return false; |
| 338 | plain_pub = tweaked->first.GetCPubKeys().at(tweaked->second ? 1 : 0); |
| 339 | } |
no test coverage detected