§ 06 · Script
P2MR
Taproot without the key: a Merkle root of scripts
On this page 7 sections
P2MRP2MR (Pay-to-Merkle-Root): An output locked only by a tree of scripts, with no public key in it: witness version 2, addresses starting prl1z. Valid on Pearl from the start; still a draft proposal for Bitcoin., pay-to-Merkle-root, is a Taproot output with the key taken out. The 32 bytes in the output aren’t a public key at all; they’re the root of a tree of scripts, and the only way to spend is to reveal one of those scripts and satisfy it.
It’s Pearl’s version of BIP-360, a proposal still in draft for Bitcoin. Pearl has accepted it from the first block. It’s rare on chain, and Pearl’s wallet never makes one, but real users do lock coins this way. This page follows one such coin in and out.
Try it
Pick the P2MR spend and hover its witness: two signatures, a script and a 1-byte control block.
What does a P2MR output look like?
- Size
- 34 bytes
- Type
- Witness version 2 program
- Format
- 52 20 ‖ 32-byte Merkle root
52 is OP_2, witness version 2, and 20 pushes the 32-byte root. In bech32m, version 2 is the letter z, so P2MR addresses start prl1z. This transaction in block 130,816 put 1,000 PRL into one:
| Field | Bytes | Value |
|---|---|---|
| Version version | 4 @0 | 1 int32 little-endian. Pearl wallets and pearld coinbases use version 1; relay policy accepts 1-2. |
| Marker marker | 1 @4 | 0x00 Segwit marker (BIP-144): says witness data follows the outputs. |
| Flag flag | 1 @5 | 0x01 Witness flag; 0x01 is the only value Pearl accepts. |
| Input count vin.length | 1 @6 | 2 CompactSize number of inputs. |
| Previous txid vin[0].txid | 32 @7 | c7057fc151674b6511d8a9fba4ee778dd5e89994bc9e61c4709a81343718193e The transaction being spent, stored byte-reversed (internal order); shown here in normal display order. |
| Output index vin[0].vout | 4 @39 | 1 Which output of that transaction is spent (uint32 LE). |
| scriptSig length vin[0].scriptSig.length | 1 @43 | 0 Always 0 for non-coinbase inputs in Pearl: every spend uses the witness instead. |
| Sequence vin[0].sequence | 4 @44 | 0xffffffff Final (0xffffffff): no RBF signal, no relative locktime, and locktime is ignored for this input. Pearl wallets use this. |
| Previous txid vin[1].txid | 32 @48 | 95b04d386bc40cd82934c9e8da8bfc74b2be3815c98e6554833bbcc82bd12469 The transaction being spent, stored byte-reversed (internal order); shown here in normal display order. |
| Output index vin[1].vout | 4 @80 | 849 Which output of that transaction is spent (uint32 LE). |
| scriptSig length vin[1].scriptSig.length | 1 @84 | 0 Always 0 for non-coinbase inputs in Pearl: every spend uses the witness instead. |
| Sequence vin[1].sequence | 4 @85 | 0xffffffff Final (0xffffffff): no RBF signal, no relative locktime, and locktime is ignored for this input. Pearl wallets use this. |
| Output count vout.length | 1 @89 | 2 CompactSize number of outputs. |
| Amount vout[0].value | 8 @90 | 1,245,583,595 grains (12.45583595 PRL) int64 little-endian, in grains (1 PRL = 100,000,000 grains). |
| Script length vout[0].scriptPubKey.length | 1 @98 | 34 CompactSize length of the locking script. |
| Locking script vout[0].scriptPubKey | 34 @99 | prl1pfndqs62kppk2ym63z4e6q7lzkdfe09wk7l5w0ytrzfqhut4c3cmsqtp9cd OP_1 OP_PUSHBYTES_32 <output key Q>: a Taproot output. |
| Amount vout[1].value | 8 @133 | 100,000,000,000 grains (1000.00000000 PRL) int64 little-endian, in grains (1 PRL = 100,000,000 grains). |
| Script length vout[1].scriptPubKey.length | 1 @141 | 34 CompactSize length of the locking script. |
| Locking script vout[1].scriptPubKey | 34 @142 | prl1zcpptqurxrvnx5pn788hph9kcufrmmja7vp0x3lkms7ppc23ppf5q673upx OP_2 OP_PUSHBYTES_32 <Merkle root>: a Pay-to-Merkle-Root output (script path only). |
| Witness items witness[0].length | 1 @176 | 1 Number of witness stack items for input 0. |
| Schnorr signature length witness[0][0].length | 1 @177 | 64 CompactSize length of this witness item. |
| Schnorr signature witness[0][0] | 64 @178 | fa070448a485c43d77920684278440d1cb4e127859871afcf275a6582ae16c7f3856a3b85a15a09a712a64df452fd6140eee602ef75b2fc055a6b3147fade90f 64-byte BIP-340 signature (R.x ‖ s) with SIGHASH_DEFAULT: a Taproot key-path spend. |
| Witness items witness[1].length | 1 @242 | 1 Number of witness stack items for input 1. |
| Schnorr signature length witness[1][0].length | 1 @243 | 64 CompactSize length of this witness item. |
| Schnorr signature witness[1][0] | 64 @244 | 53e47282b1bce9af2697644fc4142d27505ede804fe10b49837c8242a1031d2ad9817daa434b75e371149c71d8083e78c61b61009c63edff091b7f5254520c1f 64-byte BIP-340 signature (R.x ‖ s) with SIGHASH_DEFAULT: a Taproot key-path spend. |
| Locktime locktime | 4 @308 | 0 0: no time lock. |
The address is prl1zcpptqurxrvnx5pn788hph9kcufrmmja7vp0x3lkms7ppc23ppf5q673upx, 63 characters like every Pearl mainnet address.
How is the root built?
Exactly as in Taproot, with the same tagged hashes. Each script is a leaf:
The output above commits to a single script, so its root is that script’s leaf hashTapLeaf hash: The tagged hash of one script in a Taproot or P2MR script tree: TaggedHash("TapLeaf", leaf version ‖ length ‖ script). With a single script, it is the Merkle root.. When it was spent, the script turned out to be 71 bytes, a 2-of-2 multisig:
| Step | Value |
|---|---|
| Leaf script (71 bytes) | 0020b5b010c0…4d307d ba 2003b77fbc…c7ae89 ba 52 9c |
| Preimage | c0 (leaf version) ‖ 47 (71) ‖ the script |
| TaggedHash(“TapLeaf”, preimage) | c042b070661b266a067e39ee1b96d8e247bdcbbe605e68fedb87821c2a210a68 |
| Output’s 32 bytes | c042b070661b266a067e39ee1b96d8e247bdcbbe605e68fedb87821c2a210a68: equal |
With more scripts, the leaves are paired up with TapBranch hashes until one root remains. Two leaves <G> OP_CHECKSIG and <3G> OP_CHECKSIG, for example (a test vector built with Pearl’s code), have the root 948e2e1895d94ef46707b2b63b764b4eb2d30ab31f6c4d343a72969fabca06f2 and the address prl1zjj8zuxy4m980gec8k2mrkajtf6edxz4nraky6dp6w2tfl272qmeqpu4nqx.
How is a P2MR output spent?
By revealing a script. The witness is the script’s inputs, then the script, then the control blockControl block: The last item of a script-path witness: a few bytes proving that the script being run really belongs to the output's script tree.:
| Field | Bytes | Value |
|---|---|---|
| Version version | 4 @0 | 1 int32 little-endian. Pearl wallets and pearld coinbases use version 1; relay policy accepts 1-2. |
| Marker marker | 1 @4 | 0x00 Segwit marker (BIP-144): says witness data follows the outputs. |
| Flag flag | 1 @5 | 0x01 Witness flag; 0x01 is the only value Pearl accepts. |
| Input count vin.length | 1 @6 | 1 CompactSize number of inputs. |
| Previous txid vin[0].txid | 32 @7 | 2991e42afb3613fe14d28882c6cff8d18d73471655487be2e71940c2f34fe212 The transaction being spent, stored byte-reversed (internal order); shown here in normal display order. |
| Output index vin[0].vout | 4 @39 | 1 Which output of that transaction is spent (uint32 LE). |
| scriptSig length vin[0].scriptSig.length | 1 @43 | 0 Always 0 for non-coinbase inputs in Pearl: every spend uses the witness instead. |
| Sequence vin[0].sequence | 4 @44 | 0xffffffff Final (0xffffffff): no RBF signal, no relative locktime, and locktime is ignored for this input. Pearl wallets use this. |
| Output count vout.length | 1 @48 | 3 CompactSize number of outputs. |
| Amount vout[0].value | 8 @49 | 98,000,000,000 grains (980.00000000 PRL) int64 little-endian, in grains (1 PRL = 100,000,000 grains). |
| Script length vout[0].scriptPubKey.length | 1 @57 | 34 CompactSize length of the locking script. |
| Locking script vout[0].scriptPubKey | 34 @58 | prl1p6gs43sjpfxpmq9mlp2juna44txx50afdrpeytd6s2r0r7kc3rmlscf8dpl OP_1 OP_PUSHBYTES_32 <output key Q>: a Taproot output. |
| Amount vout[1].value | 8 @92 | 999,999,500 grains (9.99999500 PRL) int64 little-endian, in grains (1 PRL = 100,000,000 grains). |
| Script length vout[1].scriptPubKey.length | 1 @100 | 34 CompactSize length of the locking script. |
| Locking script vout[1].scriptPubKey | 34 @101 | prl1pu6x5e5z7svtu03xtazz3d9xrwm4qgfphatv94fd9t3wy79ds8qrq8x6km9 OP_1 OP_PUSHBYTES_32 <output key Q>: a Taproot output. |
| Amount vout[2].value | 8 @135 | 999,999,500 grains (9.99999500 PRL) int64 little-endian, in grains (1 PRL = 100,000,000 grains). |
| Script length vout[2].scriptPubKey.length | 1 @143 | 34 CompactSize length of the locking script. |
| Locking script vout[2].scriptPubKey | 34 @144 | prl1pq3mn238ug5cj32c6tf8hy9u5582pg8a0t2geh9qj74ktlfqp8alsddygmv OP_1 OP_PUSHBYTES_32 <output key Q>: a Taproot output. |
| Witness items witness[0].length | 1 @178 | 4 Number of witness stack items for input 0. |
| Signature length witness[0][0].length | 1 @179 | 64 CompactSize length of this witness item. |
| Signature witness[0][0] | 64 @180 | fca1da7d031d5096e68ac4501b30b907a35a379ce9aac05fa337cff0bd5ebecaf8a9ff45acdb2738e54937e8f56652f357328995ea567af6648151c510619960 64-byte BIP-340 Schnorr signature (SIGHASH_DEFAULT) consumed by the leaf script. |
| Signature length witness[0][1].length | 1 @244 | 64 CompactSize length of this witness item. |
| Signature witness[0][1] | 64 @245 | 4122bbf2d9ce57758ae7a15c6c7096a4401439630bbb45b7268eefef05f5f4128d9b04872ac61925ec231298c463d1102fa24f674dcd7a698873302d3873790a 64-byte BIP-340 Schnorr signature (SIGHASH_DEFAULT) consumed by the leaf script. |
| Leaf script length witness[0][2].length | 1 @309 | 71 CompactSize length of this witness item. |
| Leaf script witness[0][2] | 71 @310 | 0020b5b010c0e14cb57cecaba3484b962e6a7f92a9f2cb7bf66d9f0fbc0ced4d307dba2003b77fbc5b8c2f9c5e544c744b0a49e11cde9e6c32035cbba093774f57c7ae89ba529c The tapscript being executed; its TapLeaf hash is proven against the output by the control block. |
| Control block length witness[0][3].length | 1 @381 | 1 CompactSize length of this witness item. |
| Control block witness[0][3] | 1 @382 | c1 P2MR control block: 0xc1 = leaf version 0xc0 with the parity bit forced to 1, no internal key, no proof hashes (single-leaf tree). |
| Locktime locktime | 4 @383 | 0 0: no time lock. |
| Field | Size | Description |
|---|---|---|
| leaf version | 1 | 1 | c0 with its low bit set: always c1. The low bit must be 1. |
| Merkle path | 32 × m | Sibling hashes up to the root; none for a one-script tree. m is at most 128. |
No internal key, so the control block is 1 + 32m bytes, at most 4,097. Here it’s the single byte c1. For the two-leaf test tree above, spending the first leaf would need c1 followed by the other leaf’s hash, a5f4dd9b…333e5f: 33 bytes.
The node then:
-
Rejects a key path
If only one item is left (after removing any annex), it fails: “P2MR does not support key-path spends”. -
Rebuilds the root
From the revealed script and the path in the control block. -
Compares directly
The root must equal the 32 bytes in the output. No tweak is involved. -
Runs the script
As tapscript, with the earlier witness items as its stack. For this 2-of-2, both signatures check out and the script ends with true. The Script page traces it step by step.
The spend paid a 1,000-grain fee for 232 vbytes, 4.3 grains per vbyte, low but still mined.
What is the sighash quirk?
The one way P2MR on Pearl differs from the BIPs, and the reason textbook signing code doesn’t work.
A signature normally commits to the amounts and locking scripts of every coin being spent. Pearl’s node only computes those two fields when some input spends a Taproot (P2TR) output. In a transaction whose inputs are all P2MR, both stay at 32 zero bytes, and that’s the message consensus checks.
The spend above shows it. Rebuilding its signed message both ways:
- With zeros in sha_amounts and sha_scriptpubkeys: sighash
0f7cb7d4…b89dd382. Both signatures are valid. - As BIP-341/342 specify: sighash
826d8ce5…3c683d8b. Neither signature is valid.
So these P2MR signatures don’t commit to what they’re spending, and a signer written to the BIP-360 text gets its signatures rejected. A transaction that also spends at least one P2TR input uses the real values throughout. Details on the sighash page.
Why would anyone use P2MR?
BIP-360’s argument is about quantum computers. A Taproot output puts an elliptic-curve key (Q) on chain the moment it’s created, and a large enough quantum computer could in principle work out its private key. A P2MR output holds only a hash of scripts, so there’s no key to attack until a script is revealed.
That only helps if the scripts themselves are quantum-safe. BIP-360 defines no post-quantum signature check; Pearl adds one, OP_CHECKXMSSSIG. The 2-of-2 on this page uses ordinary Schnorr keys, which become visible when it’s spent.
Who uses P2MR on Pearl?
- Consensus: valid on every Pearl network. The code has no activation height for it, so it has been valid since genesis.
- Pearl’s wallet: can spend a single-leaf P2MR output whose script it has stored, but nothing in the v1.5.2 code outside tests creates P2MR addresses. Default addresses and quantum-safe addresses are both Taproot.
- On chain: rare. In 200 recent blocks there were 5 P2MR outputs against 62,638 Taproot outputs, and the P2MR spends seen all had this 2-of-2 shape (witness items of 64, 64, 71 and 1 bytes).