OP_DROPProtocol

Conformance vectors, spec 1.0.0

Test vectors

Every byte on this page was produced by the reference OP_DROP encoder and verified by the reference decoder and the reference Taproot commitment check. Paste any leaf hex into the builder and decoder to reproduce the result in your browser.

These are documentation keys. The key pair below is published so the vectors are reproducible. Never send funds to any address on this page. Anyone can spend from them.

Shared setup

Parameters shared by every vector
Private key (documentation only)4654771a8e22773b5fd328d1ebad41f6c97f637e014984ae03a5d142bf51def1
x-only public key8836f3e74b35d5367eb26b762186393bad3cdf669c822772c0a0ee7398aebf3b
Taproot internal keythe same x-only key
Script treesingle leaf, tapleaf version 0xc0, depth 0
Networkmainnet (leaf bytes are identical on every network; only the address encoding differs)

V. Valid leaves

V1. Deploy drop

Payload{"p":"op-drop","op":"deploy","tick":"drop","max":"21000000","lim":"1000"}
Payload bytes73
Payload sha256f970d478e38939a89f6d9615aef772e21716dc79e2e752de1dd0539c553b74ca
Leaf script0e6269703131302d6f702d64726f7075106170706c69636174696f6e2f6a736f6e7520f970d478e38939a89f6d9615aef772e21716dc79e2e752de1dd0539c553b74ca75497b2270223a226f702d64726f70222c226f70223a226465706c6f79222c227469636b223a2264726f70222c226d6178223a223231303030303030222c226c696d223a2231303030227d75208836f3e74b35d5367eb26b762186393bad3cdf669c822772c0a0ee7398aebf3bac
Leaf script bytes177
Leaf script sha256546e1624adf71006b54721e2a005d6c91af513e3e8b09497e3f19c5b0181d1ec
Commit scriptPubKey5120f865873be28e8ea28d0f6dd018b94a30ec17b569b2cac767eb7f7b5222e43805
Commit addressbc1plpjcwwlz36829rg0dhgp3w22xrkp0dtfkt9vwelt0aa4yghy8qzsnqwgwm
Control blockc08836f3e74b35d5367eb26b762186393bad3cdf669c822772c0a0ee7398aebf3b
Reveal size estimate656 weight units, 164 vB (94 base bytes, 278 witness bytes)
Expected outcomecarrier valid; ledger valid if drop has no prior deployment on this network

V2. Mint 1000 drop

Payload{"p":"op-drop","op":"mint","tick":"drop","amt":"1000"}
Payload bytes54
Payload sha2563c0153364dd98ded936f3d29a89959c6ca0e294540746e543037cbcfc33912e1
Leaf script0e6269703131302d6f702d64726f7075106170706c69636174696f6e2f6a736f6e75203c0153364dd98ded936f3d29a89959c6ca0e294540746e543037cbcfc33912e175367b2270223a226f702d64726f70222c226f70223a226d696e74222c227469636b223a2264726f70222c22616d74223a2231303030227d75208836f3e74b35d5367eb26b762186393bad3cdf669c822772c0a0ee7398aebf3bac
Leaf script bytes158
Leaf script sha256f80ecba1d440272ecb76343680714a46c92be62e9a97760e700bccb3f5140bad
Commit scriptPubKey51209194a35d62f90d352729397e55a85100e092049ce27bcd7202c8388c63559d2c
Commit addressbc1pjx22xhtzlyxn2fef89l9t2z3qrsfypyuufau6uszequgcc64n5kqtlwnap
Control blockc18836f3e74b35d5367eb26b762186393bad3cdf669c822772c0a0ee7398aebf3b
Reveal size estimate637 weight units, 160 vB (94 base bytes, 259 witness bytes)
Expected outcomecarrier valid; ledger credits 1000 to the anchor address if drop is deployed and supply remains

The control block for V2 begins c1 rather than c0 because the tweaked output key has odd parity for this leaf. Both are correct; the low bit of the first byte carries the parity.

V3. Transfer 250 drop

