2024.01 Vol.1

Bit of ordinals

Bitcoin was designed to be fungible: one bitcoin is the same as any other bitcoin no matter what. An example of fungibility is cash. People are generally willing to trade a $20 bill for any other $20 bill, it is not possible to somehow “taint” one bill and make it less valuable. This would make cash non-fungible. For something attempting to be currency, fungibility is important. If certain bills or bitcoin have different values, it would be really hard to use, defeating the whole purpose.

The bitcoin blockchain is public, so someone can (oh and they are) attempt “chain analysis” to determine if certain coins should be “tainted”. But even if a certain transaction is marked as “bad”, how are those coins going to be tracked? A bitcoin transaction has inputs and outputs, but no mapping of input coins to output coins. If a tainted coin enters a transaction are all other coins in the outputs now tainted in order to be sure? Seems like all coins will be tainted at some point if this is the case.

The fact that there is no input/output coin mapping builtin to the bitcoin protocol seems pretty important for fungibility. But that doesn’t stop anyone from defining a mapping outside of bitcoin. Which is exactly what ordinal theory does. Casey, the oridinal creator, describes ordinal theory as a “lens” to look at bitcoin and I think that is a great comparison. One can choose to look at bitcoin through this lens or not. Oridinal theory makes sats on the blockchain non-fungible since they are now mapped through transactions following some kinda arbitrary, but deterministic, rules. Sats can now have different values for users who care about oridinals.

What could give a sat more value than another? Casey gives one example in his blog how users might want to collect sats which “came” (through the lens of ordinal theory) from the genesis block. Another way is to “inscribe” some data on to a particular sat. This is where oridinals start to get controversial. Buying into oridinal theory doesn’t effect users who don’t buy in. However, inscribing data on to the blockchain does effect those who don’t buy in.

Bitcoin transaction scripts are designed to specify how bitcoin is locked. While Script is purposefully a very limited language so that is possible to statically analyze scripts, it has wiggle room on what data can go in these scripts. One opcode in particular, OP_RETURN, has a ton of history here.

Back in the early days (2013-ish) bitcoin users were already trying to put random data on the blockchain. This didn’t excite all users, so OP_RETURN was added as a middle ground to enable explicit data in a script: “Hey, this script always fails so don’t think much more on it! Also here are some random bytes”. Since the script always fails the UTXO can be pruned out of systems which only care about possible financial transactions. The bytes still end up in the blockchain and on hard drives around the world, but this is less of a performance burden than forever living in the hot, more resource hungry, UTXO set which is used to validate new transactions.

"vout" : [
    {
        "value" : 0.00000000,
        "n" : 0,
        "scriptPubKey" : {
            "asm" : "OP_RETURN 636861726c6579206c6f766573206865696469",
            "hex" : "6a13636861726c6579206c6f766573206865696469",
            "type" : "nulldata"
        }
    },
    {
        "value" : 0.00200000,
        "n" : 1,
        "scriptPubKey" : {
            "asm" : "OP_DUP OP_HASH160 b8268ce4d481413c4e848ff353cd16104291c45b OP_EQUALVERIFY OP_CHECKSIG",
            "hex" : "76a914b8268ce4d481413c4e848ff353cd16104291c45b88ac",
            "reqSigs" : 1,
            "type" : "pubkeyhash",
            "addresses" : [
                "1HnhWpkMHMjgt167kvgcPyurMmsCQ2WPgg"
            ]
        }
    }
],

You don’t necessarily have to burn bitcoin forever to inscribe data in the blockchain, shown here with a 0 value output

Bitcoin Core has a policy (“standardness rules”) to limit OP_RETURN to just 80 bytes of data. Bitcoin Core version 0.12.0 extended those policy restrictions: “There must still only be a single null data output and it must still pay exactly 0 satoshis”, I assume to stop users from adding a bunch of outputs which all use OP_RETURN? In any case, these are just policy rules, not consensus, so a user could go right to a miner and get some crazy transaction mined which is just a bunch of data. It would be expensive, but they could do it. It ain’t exactly easy though, which might explain why no big OP_RETURN usage has ever taken off. (Some recent spicy chatter on these rules, not sure why these policy ones get so many eyes since users can go around them…more to learn I guess)

So back to ordinal inscriptions, are they using OP_RETURN to inscribe data? Nope, inscriptions use an “envelope technique” which leverages some of the witness changes over the years. The unlock scripts (witnesses) were moved out of transaction storage object which allowed them to loosen a few restrictions and give a size discount to the data stored in the witness. As in, more data can be stored in the unlock script than the lock script. If you are looking to store random data in the blockchain, this is great news! But since the data is being stored in the unlock script instead of the output, a two step process is required to get the data “in the clear” on the blockchain. First, a “commit” transaction is created which pays to an output hash of a script which contains the data. Then a “reveal” transaction is used to unlock that output script and reveal the data onchain. So more complicated than a simple OP_RETURN in an output, but more storage.

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

The OP_FALSE and OP_IF make this script a no-op, but the data is onchain

The commit transaction’s locking script can be concatenated with any other normal locking script since the data inscription is just a no-op, like in this example reveal transaction.

This shift of the data to the input is clever, and dare I say, good? “Non financial” data is on the blockchain, which is frowned upon by some, but at least it is not in the UTXO set just chilling forever.

But it looks like other protocols have joined the ordinal party, like BRC-20 or STAMPS, that are causing more chaos. BRC-20 is a protocol that leverages the inscriptions’ protocol, slamming some JSON which describes a new token onto the blockchain and tying it to a sat. I think the main technical knock (other knocks include being totally scammy) against BRC-20 is that it generates a bunch of small UTXOs. I am not sure on the costs of that, but Casey has a proposal to address this technical shortcoming called Runes.

STAMPS (“Secure Tradeable Art Maintained Securely”) is worse. STAMPS are like inscriptions, but they don’t like how inscription data can be pruned out of the UTXO set so they have an explicit goal to get back in there. They don’t want to play nice and use OP_RETURN in the locking scripts, cause of the limiting policy rules. They just put as much data in the output as possible using bare 1-of-3 multisig, smashing the data into two of the signatures. I assume the last is a real sig for moving the bitcoin. This protocol is unfortunate because it puts pressure on the UTXO set, maybe causing some centralization if node runners give up.

I don’t think the answer to any of these “data on the blockchain” concerns is to attempt to filter them. Instead, we need to make the system more performant (like UTreeXO for the UTXO set) and transactions more “value dense” by sharing UTXOs (contracts and covenants). Performance keeps things distributed while dense transactions will price out (subjectively!) stupid shit.