Table of Contents
"Ordinal Inscription" is essentially a 2-step protocol:
- It defines a "Ordinal Theory" which defines an order for each satosh of utxo.
- Satoshis are numbered in the order in which they're mined, and transferred from transaction inputs to transaction outputs first-in-first-out.
- It defines an "inscription protocol" which allows inscribe a utxo satosh with arbitrary content, and the inscription can be transfered by transfering the corresponding satosh.
- The inscription content is stored in taproot1 script-path spend scripts, thus inscriptions are made using a two-phase commit/reveal procedure.
Now let's go through the details of the above mentioned "Ordinal Theory" and "inscription protocol".
It's implemented at both tx level and block level.
- At tx level, the main logic is in
index_transaction_sats
.- Each tx input contains precomputed sat ranges, the
input_sat_ranges
are assigned to outputs first-in-first-out, the sat ranges assigned to each output are stored to serve as precomputed sat ranges when spent as tx input.
- Each tx input contains precomputed sat ranges, the
- At block level: tx fees are appended to the tail of coinbase input sat ranges, burned sats are assigned to
null
output, thusindex_transaction_sats
is first applied on normal transactions, then applied on coinbase tx.
The overall process is essentially very similar to index_transaction_sats
, the main difference is:
- At tx level, the role of
input_sat_ranges
forindex_transaction_sats
is taken byfloating_inscriptions
instead, which contains both previously inscribed inscriptions and inscriptions being inscribed. - At block level, inscriptions on tx fee sats are saved in the
flotsam
field, and later appended to the tail offloating_inscriptions
for coinbase tx, inscriptions on burned sats are assigned to the corresponding sat point of the null output.
In order to inscribe an inscription on a specific tx input, just ensure the serialized inscription content is contained within the witness tapscript. By default the inscription is inscribed on the first sat of its input, unless it has a pointer tag specified to explicitly change the position.
Inscription content is serialized using data pushes within unexecuted conditionals of tapscript, called "envelopes". Envelopes consist of an OP_FALSE
OP_IF
… OP_ENDIF
wrapping any number of data pushes.
A text inscription containing the string "Hello, world!" is serialized as follows:
OP_FALSE
OP_IF
OP_PUSH "ord"
OP_PUSH 1
OP_PUSH "text/plain;charset=utf-8"
OP_PUSH 0
OP_PUSH "Hello, world!"
OP_ENDIF
First the string ord
is pushed, to disambiguate inscriptions from other uses of envelopes, checked here.
OP_PUSH 1
encodes the content type tag, which indicates that the next push contains the content type, and OP_PUSH 0
indicates that subsequent data pushes contain the content itself.
The general process for serializing inscription content is: first the tag part is serialized as tag_id/value pairs, then the body part is serialized as OP_PUSH 0
followed by data pushes. A complete list of valid tags can be checked here, with explanations here.
Follow the ord wallet inscribe
command here to inscribe an inscription to some destination address.
Basically users only need to specify the fee rate, the inscription content, the destination address and the optional sat point, then create_batch_inscription_transactions
will finally be called to generate proper commit/reveal transactions, tweaked BIP-340 recovery key for tapscript.
Follow the ord wallet send
command here to send inscription to some destination address.
Basically users only need to specify the fee rate, the inscription id, the destination address and the postage to include with the sent inscription, then create_unsigned_send_satpoint_transaction
will be called to generate a single tx that transfers the target sat point to the destination address.
Footnotes
-
This post assumes knowledge of the Bitcoin taproot. ↩