The Witness That Tells Everything
Your transaction just confirmed. Taproot did its job, you think, and the spending conditions you used are nobody's business. That assumption is correct, right up until the moment it isn't, and the line between private and exposed runs straight through the witness field, visible to every node that downloads the transaction.
Taproot's central promise was elegant: a multisig, a time-lock, or a plain single-key spend could all look identical on-chain, provided the keypath was used. That promise holds. The word "provided" is doing a lot of work in that sentence, and most commentary glosses right past it. The moment a script is actually executed, the witness structure announces the fact to the network. Understanding exactly why requires looking at how Taproot constructs its outputs.
One Output, Two Very Different Witnesses
A Taproot output is a Pay-to-Taproot (P2TR) scriptPubKey: a 34-byte structure containing a single 32-byte x-only public key, the tweaked key. That key encodes a commitment to both an internal key and a Merkle root of possible scripts. At output creation, observers see one uniform blob. Nothing is distinguishable yet.
Spending is where the paths diverge.
Keypath spend: The witness contains exactly one item, a 64-byte Schnorr signature (65 bytes if using a non-default sighash type). No script, no control block. A chain observer sees a signature and nothing else. Whether that single key is controlled by one person or is the aggregated MuSig2 key of a 7-of-12 multisig, the witness looks identical.
Scriptpath spend: The witness must contain, at minimum, the spending script itself (the script leaf) and a control block. The control block is a byte string beginning with a version byte plus the parity of the output key, followed by the 32-byte internal public key, then zero or more 32-byte Merkle proof nodes (the inclusion proof). Every item is visible to any observer who downloads the transaction.
The detection is trivial. Count the witness items: one item at 64 bytes is keypath; two or more items, with the last one a control block, is scriptpath. No heuristics required. The distinction is structural, not probabilistic.
What the Control Block Actually Gives Away
Consider two users, Priya and Daniel, both setting up 2-of-3 multisig wallets using Taproot. Priya's wallet uses keypath spending via MuSig2: all three cosigners coordinate to produce a single aggregated signature. On-chain, her spend looks like any solo payment. A passive observer learns nothing about the multisig arrangement.
Daniel's wallet uses scriptpath spending with a traditional CHECKSIGADD script, because his hardware wallet does not support MuSig2 key aggregation. His transaction witness contains the two required signatures, the CHECKSIGADD script leaf, and a control block. The control block's length is itself informative. A control block with no internal Merkle nodes (33 bytes after the version byte) means the script tree had only one leaf. A control block with two 32-byte nodes (33 + 64 = 97 bytes) means the tree had at least three leaves and his script was at a specific depth.
From that control block, an observer can deduce roughly how many alternative scripts existed (from the proof depth), which script was actually used (it is plainly in the witness), and the internal public key (also in the control block). That internal key may match a known wallet fingerprint or key derivation pattern.
Priya spent privately. Daniel left a detailed map.
What People Get Wrong About Taproot Privacy
The common mistake is treating Taproot as a blanket privacy upgrade. It is not. It is a conditional privacy upgrade, and the condition is strict: keypath spending, full stop.
The upgrade is real. Before Taproot, a 2-of-3 multisig using P2WSH had to reveal all three public keys and the entire script at spend time, regardless of which execution path was taken. Taproot hides the unexecuted branches entirely. If Daniel had three scripts in his tree and used only one, observers see only that one script, not the others. That is a genuine improvement over legacy multisig, and it deserves credit.
The improvement is asymmetric, though. Keypath spends are opaque. Scriptpath spends reveal the executed script completely, the internal pubkey, and the depth and shape of the Merkle tree for unexecuted branches. The gap between those two outcomes is wide enough to matter.
There is also a subtler problem, one the privacy discussion rarely surfaces. Keypath spending requires interactive signature aggregation before the transaction is broadcast. For cold storage setups where signers are air-gapped and communicate asynchronously, scriptpath is often the pragmatic choice. Wallet software and hardware constraints, not user negligence, push people toward the more revealing path. Blockchain analytics firms already flag control-block patterns to identify wallet software and custody arrangements. This is not a hypothetical: it is documented clustering methodology.
So here is the question worth sitting with: if the infrastructure that is supposed to protect user privacy systematically steers users toward the less private option, who exactly is the privacy guarantee for?
The Merkle Tree Is a One-Way Cloak
Think of the Taproot script tree as a coat with hidden pockets. Until you reach into a pocket, nobody knows how many exist or what is in them. The moment you pull something out, everyone sees what you pulled, how deep the pocket was, and gets a reasonable silhouette of the coat's internal structure.
The Merkle inclusion proof hides the specific contents of unexecuted branches, yes. A tree with four script leaves reveals only one at spend time; the other three remain private. The proof depth, though, tells observers the tree had at least that many leaves. Sophisticated observers can combine the internal key with known wallet templates to make educated guesses about the hidden branches. The privacy model here is probabilistic concealment of unexecuted paths, not cryptographic concealment of the spending mechanism itself. Those are meaningfully different guarantees, and conflating them is where analysis goes wrong.
For wallet designers, the practical implication is not complicated: keypath spending should be the default happy path, not a premium feature. Scriptpath belongs in genuine fallback conditions. When scriptpath is unavoidable, the sound approach is to minimize tree depth and avoid script templates unique to a single wallet vendor. The chain will always see the witness. The goal is for that witness to look like everyone else's, which is a design objective that has to be built in from the start, not patched in after the fact.