Drops Protocol documentation

Normative · revision 2026-09-01

Drops specification

This page is the normative description of a Drop: the exact script a Drops leaf must be, the exact commitment it must satisfy, the identity it receives, and the conditions under which a candidate is not a Drop at all.

1. Scope and status

Drops is an original Bitcoin Universe application protocol. It defines how a compact media artifact, or a Drop Pact record, is committed to Bitcoin inside a Taproot script-path spend and how an indexer decides whether that commitment counts.

This document describes the behaviour implemented by the Bitcoin Universe reference indexer for Drops and OP_DROP. Where the reference implementation makes a choice that another implementation could reasonably make differently, this document says so.

Status of this specification
ProtocolDrops (application layer)
CarrierOP_DROP Tapscript leaf, Tapleaf version 0xc0
ChainBitcoin
Networksmainnet, testnet, signet, regtest
Lifecyclestable
AvailabilityFeature-gated in Bitcoin Universe products. See what that means.
Document revision2026-09-01

2. Conventions

The words must and must not mark an absolute requirement. A candidate that violates one is not a Drop and is not recorded. should marks a strong recommendation for producers. may marks a genuine option.

Byte lengths are exact. Hexadecimal is lowercase unless a rule says otherwise. SHA256 means one single pass of SHA-256 over the raw bytes, not a double hash.

3. The Drops leaf

A Drop lives in exactly one Tapscript leaf. The leaf is a fixed sequence of five data pushes, each of the first four consumed by OP_DROP, with the fifth push spent by OP_CHECKSIG.

PUSH <marker>         OP_DROP
PUSH <content type>   OP_DROP
PUSH SHA256(body)     OP_DROP
PUSH <body>           OP_DROP
PUSH <x-only pubkey>  OP_CHECKSIG
Byte layout of a Drops Tapscript leaf Five rows. Row one, marker, one to eleven bytes, followed by OP_DROP. Row two, content type, one to eighty bytes, followed by OP_DROP. Row three, SHA-256 of the body, exactly thirty-two bytes, followed by OP_DROP. Row four, body, one to two hundred and fifty-six bytes, followed by OP_DROP. Row five, x-only public key, exactly thirty-two bytes, followed by OP_CHECKSIG. A bracket on the right shows that rows three and four are bound together because the hash must equal SHA-256 of the body. marker 1 to 11 bytes · drops or drops-pact OP_DROP content type 1 to 80 bytes · lowercase type/subtype OP_DROP SHA256(body) exactly 32 bytes OP_DROP body 1 to 256 bytes OP_DROP x-only public key exactly 32 bytes, a valid curve point OP_CHECKSIG BOUND hash must equal SHA256 of the body Total decompiled chunks: exactly 10. Five data pushes at even positions, five opcodes at odd positions. Any extra chunk, missing chunk, reordering or trailing byte makes the script something other than a Drop.
The leaf is a shape, not a search pattern. A parser that greps a transaction for the string drops has not read this specification.

3.1 Leaf structure rules

  1. D-1

    A Drops leaf must decompile to exactly ten chunks: data pushes at positions 0, 2, 4, 6 and 8, opcodes at positions 1, 3, 5, 7 and 9.

  2. D-2

    The opcodes must be OP_DROP, OP_DROP, OP_DROP, OP_DROP, OP_CHECKSIG in that order.

  3. D-3

    Every one of the five fields must be a data push. An opcode that produces a value, such as OP_1 or OP_1NEGATE, is not a data push and does not satisfy any field.

  4. D-4

    Every push must use the minimal encoding for its length. Re-serializing the parsed fields must reproduce the leaf script byte for byte.

  5. D-5

    The Tapleaf version must be 0xc0. No other leaf version is accepted.

3.2 Marker

  1. D-6

    The marker must be exactly one of two ASCII strings: drops for an artifact, or drops-pact for a Pact Seed record.

  2. D-7

    The OP_DROP carrier marker 6269703131302d6f702d64726f70 (OP_DROP marker hex) uses the same five-field shape but must not be accepted as a Drop. Markers are namespaces, not decoration. See the marker registry.

