What's the deal with taproot transactions storing so much data?

11 replies 160 views
coin_2013Member
Posts: 54 · Reputation: 198
#1Feb 5, 2024, 04:36 PM
I'm a bit confused about how ordinals can pack so much data on-chain. I get the whole ordinals envelope thing. 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 ordinals handbook says that "Hello, world!" is actually stored on-chain here. But I thought the taproot upgrade was just about letting people tweak the public key to embed a merkle root by modifying the address. Even so, the merkle root itself isn't really stored on-chain, right? You just need to know it to spend coins from that address, correct? I realize I'm missing something because if all you needed was the merkle root to spend coins from the script path, you wouldn't need to know the hash of the leaves. So can someone help me out here? I know bitcoin transactions have some scripting code in the hex of the transaction. Like, a basic locking script in a bitcoin output looks like this: "scriptPubKey": "OP_DUP OP_HASH160 HASH_OF_PUBKEY_IN_HEX OP_EQUALVERIFY OP_CHECKSIG". To spend that transaction, the person with the private key of the address in the UTXO needs to provide an unlocking script with their signature and public key. But this is just a tiny bit of data compared to how taproot lets you store way more. What's the trick?
5 Reply Quote Share
LuckyCoinLegendary
Posts: 832 · Reputation: 4795
#2Feb 5, 2024, 08:27 PM
As you can see in the script opcode, the push instructions are never evaluated. If they were, then all of these gigantic ordinals transactions would fail because they would overflow the stack. The manner in which the Ordinals transactions are spent is by using the conventional Schnorr signature directly, not any of the leaf evaluations. And also P2TR outputs do not count any sigops so its effectively limited only by block size, i.e. it's possible to fill an entire block with a large enough Ordinal.
0 Reply Quote Share
sage777Full Member
Posts: 102 · Reputation: 305
#3Feb 6, 2024, 08:19 PM
Look at this example: https://mempool.space/tx/0301e0480b374b32851a9462db29dc19fe830a7f7d7a88b81612b9d42099c0ae See? Everything is splitted just into 520-byte blocks. Tweaking the key is one thing. But how do you know, if the TapScript is valid or not? You have to see that. And Ordinals just abuse the fact, that the whole TapScript is always revealed. Which means, that even if there is a way to make things smaller, without sacrificing security, then still, people can choose the least optimal way, just because they can. For example: if you have a single public key, then you can use this script: "<pubkey> OP_CHECKSIG". It will be simple. But: anyone can abuse the Script, and instead write: "OP_2 OP_2 OP_ADD OP_4 OP_EQUALVERIFY <pubkey> OP_CHECKSIG". Then, this part "2+2=4" is useless, but it is still there, and it has to be revealed, if you want to spend by TapScript. Yes, but you don't have to pick the best way. Which means, that if you want to make a condition: "Alice or Bob can spend those coins", then you can create two branches: "<pubkeyAlice> OP_CHECKSIG" and "<pubkeyBob> OP_CHECKSIG". And then, you can reveal one of them. But: you can abuse the TapScript, and make a single branch with both conditions: "OP_IF <pubkeyAlice> OP_CHECKSIG OP_ELSE <pubkeyBob> OP_CHECKSIG OP_ENDIF". Then, everything will be always revealed, if you will spend by TapScript. You have to prove, that the revealed TapScript is committed to your address. Which means, that you provide some kind of SPV proof, similar to proving, that a given transaction is part of the block. And then, you reveal the whole TapScript in that leaf. Then, all comes into what users picked: they could for example always spend by public keys, and reveal their TapScripts outside Bitcoin. Or they could put their Ordinals into a separate leaf, which could begin with OP_RETURN, so it would be never pushed on-chain, but could be still committed to their address. So, to sum up, there are many ways to make the whole system secure, without pushing everything on-chain. But users just decided to put their data anyway, even if there is no need to do so. And also, for that reason, I think about making pubkey-only system, which could be resistant to that kind of attack. Or at least about making a lightweight node, which would only process signatures, without storing data, so it would be similar to OP_CHECKSIGFROMSTACK.
0 Reply Quote Share
coin_2013Member
Posts: 54 · Reputation: 198
#4Feb 8, 2024, 05:31 PM
Thank you very much for your answer. I think I'm starting to wrap my head around this better...  So when someone makes an ordinal they are not using tapscript right? They are simply writing Opcodes into the transaction just like you would with a non-taproot transaction?  If I did a typical P2PKH transaction I would put as my locking script, but If I wanted to do an ordinal I would make my locking script ? Does this mean that I could do an ordinal in a non-taproot address bitcoin transaction? So I could mint an ordinal with a P2PKH address?
6 Reply Quote Share
mike777Member
Posts: 44 · Reputation: 242
#5Feb 8, 2024, 11:17 PM
They do.  They wrap arbitrary data in a tapscript and inject it in the witness part of the transaction.  An ordinal specifically?  No, because the ordinal protocol relies on taproot, AFAIK.  However, arbitrary data?  Certainly.  You could achieve that by treating multiple P2PKH as 20-byte blocks.  I think you can achieve it with OP_RETURN too, but there are standardness limits.
3 Reply Quote Share
coin_2013Member
Posts: 54 · Reputation: 198
#6Feb 9, 2024, 04:28 AM
But I thought tapscripts only stored the merkle root on chain. Each one of the leafs gets collapsed down to a single hash (the merkle root) and that's the only thing that gets committed to the chain. Therefore, if you have a any data longer than a hash, it will vanish into the merkle root.  My above explanation could be wrong so please correct me if it's wrong.  Is that why you have to spend it in order to get the ordinal on chain? Does the committed ordinal data only exist in the proof that you provide?
4 Reply Quote Share
sage777Full Member
Posts: 102 · Reputation: 305
#7Feb 9, 2024, 05:57 AM
There are two things: sending to Taproot, and spending from Taproot. If you send your coins to Taproot, then you put only someone's public key. But: if you spend coins from Taproot, then you can spend by key, or by TapScript. If you spend by key, you provide a Schnorr signature, matching that public key from the address. But if you spend by TapScript, then you reveal some public key, and the whole TapScript leaf, along with the SPV proof, that it is a part of the tree. This is true if some leaf is unused. But if it is used, it has to be revealed. If you have a tree, you can have N leaves, but the problem is, that one of them has to be revealed, if you spend by TapScript. And that leaf can be as complex, as you want, taking for example almost 4 MB, because it is limited only by block size in consensus rules (there are more restrictions, like transaction size, but still, you can fill the whole block with something like 40 transactions, if you assume 100 kB per transaction). Yes, you reveal data in your input. It can exist anywhere, but people who created Ordinals, decided to put in on-chain. For example: Ordinals could work with any address type, if the commitment would refer to R-value of the signature. But: if you reveal it on-chain, then every full node is forced to store it. If you have this transaction 0301e0480b374b32851a9462db29dc19fe830a7f7d7a88b81612b9d42099c0ae, then it could contain only "8639eaab74c917a6385fd2932e2085dca8401c28b6bd506146ad4e552e229013" as some R-value in the on-chain signature, and it would be enough to see that "this image is connected with this address". But instead, everything is pushed on-chain, so each node is forced to process this almost 4 MB transaction.
3 Reply Quote Share
mike777Member
Posts: 44 · Reputation: 242
#8Feb 9, 2024, 09:16 AM
I think there might be a misunderstanding here, or perhaps I'm not following you correctly.  Ordinals require storing arbitrary data on-chain; that's essentially their purpose.  The main attraction is storing the image itself, unlike regular NFTs, where you typically only store a hash of the image and chain observers can verify the "ownership" of that image.  How can you store the entire image without forcing each node to process big transactions?
1 Reply Quote Share
sage777Full Member
Posts: 102 · Reputation: 305
#9Feb 9, 2024, 01:26 PM
You can just hide it in your signature. Here is how: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2023-November/022176.html Edit: Note that Ordinals do not enforce "ownership" in any way. If you post two identical NFTs, then there is no mechanism anywhere, to prevent claiming, that you are the real owner. Those pushes are just huge OP_NOPs, and there are no consensus rules, which could bring "real NFTs" here. Because if those creators would really want to make NFTs, then they would use some sidechain to do that.
3 Reply Quote Share
mike777Member
Posts: 44 · Reputation: 242
#10Feb 9, 2024, 07:40 PM
How can you obtain the data solely from R?  You're appending a hash to r0, but you're unable to reverse the hash to retrieve the data.  Essentially, this is akin to having only OP_RETURN data. I haven't delved into their protocol because, frankly, I find it uninteresting—it's just another valueless scheme.  What I meant to convey is that observers can confirm whether the image data requested matches with the OP_PUSHed bytes.
3 Reply Quote Share
sage777Full Member
Posts: 102 · Reputation: 305
#11Feb 9, 2024, 09:45 PM
You push it into your own network, as each honest altcoin do. This is better, because then nobody knows, if your transaction has any commitment or not. You have just a regular signature (with any address type you want, including P2PK), and people can find out, that something is hidden behind it, only when you reveal that information. Which means, that you can also make private inscriptions. And all of that is also timestamped on-chain, which means, that it is covered with Proof of Work, as every other timestamped document. You can do the same with R-value commitments. The difference is that you don't have to push your data on-chain.
4 Reply Quote Share
mike777Member
Posts: 44 · Reputation: 242
#12Feb 10, 2024, 01:33 AM
This is the response I expected.  Your model operates effectively when there's an alternative chain, such as a sidechain, that retains the image data.  However, Ordinals doesn't operate on that premise.  The fundamental concept of Ordinals is that they're stored on the main chain—not a flaw but a deliberate design choice.  This distinction is clear.  No other chain can ensure the same long-term sustainability as Bitcoin's main chain. I understand that it may seem illogical, but most people make financial decisions based on emotions.  By adopting your approach, you're compromising the core aspect of Ordinals that sets it apart from other (meaningless) tokens.
4 Reply Quote Share
?Reply
Sign in to reply to this topic

Related topics