2

We have two companies and we want to spend funds with 1-of-2 multisig. We successfully did such a multisig with P2SH. How can I do this in P2TR? Can any give me a detailed instruction step by step? Thanks.

1
  • 3
    Hi Wei, do you have any requirements regarding the software, programming language or library you are using?
    – Murch
    Commented Mar 1, 2023 at 23:29

1 Answer 1

1

The Tapscript would look like this:

<32-byte pubkey1> OP_CHECKSIG <32-byte pubkey2> OP_CHECKSIGADD 1 OP_NUMEQUAL

Note: Unlike in P2SH/P2WSH, pubkeys should be 32-byte x-only pubkeys in tapscript.

This tapscript would go in the Tapscript tree. Assuming this is the only script you'd like to lock the bitcoin to, the tree would be a single leaf with this script and the BIP342 Leaf Version.

Next, you must define an internal pubkey. Assuming you want the 1-of-2 script to be the only way to spend the bitcoin, you can follow BIP341's recommendation for how to generate a private but provably unsolvable internal key.

...pick as internal key a point with unknown discrete logarithm. One example of such a point is H = lift_x(0x0250929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0) which is constructed by taking the hash of the standard uncompressed encoding of the secp256k1 base point G as X coordinate. In order to avoid leaking the information that key path spending is not possible it is recommended to pick a fresh integer r in the range 0...n-1 uniformly at random and use H + rG as internal key. It is possible to prove that this internal key does not have a known discrete logarithm with respect to G by revealing r to a verifier who can then reconstruct how the internal key was created.

From there, you must merkelize the script tree (a single leaf in your case) and use the result to tweak the internal pubkey, resulting in Q, the Taproot output key. BIP341 explains this process and provides sample python code to do so:

https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki#constructing-and-spending-taproot-outputs

5
  • 3
    That seems a bit silly; you can instead pick one of the keys as internal key, and use the other one in a "<key> OP_CHECKSIG" script. That's strictly cheaper to spend. Commented Mar 8, 2023 at 17:55
  • Yes this is definitely the better way to go if the only spend option you want is a 1-of-2. I think my answer is still valuable in the case that someone wants a 1-of-2 multisig as only 1 in a set of possible spend conditions. Commented Mar 11, 2023 at 15:50
  • 1
    Even then it's better to split the options up into two individual single key options, and either turn both into leaves, or one into a leaf and the other into a key path. But fair enough, in that case it's less clear cut. Commented Mar 11, 2023 at 17:58
  • @sachin To clarify, the unlocking script for this would be either [00] [sig] or [sig] [00], and the script would fail if [sig0] [sig1] is provided (regardless if one or both signatures were valid). Correct?
    – Peter
    Commented May 13, 2023 at 15:44
  • To be clear, the 0x00 byte indicates an empty vector. It's the length byte, not actual data. so the unlocking part of the stack would be [sig] [] or [] [sig]. And yes, [sig] [sig] should fail. You could easily change the script to accept >= N signatures but why waste data. Commented May 23, 2023 at 17:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.