Payload{"p":"op-drop","op":"transfer","tick":"drop","amt":"250"}
Payload bytes57
Payload sha256090455d3d8b15ef3d38e202c8c13033362c58e961f078615a1f1f23df256c13e
Leaf script0e6269703131302d6f702d64726f7075106170706c69636174696f6e2f6a736f6e7520090455d3d8b15ef3d38e202c8c13033362c58e961f078615a1f1f23df256c13e75397b2270223a226f702d64726f70222c226f70223a227472616e73666572222c227469636b223a2264726f70222c22616d74223a22323530227d75208836f3e74b35d5367eb26b762186393bad3cdf669c822772c0a0ee7398aebf3bac
Leaf script bytes161
Leaf script sha256e57210d2444c8e6253da80594070177b0d6564248ff18a7b2881665933b2586e
Commit scriptPubKey51203cde155d12f33c25f52b796b8c924fb87cc69d41025782cfa877117596be7787
Commit addressbc1p8n0p2hgj7v7ztaft094ceyj0hp7vd82pqftc9nagwught947w7rsvapwql
Control blockc18836f3e74b35d5367eb26b762186393bad3cdf669c822772c0a0ee7398aebf3b
Reveal size estimate640 weight units, 160 vB (94 base bytes, 262 witness bytes)
Expected outcomecarrier valid; ledger reserves 250 and opens a transfer against anchor {revealTxid}:0

V4. Largest possible deploy payload

Every field at its maximum: a four-character ticker with max and lim both at 264 minus 1. This is the upper bound on a token payload, and it is well below the 256-byte push ceiling.

Payload{"p":"op-drop","op":"deploy","tick":"zzzz","max":"18446744073709551615","lim":"18446744073709551615"}
Payload bytes101
Payload sha256d8b26b33fd53926571adbf5ae1c5896662d431405b9ef917d6e3e299e13f51fc
Push encodingOP_PUSHDATA1 (0x4c 0x65), because 101 is above 75
Leaf script bytes206
Expected outcomecarrier valid, ledger valid

T. Commitment vectors

These use the V2 leaf and vary only the proof. They separate "this is not an OP_DROP leaf at all" from "this leaf did not belong to the output that was spent".

Taproot commitment outcomes
#InputExpected result
T1V2 leaf, control block c18836…bf3b, previous output 51209194…9d2cvalid The leaf is committed by the spent output.
T2V2 leaf, V2 control block, previous output belonging to a different Taproot keyinvalid_taproot_commitment Reason text: Taproot leaf does not commit to previous output.
T3V2 leaf, V2 control block, previous output 0014 followed by 20 zero bytes (P2WPKH)invalid_taproot_commitment Reason text: previous output is not P2TR.
T4V2 leaf, control block with first byte changed to c2invalid_taproot_commitment Reason text: unsupported Taproot leaf version.
T5V2 leaf, control block of 65 bytes (a one-level tree path)not an OP_DROP reveal The witness fails OD-3.2, so no event is recorded at all.
T6Witness with four items (signature, script, control block, annex)not an OP_DROP reveal The witness fails OD-3.1.

I. Invalid leaves

Each of these is a complete script hex. Paste any of them into the decoder to see the same message.

I1. Non-minimal push encoding

The V2 leaf with the 14-byte marker re-encoded using OP_PUSHDATA1 (4c 0e) instead of a direct push. Every field decodes identically. It is still invalid.

4c0e6269703131302d6f702d64726f7075106170706c69636174696f6e2f6a736f6e75203c0153364dd98ded936f3d29a89959c6ca0e294540746e543037cbcfc33912e175367b2270223a226f702d64726f70222c226f70223a226d696e74222c227469636b223a2264726f70222c22616d74223a2231303030227d75208836f3e74b35d5367eb26b762186393bad3cdf669c822772c0a0ee7398aebf3bac

rejected Rule OD-4.8. Not recorded as an event.

I2. Unknown carrier marker

The V2 leaf with the marker changed to bip110-op-drip.