3.3 Content type

  1. D-8

    The content type must match ^[a-z0-9][a-z0-9!#$&^_.+-]*\/[a-z0-9][a-z0-9!#$&^_.+-]*$. This is the RFC 6838 restricted-name grammar, lowercased.

  2. D-9

    The content type must be at most 80 bytes and must be pure ASCII.

  3. D-10

    Parameters must not appear. text/plain; charset=utf-8 is invalid; text/plain is valid. Uppercase is invalid: TEXT/plain is rejected.

  4. D-11

    There is no allowlist of media types at the protocol layer. image/svg+xml is a valid Drops content type. How a serving implementation renders it is a separate, deliberately narrower policy: see artifact serving.

3.4 Body hash

  1. D-12

    The hash field must be exactly 32 bytes.

  2. D-13

    The hash field must equal SHA256(body) computed over the raw body push bytes, single pass.

3.5 Body

  1. D-14

    The body must be one push of 1 to 256 bytes. An empty body is invalid.

  2. D-15

    A one-byte body whose single byte is 0x81, or in the range 0x01 to 0x10, must be rejected. Those values have no minimal data-push encoding, because Bitcoin Script folds them into OP_1NEGATE and OP_1 through OP_16. A one-byte body of 0x00 is valid.

  3. D-16

    The body is opaque bytes. The protocol assigns it no structure beyond the declared content type. Two application profiles do define structure inside the body: Pact Seed and Pacts reference.

  4. D-17

    Content larger than 256 bytes should be referenced by an explicit content-addressed pointer inside the body, never implied by convention.

3.6 Creator key

  1. D-18

    The final push must be a 32-byte x-only secp256k1 public key.

  2. D-19

    The key must be a valid point on the curve. A length check alone is not sufficient; an implementation must perform point validation.

  3. D-20

    The creator key is the key that OP_CHECKSIG checks the reveal signature against. It is a claim by the spender, not an attestation of authorship by anyone else.

4. Taproot commitment

The leaf is only meaningful if the Taproot output that was spent actually committed to it. This is the step that separates Drops from formats that trust whatever a witness happens to contain.

  1. D-21

    The spent previous output must be a native P2TR script: exactly 34 bytes, 0x51 0x20 followed by the 32-byte output key.

  2. D-22

    The control block length must be at least 33 bytes, and (length - 33) must be a multiple of 32.

  3. D-23

    The merkle path may contain up to 128 hashes. The Drops leaf is permitted to sit anywhere in a Taproot script tree; it does not have to be the only leaf.

  4. D-24

    controlBlock[0] & 0xfe must equal 0xc0.

  5. D-25

    The internal key, bytes 1 through 32 of the control block, must be a valid x-only point.

  6. D-26

    The tapleaf hash must be computed as taggedHash("TapLeaf", leafVersion || compactSize(len(script)) || script), folded up the merkle path with taggedHash("TapBranch", min(a,b) || max(a,b)), then tweaked with taggedHash("TapTweak", internalKey || merkleRoot).

  7. D-27

    The resulting output key parity must equal controlBlock[0] & 1, and the resulting x-only key must equal the 32 bytes of the spent P2TR script.

  8. D-28

    Any error raised while performing these steps must be treated as failure to verify, never as success.

Tagged hashing throughout is SHA256(SHA256(tag) || SHA256(tag) || data), as defined by BIP 340 and BIP 341.

4.1 Witness shape

  1. D-29

    The reveal input witness must contain exactly three items: a Schnorr signature, the leaf script, and the control block.

  2. D-30

    The signature item must be 64 or 65 bytes. A 65-byte signature carries an explicit sighash byte.

  3. D-31

    A Taproot annex must not be present. An annex is recognised by a final witness item whose first byte is 0x50.

  4. D-32

    Every witness item must be an even-length hexadecimal string when read from a node's transaction representation.

5. Identity

drops:<network>:<reveal-txid>:d<reveal-input-index>
  1. D-33

    A Drop's identity must be derived from the input that revealed it, not from an output. One transaction with two Drops-revealing inputs produces two distinct Drops.

  2. D-34

    The transaction id must be lowercase hex, 64 characters.

  3. D-35

    The input index must be written without leading zeros. d0 and d3 are valid; d01 is not.

  4. D-36

    The accepting form is ^drops:([a-z]+):([0-9a-fA-F]{64}):d(0|[1-9][0-9]*)$. An implementation should accept mixed-case transaction ids on input and must emit lowercase.

  5. D-37

    The network segment must match the network the reading implementation is indexing. A mainnet indexer must not resolve a drops:signet: identity.

5.1 Derived labels

Labels an implementation derives, and what they are for
LabelDerivationStatus
dropmarkFirst 10 hex characters of the body SHA-256, uppercased. Matches ^[0-9A-F]{10}$.Decorative. Never an identity.
sequenceZero-based, network-scoped ordering counter assigned by the indexer.Presentation only. Must not replace the Drop identity.
displayNameIndexer-local, for example Drop #42.Presentation only.
Do not key on presentation fields

Two indexers that started scanning at different heights will disagree about sequence and displayName. They will agree about the Drop identity, because it comes from the chain.

6. Operations and state

Drops has no deploy or mint step. There are exactly two on-chain operations: revealing an artifact, and moving the custody of one that already exists.

6.1 Reveal

  1. D-38

    A reveal is a confirmed transaction input that spends a P2TR output on the script path and satisfies every rule in sections 3 and 4.

  2. D-39

    The initial owner of the artifact is the address of the reveal transaction's output 0.

  3. D-40

    An artifact must only be recorded once its reveal transaction is at the implementation's configured confirmation depth. See confirmation policy.

6.2 Custody transitions

Custody follows the profile drops-custody-v1. The rule is deliberately narrow so that custody is never ambiguous.

Drops custody state transitions A recorded artifact begins in the active state holding a custody outpoint at output zero of its reveal transaction. Spending that outpoint moves custody to output zero of the spending transaction and the artifact stays active, provided output zero is a pay to witness public key hash or pay to Taproot output with a positive value. If output zero does not satisfy that test the artifact moves to the burned state, which is terminal. Records whose custody chain the projection cannot resolve are recorded as legacy unresolved. active holds one custody outpoint spend output 0 to a P2WPKH or P2TR output with a positive value: custody moves, still active spend output 0 to anything else (no address, zero value, other script) burned terminal legacy_unresolved custody chain not resolvable by the projection Successor output index is always 0. No later output, change output, or witness-derived address can take custody. Custody projection version 1. The projection is rebuilt from immutable rows after a chain reorganisation.
Custody is an output-zero rule, on purpose. Ambiguity about which output holds an artifact is the failure mode this design refuses.
  1. D-41

    The custody outpoint of a newly recorded artifact must be output 0 of its reveal transaction.

  2. D-42

    When the custody outpoint is spent, custody must move to output 0 of the spending transaction, and only output 0.

  3. D-43

    A successor output is supported only if it has a resolvable address, a script hex, a value greater than zero satoshis, and a script matching ^0014[0-9a-f]{40}$ (P2WPKH) or ^5120[0-9a-f]{64}$ (P2TR).

  4. D-44

    If the successor output is not supported, the artifact's custody status must become burned. The record itself remains; only its custody ends.

  5. D-45

    Custody status must be one of active, burned, or legacy_unresolved. The last is recorded when the projection cannot resolve a custody chain, for example for a record predating the custody activation height of that deployment.

  6. D-46

    Custody is a projection over confirmed history. After a chain reorganisation it must be rebuilt from the surviving immutable records rather than patched.

7. Invalid conditions

Every condition below means the candidate is not a Drop. There is no partial acceptance and no repair. The reference implementation raises the message shown; the messages are stable enough to use as diagnostic keys.

Leaf and field rejections
ConditionRejection reasonRule
Chunk count is not 10, or decompilation failedDrops leaf must contain exactly five pushes and five opcodes.D-1
A field position holds an opcode rather than a data pushThe named field is not a data pushD-3
Opcode at an odd position is not the required oneDrops leaf does not use the required OP_DROP/OP_CHECKSIG grammar.D-2
Marker is neither drops nor drops-pactDrops leaf has an unknown marker.D-6, D-7
Content type fails the grammar or exceeds 80 bytesDrops MIME type must be lowercase ASCII type/subtype with no parameters and at most 80 bytes.D-8, D-9, D-10
Content type contains non-ASCII bytesDrops MIME type must be ASCII.D-9
Hash field is not 32 bytesDrops leaf sha256 field must be exactly 32 bytes.D-12
Body length is 0 or above 256Drops body must be one push of 1 to 256 bytes.D-14
One-byte body with no minimal push encodingThe body has no minimal data-push encodingD-15
Hash field does not equal SHA256 of the bodyDrops leaf sha256 does not match its body.D-13
Final push is not a valid x-only pointDrops leaf requires a valid 32-byte x-only secp256k1 public key.D-18, D-19
Re-serialization does not reproduce the scriptA push does not use its minimal encodingD-4
Taproot commitment rejections
ConditionRejection reasonRule
Leaf script is not a valid Drops leafThe leaf failed section 3D-1 to D-20
Spent output is not native P2TRprevious output is not P2TRD-21
Control block length or path length is wronginvalid Taproot control block structureD-22, D-23
Leaf version byte is not 0xc0unsupported Taproot leaf versionD-5, D-24
Internal key is not a curve pointinvalid Taproot internal keyD-25
Output key parity disagrees with the control blockTaproot control block parity mismatchD-27
Recomputed output key differs from the spent scriptTaproot leaf does not commit to previous outputD-27
Verification raised an errorTaproot commitment could not be verifiedD-28
The spent output could not be fetchedmissing_previous_outputD-21

Test vectors gives concrete valid and invalid inputs for these conditions. Validation and indexing covers the order in which a conforming implementation performs the checks, and what it does about confirmations and reorganisations.

8. Versioning and change policy

  1. D-47

    The leaf grammar carries no version field. A change to the grammar would be a new marker, not a new version byte inside the existing one.

  2. D-48

    A confirmed Drop keeps the meaning it had when it was created. A later revision of this document must not retroactively invalidate a record that was valid under the rules in force at its confirmation height.

  3. D-49

    Deployment-scoped activation heights, such as the height at which custody projection becomes authoritative, are operator configuration rather than protocol constants. Two deployments may differ, and an implementation should publish the heights it uses.

Document revisions are listed in the version history.