1

Given raw transaction input/output data, is it possible to know if a Taproot output is multisig or not?

I'm getting raw block data from a bitcoin node, and want to classify each spend according to the script (P2PKH, P2SH, P2WSH, P2WPKH, P2MS and P2TR).

I want to be able to tell if an output represents a multisig spend, in particular for Taproot (P2TR).

Furthermore, if multisig, would it be possible to infer M and N?

2 Answers 2

1

This is possible with every output type except for P2TR. Taproot introduced to the Bitcoin protocol Schnorr signatures and Merklized Alternative Script Trees, both of which can be used to hide the true number of participants in a multisig.

Schnorr signatures

Taproot uses a new signature scheme called Schnorr signatures, which allows key aggregation. A single public key can belong to one user or be aggregated from multiple users using an n-of-n scheme like MuSig2 or even a threshold m-of-n scheme like FROST/ROAST. This makes multisig transactions smaller and therefore cheaper, but it also means you cannot tell if a multisig even happened, let alone its size.

Merklized Alternative Script Trees

A P2TR output can optionally commit to a script tree (MAST). The key difference from previous output types is that you can now have many alternative spending conditions, and only reveal the one that you end up using.

Even without key aggregation, this allows you to obfuscate the actual size of your multisig. For example, if you want a 2-of-3 multisig, you can create a script tree with three different 2-of-2 multisigs: A&B, B&C and A&C. Only one of these 2-of-2s will need to be revealed and nobody will be able to tell if the actual multisig was 2-of-2, 2-of-n for some higher n, or even a decoy multisig in which both keys were in fact owned by the same person.

You can use key aggregation in combination with script trees, for example to implement 2-of-3 using three different keys aggregated using 2-of-2 MuSig2. A footnote in BIP342 goes into a bit of detail on multisigs in script trees.

3
  • Thanks Vojtěch! So if I understand correctly, Schnorr signatures would completely obfuscate the multisig status. For MASTs however, would I be able to at least perform a binary check on whether there is/isn't a multisig present? Oct 21, 2022 at 14:59
  • Not exactly, because a single key present in a leaf script could still be an aggregated key from any number of users, or belong to a 1-of-n multisig construction. There's just no way to tell what the underlying contract looks like. Oct 21, 2022 at 15:08
  • I see. Thanks for the excellent response Vojtěch. Oct 21, 2022 at 15:39
0

If the multisig was implemented through a script that involves multiple signature checks, then yes. Taproot script path spends reveal the full script used, so a technique very similar to P2WSH could be used (the script is the penultimate script stack element rather than the last one, but other than that, it's pretty much the same).

However, that is not the only means of implementing multisig policies, and the other ones aren't as recognizable.

A possibility is that the k-of-n multisig is implemented using several disjoint leaves in the taproot script tree, each script implementing a different k-of-k subset of the k-of-n. In this case you can see there are at least k keys, and based on the depth of the tree you may be able to estimate n, but it very much depends on guessing correctly that this is even what's going on.

It gets even harder if the multisig policy is implemented through MuSig key aggregation (a single key that represents a k-of-k agreement of multisig signers), or FROST native threshold signing (a single key that represents a whole k-of-n policy). These may be entirely indistinguishable on chain from simple single key policies.

2
  • Thanks Pieter. For the Taproot script path spend, the technique (similar to P2WSH) you mention, is it checking if the last byes of the penultimate entry in the witness script stack are 'ae' of 'af'? Or what would that look like? Oct 21, 2022 at 16:40
  • (1) drop the annex (if the last witness stack element starts with byte 0x50, drop it) (2) if the (remaining) stack has only 1 element, it's a key path spend and not a script (3) check if it's a tapscript (identified by the final remaining start element starting with 0xc0 or 0xc1); if not, you know nothing. (4) analyze the script; CHECKMULTISIG(VERIFY) don't exist in tapscript, so the script will likely be "key1 CHECKSIGVERIFY key2 CHECKSIGVERIFY ... keyn CHECKSIG" (for n-of-n) or "key1 CHECKSIG key2 CHECKSIGADD ... keyn CHECKSIGADD k NUMEQUAL" for k-of-n. Oct 21, 2022 at 16:47

Your Answer

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

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