0e6269703131302d6f702d6472697075106170706c69636174696f6e2f6a736f6e75203c0153364dd98ded936f3d29a89959c6ca0e294540746e543037cbcfc33912e175367b2270223a226f702d64726f70222c226f70223a226d696e74222c227469636b223a2264726f70222c22616d74223a2231303030227d75208836f3e74b35d5367eb26b762186393bad3cdf669c822772c0a0ee7398aebf3bac

rejected Rule OD-4.1. Not recorded as an event.

I3. Digest does not match the payload

The V2 leaf with the final byte of the digest field changed from e1 to e0.

0e6269703131302d6f702d64726f7075106170706c69636174696f6e2f6a736f6e75203c0153364dd98ded936f3d29a89959c6ca0e294540746e543037cbcfc33912e075367b2270223a226f702d64726f70222c226f70223a226d696e74222c227469636b223a2264726f70222c22616d74223a2231303030227d75208836f3e74b35d5367eb26b762186393bad3cdf669c822772c0a0ee7398aebf3bac

rejected Rule OD-4.3. Not recorded as an event.

I4. Reordered payload keys

A well-formed leaf whose payload is {"op":"mint","p":"op-drop","tick":"drop","amt":"1000"}. The digest matches the payload; only the key order is wrong.

0e6269703131302d6f702d64726f7075106170706c69636174696f6e2f6a736f6e75202da4f53ea09fdcfa8b20793398294870c00d671c7cd51cbeb949bbfdab3b35a175367b226f70223a226d696e74222c2270223a226f702d64726f70222c227469636b223a2264726f70222c22616d74223a2231303030227d75208836f3e74b35d5367eb26b762186393bad3cdf669c822772c0a0ee7398aebf3bac

rejected Rule OD-6.6. Not recorded as an event.

I5. Whitespace in the payload

Payload {"p": "op-drop", "op": "mint", "tick": "drop", "amt": "1000"}, 61 bytes instead of 54, with a matching digest.

0e6269703131302d6f702d64726f7075106170706c69636174696f6e2f6a736f6e75206dabec6b4ddc3f46f53da8e34ad2f11544c82ec1d1b869b3e44fff35bb3c4280753d7b2270223a20226f702d64726f70222c20226f70223a20226d696e74222c20227469636b223a202264726f70222c2022616d74223a202231303030227d75208836f3e74b35d5367eb26b762186393bad3cdf669c822772c0a0ee7398aebf3bac

rejected Rule OD-6.12. Not recorded as an event.

I6. Five-character ticker

Payload {"p":"op-drop","op":"mint","tick":"drops","amt":"1000"}.

0e6269703131302d6f702d64726f7075106170706c69636174696f6e2f6a736f6e752004ae962007e5de7d7d56494e2181850272c6fb1168a672a86c03bd599e97d23375377b2270223a226f702d64726f70222c226f70223a226d696e74222c227469636b223a2264726f7073222c22616d74223a2231303030227d75208836f3e74b35d5367eb26b762186393bad3cdf669c822772c0a0ee7398aebf3bac

rejected Rule OD-6.5. Not recorded as an event.

I7. A conditional opcode in the grammar

The V2 leaf with the first OP_DROP (75) replaced by OP_IF (63). This is roughly what a witness envelope looks like at that position, and it is exactly what OP_DROP refuses.

0e6269703131302d6f702d64726f7063106170706c69636174696f6e2f6a736f6e75203c0153364dd98ded936f3d29a89959c6ca0e294540746e543037cbcfc33912e175367b2270223a226f702d64726f70222c226f70223a226d696e74222c227469636b223a2264726f70222c22616d74223a2231303030227d75208836f3e74b35d5367eb26b762186393bad3cdf669c822772c0a0ee7398aebf3bac

rejected Rules OD-4.6 and OD-4.9. Not recorded as an event.

I8. Carrier valid, ledger invalid

A deploy carrying self_mint. The leaf parses, the digest matches, the push encoding is minimal, and the Taproot proof would succeed. The ledger still refuses it.

