Guide · for people making one
Create a Drop
Six steps, each of which you can check before the next. The transaction structure is ordinary Taproot; the only Drops-specific work is assembling the leaf correctly and keeping the commit output safe until you reveal.
Bitcoin transactions are difficult to reverse. Rehearse on signet or regtest first. Review the body, the network, the destination and the fee in a wallet you trust before signing anything. No Drops interface ever needs your seed phrase or private key. This page is a protocol walkthrough, not a wallet.
1. Decide what the artifact is
You have 256 bytes. Choose between putting the content itself on chain, or putting a content-addressed pointer to it on chain. Those are different promises, and the choice is permanent.
| If you want | Put in the body | What Bitcoin then proves |
|---|---|---|
| The content itself to be permanent | The content, under 256 bytes | These exact bytes were committed at this height. |
| A large file to be pinned | A hash or content-addressed URI of it | This exact reference was committed. Retrieval is your problem, not Bitcoin's. |
| An agreement to be recorded | A Pact Seed or a Pacts reference | These terms, this ruleset, this enforcement floor. |
Pick the content type at the same time. It is part of the leaf and cannot be corrected later. Lowercase, no parameters, at most 80 bytes.
2. Build the leaf
Five pushes, each with its minimal opcode, in fixed order.
body = utf8("hello drops") # 11 bytes
bodyHash = SHA256(body) # 32 bytes, single pass
marker = ascii("drops") # or "drops-pact"
mime = ascii("text/plain")
leaf = push(marker) || OP_DROP
|| push(mime) || OP_DROP
|| push(bodyHash) || OP_DROP
|| push(body) || OP_DROP
|| push(pubkey) || OP_CHECKSIG
Where push(x) is the minimal encoding: the bare length byte for 1 to 75 bytes, OP_PUSHDATA1 for 76 to 255, and OP_PUSHDATA2 for exactly 256. Two body values have no minimal push at all and must be avoided: the single byte 0x81, and any single byte from 0x01 to 0x10.
The public key is the x-only key that will sign the reveal. Paste your assembled leaf into the decoder before you go any further. It will tell you if any field is wrong while it is still free to fix.
3. Commit to it
leafHash = taggedHash("TapLeaf", 0xc0 || compactSize(len(leaf)) || leaf)
merkleRoot = leafHash # single-leaf tree
tweak = taggedHash("TapTweak", internalKey || merkleRoot)
Q = internalKey + tweak*G
commitOutputScript = OP_1 || push32(xOnly(Q)) # 34 bytes
Send a funding transaction to that output. Give it enough value to cover the reveal fee plus the amount the artifact will carry, because the reveal spends this output and its own output 0 becomes the artifact's custody outpoint.
The leaf may sit anywhere in a larger script tree if you want other spending paths alongside it; fold the sibling hashes into the merkle root in the usual way and include them in the control block. A single-leaf tree is the simplest and gives a 33-byte control block.
4. Reveal it
Spend the commit output on the script path. The input witness has exactly three items and nothing else.
witness = [
schnorrSignature, # 64 bytes, or 65 with an explicit sighash byte
leaf, # the script from step 2
controlBlock # (0xc0 | parity(Q)) || internalKey || merklePath
]
The low bit of the control block's first byte is the parity of Q, not a flag you choose. And there must be no annex: a fourth witness item starting with 0x50 disqualifies the input entirely.
Output 0 of this transaction is the artifact's first custody outpoint, so send it to an address you control. It must be P2WPKH or P2TR with a positive value, or the artifact is recorded as burned the moment it appears.
5. Wait
Nothing exists until the reveal confirms deeply enough. On mainnet that means at least six confirmations, roughly an hour, and a given indexer may be configured deeper. There is no mempool view for Drops artifacts: an unconfirmed reveal is not a pending Drop, it is nothing.
6. Check the result
Your artifact's identity is fixed by the reveal, so you can write it down before it is recorded:
drops:mainnet:<reveal-txid>:d<index of the input you revealed on>
Then confirm the record independently: fetch it from an indexer, fetch its body, and check that SHA-256 of the returned body equals the bodySha256 field and equals the hash you put in the leaf. If those three agree, the record is what you made. See the API reference for the endpoints and the integration guide for doing this in code.
Mistakes that cost a transaction
- Wrong hash, wrong content type case, a parameter in the content type, a non-minimal push. All caught by the decoder.
- A body value with no minimal encoding.
- A public key that is 32 bytes but not on the curve.
- Wrong body, wrong content type, wrong marker. The record is permanent and there is no revision mechanism.
- Output 0 sent to an unsupported script or a zero value: the artifact is recorded as
burnedat birth. - Revealing on the wrong network. A signet Drop is not a mainnet Drop and never becomes one.
Rehearsing the whole flow on regtest costs nothing and catches all of these.