Why does a MuSig2 partial signature pass local verification but get rejected by mempool — BIP341 double-tweak with python-bitcoinutils?

Why does a MuSig2 partial signature pass local verification but get rejected by mempool — BIP341 double-tweak with python-bitcoinutils?

Manage alerts

Loading saved threads...

Aaron Zhang · External communityPost link
External question — Bitcoin Stack Exchange Author: Aaron Zhang Original post: https://bitcoin.stackexchange.com/questions/130657 License: CC BY-SA 4.0 — https://creativecommons.org/licenses/by-sa/4.0/ Adaptation: HTML converted to plain text; contact email addresses removed. I implemented a MuSig2 cooperative close for a Taproot Lightning channel on testnet. Local signature verification passed, but the transaction was rejected by Bitcoin Core's mempool. I first suspected the nonce aggregation was wrong, then thought it might be a sighash mismatch — printed the raw bytes on both sides, identical. Eventually I dumped the actual output key from the library versus what I had in my SessionContext. They were different. That's when I realized the issue was related to BIP86 tweaks. Has anyone run into this?
Quote
Report
Aaron Zhang · External communityPost link
External answer — Bitcoin Stack Exchange Author: Aaron Zhang Original post: https://bitcoin.stackexchange.com/a/130658 License: CC BY-SA 4.0 — https://creativecommons.org/licenses/by-sa/4.0/ Adaptation: HTML converted to plain text; contact email addresses removed. The problem is a double tweak. python-bitcoinutils applies a BIP86 tweak internally when you call get_taproot_address(). If you have already applied a BIP86 tweak manually to the aggregate key, the on-chain output key has been tweaked twice. Local schnorr_verify passes because it checks against the key you provide — it does not know what is actually on-chain. Bitcoin Core checks against the real output key, which has two tweaks applied. The signature built with only one tweak is invalid against that key. The fix: SessionContext must carry both tweaks explicitly: pythonsession_ctx = SessionContext( aggnonce, pubkeys, [tweak1, tweak2], # both tweaks required [True, True], msg ) This is not a bug — the library handles BIP86 automatically for typical single-key use. In MuSig2, where you manage tweaks manually, the abstraction leaks. Verified on testnet: af6fdae8...9d1f
Quote
Report

Post Reply

Quoted from Forex.com.bd-Editorial External question — Bitcoin Stack Exchange Author: Aaron Zhang Source score (net votes, not local likes): 0 Original post: https://bitcoin.stackexchange.com/questions/130657 License: CC BY-SA 4.0 — https://creativecommons.org/licenses/by-sa/4.0/ Adaptation: HTML converted to plain text; contact email addresses removed. I implemented a MuSig2 cooperative close for a Taproot Lightning channel on testnet. Local signature verification passed, but the transaction was rejected by Bitcoin Core's mempool. I first suspected the nonce aggregation was wrong, then thought it might be a sighash mismatch — printed the raw bytes on both sides, identical. Eventually I dumped the actual output key from the library versus what I had in my SessionContext. They were different. That's when I realized the issue was related to BIP86 tweaks. Has anyone run into this?

Cancel quote

Checking account access…