Payload{"p":"op-drop","op":"deploy","tick":"demo","max":"21000000","lim":"1000","self_mint":"true"}
Payload bytes92 (encoded with OP_PUSHDATA1, 0x4c 0x5c)
Payload sha256b197c20f43a1d8cd3ca7fc7fe1c9c10328efaf4b8656d53f198a134774aa4e72
Leaf script0e6269703131302d6f702d64726f7075106170706c69636174696f6e2f6a736f6e7520b197c20f43a1d8cd3ca7fc7fe1c9c10328efaf4b8656d53f198a134774aa4e72754c5c7b2270223a226f702d64726f70222c226f70223a226465706c6f79222c227469636b223a2264656d6f222c226d6178223a223231303030303030222c226c696d223a2231303030222c2273656c665f6d696e74223a2274727565227d75208836f3e74b35d5367eb26b762186393bad3cdf669c822772c0a0ee7398aebf3bac
Carrier resultvalid
Ledger resultinvalid reason unsupported_self_mint, recorded as an event, no balance change

This is the case that shows why the two layers are specified separately. An implementation that only checks the carrier will report this as a successful deploy and be wrong.

L. Ledger sequences

Apply these in order on a fresh network. Each row is one event, in the ordering defined by OD-9.1.

L1: supply arithmetic including the partial final mint
#EventResultCreditedMinted after
1deploy tick=test max=100 lim=30valid-0
2deploy tick=test max=999 lim=1duplicate_deploy-0
3mint tick=test amt=30valid3030
4mint tick=test amt=31mint_limit_exceeded030
5mint tick=test amt=30valid3060
6mint tick=test amt=30valid3090
7mint tick=test amt=30valid, partial10100
8mint tick=test amt=1supply_exhausted0100
9mint tick=zzzz amt=1unknown_tick0100

Event 7 is the case implementers most often get wrong. The request is 30, the remaining supply is 10, the request does not exceed lim, so the event is valid and credits 10. It does not fail.

X. Transfer sequences

Start with address A holding 1000 available units of test.

X1: a transfer that settles
#EventA availableA reservedB availableStatus
0starting state100000-
1reveal at A: transfer amt=2507502500transfer_pending
2anchor {tx1}:0 spent, output 0 pays B7500250settled
3a second transaction also references {tx1}:07500250no event, already settled
X2: a transfer that returns
#EventA availableA reservedStatus
0starting state10000-
1reveal at A: transfer amt=250750250transfer_pending
2anchor spent, output 0 is an OP_RETURN10000invalid, invalid_transfer_destination
X3: rejected transfers
#EventResult
1reveal at A: transfer amt=2000 while A has 1000 availableinsufficient_available_balance
2one transaction whose inputs 0 and 1 both carry valid transfer leavesambiguous_transfer_anchor on both. They would claim the same anchor, so neither is applied.
3one transaction whose input 0 carries a transfer leaf and input 1 carries a mint leafThe transfer applies normally and the mint applies normally. Only competing transfers are ambiguous.
4a transfer whose reveal transaction has no output 0 addressinvalid_anchor
5at or above the configured activation height, a transfer whose transaction spends no other input with the same script as output 0missing_transfer_source_authorization

Reproducing these

Every leaf script above is a pure function of its payload and the x-only key. To reproduce V2 by hand:

  1. Serialize the payload as compact JSON in the required key order and encode it as UTF-8. That is 54 bytes.
  2. Take its SHA-256 digest: 3c0153…12e1.
  3. Concatenate: minimal push of bip110-op-drop, 75, minimal push of application/json, 75, minimal push of the 32-byte digest, 75, minimal push of the 54 payload bytes, 75, minimal push of the 32-byte key, ac.
  4. The result is 158 bytes and must equal the hex in V2 exactly.
  5. Build the tapleaf hash at version 0xc0, tweak the internal key with it as the sole leaf, and the output key is 9194a3…9d2c.

The builder performs steps 1 to 4 in your browser and shows each intermediate value.