Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is this a problem with ordinal numbering? #3690

Closed
sharphill2022 opened this issue Apr 25, 2024 · 19 comments
Closed

Is this a problem with ordinal numbering? #3690

sharphill2022 opened this issue Apr 25, 2024 · 19 comments

Comments

@sharphill2022
Copy link

sharphill2022 commented Apr 25, 2024

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
Copy link
Collaborator

casey commented Apr 26, 2024

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.

@casey casey closed this as completed Apr 26, 2024
@sharphill2022
Copy link
Author

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:

  •                    ->        110 (1000-1099, 190-199)
    

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:

  •                    ->        109 (1000-1099, 190-198)
    

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:

  •                    ->        109 (190-199, 1000-1098)
    

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
Copy link
Collaborator

casey commented Apr 26, 2024

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
Copy link
Author

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
Copy link
Collaborator

casey commented Apr 26, 2024

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
Copy link
Author

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
Copy link
Collaborator

casey commented Apr 26, 2024

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
Copy link
Author

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
Copy link
Author

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
Copy link
Collaborator

casey commented Apr 26, 2024

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
Copy link
Author

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
Copy link
Collaborator

casey commented Apr 26, 2024

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
Copy link
Author

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
Copy link
Author

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
Copy link
Author

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
Copy link

garyrob commented Apr 29, 2024

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
Copy link
Collaborator

casey commented Apr 29, 2024

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.

@garyrob
Copy link

garyrob commented Apr 29, 2024

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
Copy link
Collaborator

casey commented Apr 30, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants