ordinals / ord

👁‍🗨 Rare and exotic sats
https://ordinals.com
Creative Commons Zero v1.0 Universal
3.81k stars 1.35k forks source link

Is this a problem with ordinal numbering? #3690

Closed sharphill2022 closed 4 months ago

sharphill2022 commented 4 months ago

We discovered an ordinal number that is theoretically impossible. The specific questions are as follows:

For block height 626205, theoretically this block should receive a reward of 12.5 BTC. We calculate all the inputs and outputs of this block and get the result: Total number of satoshis output: 943528798853 Total number of satoshis entered: 942278798921 Subtract the two, the difference is: 1249999932 Theoretical reward: 1250000000 The difference between theory and practice: 68 According to Ordinals theory, the range of Satoshi rewarded at block height 626205 is: 1832756250000000-1832757499999999, Because 68 satoshis have not been claimed, the range of valid satoshis is only 1832757499999931. The last ordinal number of the block is 1832757499999999, which has no actual satoshi correspondence. However, now, this theoretically impossible Satoshi, ordinal number 1832757499999999, appears before our eyes (address: bc1qkwx5rhe946g9g2myj27nvx0nvdd36n5spcyfh6, UTXO: c50157dbc63666adebaa2a0e2c7625561f6a3b218159 44955a0fa43356c9ce83:0).

We found a problem in the code implementation of ord. Let’s take a look at how Satoshi transfers are tracked:

# assign ordinals in given block
def assign_ordinals(block):
   first = first_ordinal(block.height)
   last = first + subsidy(block.height)
   coinbase_ordinals = list(range(first, last))

   for transaction in block.transactions[1:]:
     ordinals = []
     for input in transaction.inputs:
       ordinals.extend(input.ordinals)

     for output in transaction.outputs:
       output.ordinals = ordinals[:output.value]
       del ordinals[:output.value]

     coinbase_ordinals.extend(ordinals)

   for output in block.transaction[0].outputs:
     output.ordinals = coinbase_ordinals[:output.value]
     del coinbase_ordinals[:output.value]

According to this satoshi transfer rule, if the reward of a block is smaller than the theoretical value, then coinbase_ordinals will not be empty after all the satoshis are finally distributed, which is the source of the lost satoshis. The code prioritizes the distribution of block rewards, which will result in some satoshis as TX inputs being eventually lost. This is probably a bug because if handled this way, the Satoshi may be destroyed. The correct way to handle this is to first allocate the satoshis of all TX inputs, and then allocate the rewarded satoshis last. In this way, even if the block reward is less, it can be considered that these Satoshis were not born, and the Satoshis that were already born will not be destroyed here, so there will be no conflict with the theory of BTC and Ordinals.

@Casey What’s your opinion?

casey commented 4 months ago

I don't think I see the issue. If a block underpays the block reward, that underpayment results first in the satoshis in any fees being destroyed, and if the block underpays enough, then some satoshis in the subsidy are destroyed. If block 626205 underpaid the reward, since it had fees, that underpayment first destroyed fees. Looking at mempool.space, the coinbase output received fees, so it did not underpay the reward enough to destroy subsidy sats. So it's expected that sat 1832757499999999 is still in circulation.

This is probably a bug because if handled this way, the Satoshi may be destroyed. The correct way to handle this is to first allocate the satoshis of all TX inputs, and then allocate the rewarded satoshis last.

I don't see why this is a bug. It seems pretty immaterial whether underpaying the reward destroys sats in the subsidy versus the fee, and the current implementation is consistent with the way that sats flow through transactions. The coinbase has an implicit input containing the subsidy, followed by implicit inputs containing the fees, in the order that they appear in the block. If this were reversed, with the implicit fee inputs being first, then the first sat of the block would not be on the first sat of the coinbase output, which doesn't seem nice. Underpaying the block reward could deduct from the subsidy satoshis first, but that would be inconsistent with how sat flow in transactions work, since underpaying in a normal transaction (i.e., paying fees) deducts from the last sats of the transaction.

I think that the implementation in ord and the python code are both consistent with each other.

Also, if you're curious, there's a bit of an easter egg. All sats destroyed this way are assigned to the null output, and can be viewed in the explorer.

sharphill2022 commented 4 months ago

Thank you very much for taking the time to respond. There might be some misunderstandings due to language descriptions, so I hope you can give me some more time to clarify this matter. To make the problem clearer based on what I have observed, I will use a simplified data model to illustrate the issue. Let's assume we have a block with 2 transactions. The first transaction is a reward transaction. Let's examine the details of the data.

TX1:

TX2:
100 (100-199) -> 90 (100-189)

If the block was supposed to receive a reward of 100 sat, assuming its ordinal number range is (1000-1099), then the transactions above are logically consistent with the ordinal allocation.

Suppose there is a problem with the mining software, and only 99 sat is claimed. According to the current ordinal allocation method, it would look like this:

TX1:

TX2:
100 (100-199) -> 90 (100-189)

It is evident that the existing 199 sat has disappeared! I believe this kind of disappearance is unreasonable, as existing satoshis should not vanish. A reasonable allocation scheme should be as follows:

TX1:

TX2:
100 (100-199) -> 90 (100-189)

This way, only the reward amount is reduced, and the existing satoshis will not disappear. This is what I see at block 626205. I'm wondering if your understanding aligns with mine.

casey commented 4 months ago

This ordering:

109 (190-199, 1000-1098)

Would cause rare sats, i.e., the first sat of the subsidy, to appear in the middle of the outputs of the coinbase transaction, instead of as the first sat of the coinbase transaction. This seems aesthetically and practically less than ideal. As is, when they're the first sat of the coinbase output, this allows miners to sequester new rare sats easily, simply by including a small output first in the coinbase output, which is nice.

sharphill2022 commented 4 months ago

I agree with your pursuit of aesthetics. But is it possible to calculate the actual number of rewards first and modify it like this: (1000-1098,190-199) This prevents existing satoshis from being lost.

casey commented 4 months ago

But this ordering:

1000-1098,190-199

Has the consistency problem that I mentioned above:

Underpaying the block reward could deduct from the subsidy satoshis first, but that would be inconsistent with how sat flow in transactions work, since underpaying in a normal transaction (i.e., paying fees) deducts from the last sats of the transaction.

When the sum of the value of the outputs of a normal transaction are less than the sum of the value of the inputs, that transaction is paying a fee, and that fee comes from the last satoshis in the inputs.

When the sum of the value of the outputs of a coinbase transaction are less than the sum of the value of the inputs, which in the case of the coinbase transaction, is one input for the subsidy, and then inputs for all the fees in the block, that underpayment comes from the last satoshis in the inputs.

In this way, paying a fee in a normal transaction and underpaying the block reward are handled consistently.

With this ordering:

1000-1098,190-199

They would be inconsistent, underpaying the block reward would come from sats in the middle of the input sats, not the last.

sharphill2022 commented 4 months ago

I understand your point now. This may be a matter of choice.

On one hand, there is the question of whether or not to guarantee the non-destructibility of satoshis. On the other hand, there is the need to ensure consistency in ordinals when processing inputs and outputs.

I would like to offer an idea: The first reward transaction has a special nature where the order of its inputs is not visible. While maintaining the order of all transaction fees is necessary, the order between transaction fees and rewards may not be as crucial. What do you think?

casey commented 4 months ago

I would like to offer an idea: The first reward transaction has a special nature where the order of its inputs is not visible. While maintaining the order of all transaction fees is necessary, the order between transaction fees and rewards may not be as crucial. What do you think?

I think changing them in this way would be a bit odd, just my personal opinion.

I'm curious, why would you prefer that existing satoshis be indestructible? A miner underpaying the block reward is a very uncommon occurrence, and it can only destroy satoshis which are spent to fees, which presumably aren't valuable to the user.

sharphill2022 commented 4 months ago

This might stem from my aesthetic pursuits, and the fact that BTC is non-destructible aligns well with my aesthetic values. When I first encountered the ordinals protocol, I was captivated by its simplicity and elegance. I believe that since satoshis are non-destructible, assigning a ordinal number to each satoshi through ordinals creates a permanent and unchanging record. Personally, I think these foundational principles are worth adhering to. Therefore, even in rare cases like this, I believe that maintaining the ordinal number of a satoshi is in line with the pursuit of simplicity as beauty.

sharphill2022 commented 4 months ago

I really hope that ordinals can guarantee these fundamental principles:

  1. Satoshis are only created, not destroyed.
  2. The ordinal number of a satoshi is assigned at its creation and remains permanently unchanged.

Aren't these the basic principles of the ordinals protocol? Could it be that my understanding of the ordinals protocol is incorrect?

casey commented 4 months ago

These are not basic principles of the protocol, and in fact, there is another way that satoshis can be destroyed. From the BIP:

If a transaction is mined with the same transaction ID as outputs currently in
the UTXO set, following the behavior of Bitcoin Core, the new transaction
outputs displace the older UTXO set entries, destroying the sats contained in
any unspent outputs of the first transaction. This rule is required to handle
the two pairs of mainnet transactions with duplicate transaction IDs, namely
the coinbase transactions of blocks 91812/91842, and 91722/91880, mined before
[https://github.com/bitcoin/bips/blob/master/bip-0034.mediawiki BIP-34] made
the creation of transactions with duplicate IDs impossible.

Ordinal numbers are indeed assigned when a satoshi is created, and remains permanently unchanged. When a satoshi is destroyed, its ordinal number is not reassigned or changed, it remains attached to that satoshi, even though it's destroyed.

sharphill2022 commented 4 months ago

I understand that BIP34 was designed to address the issue of duplicate transaction IDs, aiming to enhance the security and stability of the Bitcoin network. Additionally, in these two pairs of transactions, the sats contained within the UTXOs are not actually destroyed but rather, similar to OP_RETURN, they only are not unspent. Throughout Bitcoin's history, there has never been a case of "destroying the sats," as the sats always exist.

Since the ordinals protocol assigns numbers to sats and there is no scenario where sats are destroyed, the ordinal numbers should not be changed. Unless you can provide an example where sats are effectively destroyed.

We hope that the ordinals protocol will continue to improve, much like Bitcoin itself, with the introduction of BIPs to optimize and enhance it. We genuinely aspire for ordinals to align with these principles, which is why we have adopted the ordinals protocol and are working on its development.

casey commented 4 months ago

In both cases, duplicate TXIDs, which has happened twice, and underpaying the block reward, which has happened a few times, sats are definitely destroyed, and not unspendable, as they would be if they were sent to an OP_RETURN.

In Bitcoin Core, if you add up the value of all UTXOs including OP_RETURN UTXOs, it will reflect this, and be less than the total amount of bitcoin mined up to that point.

So for ordinal theory to match bitcoin, it must be possible to destroy sats.

sharphill2022 commented 4 months ago

These two situations have fundamental differences.

Whether it's duplicate TXIDs or block rewards, there is no possibility of sats completely disappearing. Sats may occasionally be underclaimed during reward distribution, but this should be considered as those sats not being born in the first place.

We have analyzed all the BTC mainnet data, including all sats, including those within OP_RETURN, and accounting for any underpaid block rewards. The total production aligns with the mining output of BTC without any issues. Both the technical theory of BTC and the practical mining history of BTC do not show any evidence of satoshis being destroyed in theory or practice. In reality, sats are only rendered temporarily unusable, such as being placed in OP_RETURN, but they cannot be destroyed.

If the ordinals protocol considers the underpaying reward blocks as a process of destroying satoshis, and this destruction implies a complete and permanent elimination, it differs from the actual behavior of BTC, making it difficult for others to comprehend. Why would we want to transform the process of a satoshi's creation into a process of its destruction? Wouldn't it be easier, simpler, and more understandable to avoid the destruction of satoshis altogether?

sharphill2022 commented 4 months ago

If the sats are sent to op_return, you think it is destroyed, but obviously, we can still see that these sats exist in this special utxo, but they can no longer be used. In a sense, it is destroyed, too. acceptable. Because of these sats we still know that it is locked in this utxo and know its ordinal range. But in the reward block, you think some sats were destroyed, but where are these destroyed sats? We can't see it. This is an unacceptable concept on the Bitcoin network.

This is a sats destruction event created by the ordinals protocol. In fact, no such event exists, and we believe that ordinals does not actually need this destruction event. Is there any special reason why a simple and beautiful protocol like the ordinals protocol should not follow the basic principles of Bitcoin and create the sats destruction event by itself?

sharphill2022 commented 4 months ago

In the Ordinals Theory Handbook, there is a passage that states:

"Individual satoshis can be inscribed with arbitrary content, creating unique Bitcoin-native digital artifacts that can be held in Bitcoin wallets and transferred using Bitcoin transactions. Inscriptions are as durable, immutable, secure, and decentralized as Bitcoin itself. Other, more unusual use-cases are possible: off-chain colored-coins, public key infrastructure with key rotation, a decentralized replacement for the DNS. For now though, such use-cases are speculative and exist only in the minds of fringe ordinal theorists."

It is evident that the content of the inscription is inscribed on the satoshi. If satoshis could be destroyed, how could the inscription be considered "durable" and "immutable"? Although the likelihood of such a scenario is low, as long as there is sufficient incentive, there will always be individuals looking for ways to engage in malicious activities. Why should we leave a potential loophole that allows miners to act as they please? If a miner sees enough benefit in destroying an ordinals NFT, it becomes a backdoor they can exploit.

garyrob commented 4 months ago

I am considering using Ordinal Theory for a project in which I do have to know that inscriptions are, in fact, durable and immutable, even against a motivated attacker. If ordinals don't actually work that way, I'll need to use a different mechanism. I'd prefer to use inscriptions because they are especially convenient.

casey commented 4 months ago

The only way for an inscription to be destroyed in the way that is being discussed here is:

This is not an "attack", because first the user has to fee-spend the inscription, which is under the user's control, and cannot be forced.

garyrob commented 4 months ago

The only way for an inscription to be destroyed in the way that is being discussed here is:

  • The user spends the inscription to a fee.
  • In the same block, the miner underpays the block reward enough to consume the sat of the fee-spent inscription. This is not an "attack", because first the user has to fee-spend the inscription, which is under the user's control, and cannot be forced.

Let me make sure I understand how this might apply to my particular project. I'd be inscribing some JSON and associating it with a satoshi so that it can be easily retrieved later by means of the satoshi.

Since the aim is for the JSON to be permanently available and easily retrievable, and would not need to be transferred to another user, there would be no more spending associated with the transaction that contains it.

So, the user (the entity doing the inscribing of JSON with that particular satoshi) wouldn't be spending the inscription to a free, so there is no risk of the satoshi disappearing. (At least as long as Bitcoin continues operating and Ordinal Theory is still used.) Is that correct?

casey commented 4 months ago

This is correct. And even if the sat is still spent as a few and then destroyed by underpaying the block reward, the JSON can still be retrieved by sat or by inscription ID. The sat is just immobile and not in any particular output.