Bug: Not possible to spend a MuSig Address without TapTree
Opened this issue · 4 comments
I have been attempting to construct bitcoin address that is a 2-2 MuSig address only. No taproot tree.
Something like this
points = [alice_public_key, bob_public_key]
musig = MuSigTapScript(points)
internal_pubkey = musig.point
// The address for the ScriptPubKey
p2tr_musig = internal_pubkey.p2tr_address(network="signet")
The p2tr_musig address is always tweaked. see cecc.py L200
I think this is correct per BIP86.
But, when I construct MuSig using the get_signature function. If there is no merkle_root, then no tweak is applied.
So I get back a valid signature from the untweaked public key. However, when I try to verify I transaction with an input that has a p2tr_musig
value as ScriptPubKey it verifies as false. Because the pubkey used for the ScriptPubKey is tweaked, but the sig has not been.
Basically
// Returns valid, but untweaked schnorr sig
schnorr = musig.get_signature(s_sum, r, sig_hash)
// Adds sig to tx input witness
tx_in.finalize_p2tr_keypath(schnorr.serialize())
// Is false
btc_update_tx.verify_input(input_index)
I believe a simple fix would be to remove the if/else in the get_signature function so that the tweak is always applied.
Happy to submit a P.R if I am on the right lines
Hey Will, I'm looking at the BIP327 spec and realizing that it's different than what I've implemented (over a year ago). Thus, I would hold off until the updates to the library for making it BIP327 compliant are done. Sorry for the hassle!
Sure, no worries.
What are the differences out of interest?
Very specific ways to generate the nonce, ways to add more than one tweak and so on. I've got all the tests passing, it's just a matter of getting it ready as a PR.
Any updates on this issue.
It seems per BIP341 all taproot addresses should include a tweak, and in the case where a TapScript is not required this the tweak should commit to an unspendable TapScript. I had a look in the code, but couldn't find it in there.
If the spending conditions do not require a script path, the output key should commit to an unspendable script path instead of having no script path. This can be achieved by computing the output key point as Q = P + int(hashTapTweak(bytes(P)))G. [23] https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki