Currently on the mainnet there are multiple cases of the same transaction hash included in different block numbers.
The content of the transaction does not appear to be the same in all the clashing cases, as an example consider:
7dcdcdb558028c7703faddee96e1aa48e9bbe7cd3a07cd0a74513a3599185b40, in this case the content of the transaction seems to be the same.0bd119c4fea6a1147b0eb6cfab1363c1c83b12eaab466fae35b74906d4cf69bc, in this case the content of the transaction seems to be different.I would like to add onto that:
There are currently multiple transaction hash collisions in consecutive blocks in EOS as noted below:
7dcdcdb558028c7703faddee96e1aa48e9bbe7cd3a07cd0a74513a3599185b40 at block 10712420 and 1071242123361432428f9fdf3f6c2d567b1742e365016d44866f41fceac41962855788ef at block 12587093 and 1258709412e1ff77c2353e6c6aedbfdbc553d5ef37795060bc950ba5ae3184309d3f8008 at block 13669127 and 1366912858fd855c2351c07daefb947fd8996381ae10b788812bea903ceffa668a451112 at block 13669235 and 136692361d3c6d1db78b1c76b5aedd75c5825fac2a2a81dddfaa29966fd4f6a1afa56fd1 at block 15717258 and 157172591109ca2314426f745f378d3ae7384c859e9a60b8b254ab87e0ad6c41b444d8ed at block 19109823 and 191098242fc89e92e8e5230d18e3611ed37bf628db94463d9ad62be1e763111bf2ad1cc6 at block 19656619 and 196566206a94a62c6467de6392bb7a6b2106d84414c1fcaaa8e1bc47b053e8213f422f73 at block 22037546 and 22037547Using the Trace API, we have found in the case of the above 8 collisions, the transactions to be exactly the same in the consecutive blocks with the only difference being CPU and NET usage.
However, in the following two transaction hash collisions in consecutive blocks, the transactions are not exactly the same and have different set of eosio.token transfers associated with them:
0bd119c4fea6a1147b0eb6cfab1363c1c83b12eaab466fae35b74906d4cf69bc at block 24301274 and 24301275f0da5255676a1789b617fad1cd1940eba308d89013d03b963ecf6bbda5931288 at block 24305245 and 24305246We're sure we'll find more collisions as we progress through the chain.
Are these transaction hash collisions a feature or a bug? And are they resolved later in the chain? And what is the feature/bug that is causing them?
Pinging @johndebord @larryk85 @lparisc @heifner, any thoughts on this? 🙏
@alexprut @rajathchain those are deferred TXs. The scheduling appears in one block and the execution in the later block
This should be fixed by the patch in issue #6115. As far as we know this fix hasn't been deployed on the EOS network, but if that's not the case please let me know.
@jafri @aclark-b1 thanks for looking into this, a few follow-up questions:
delayed?@alexprut
- Is there any extensive documentation that explains this type of Tx behaviour (without looking into the code)? I was looking at https://developers.eos.io/manuals/eosio.cdt/v1.7/best-practices/deferred_transactions but there is not much.
Not at this time, we can look into documenting it further in the future. While this behavior is allowed by the protocol prior to deployment of NO_DUPLICATE_DEFERRED_ID released in v1.8.0, the conditions for its appearance were also mitigated in the v1.8.0 release. Seeing recent incidences implies that there is a block-signing node running custom code or code prior to v1.8.0 (which is rare due to other activated protocol features in most networks).
- According to https://developers.eos.io/welcome/latest/protocol/transactions_protocol/#transaction_receipt-schema, shouldn't the transaction status be
delayed?
No, delayed transactions are distinct from deferred transactions and this only occurs with deferred transactions. Delayed transactions are explicitly constructed and signed by a user but contain a delay to meet authorization requirements. Deferred transactions are implicitly created as a result of contract execution.
I will file an issue to get the ambiguity in those documents corrected.
It is worth noting that seeing these transactions with same IDs and a status of executed does mean that the contents of the transaction were executed each time. Even though the IDs are the same, each of these executions was individually authorized and scheduled by the source contract so _there is no accidental duplication of actions_.
- Currently there is a pattern, i.e. all the clashing tx hashes are included in the immediate successive block, is this done intentionally by design or it's just a coincidence?
This is not intentional however, it is a hallmark of the conditions that create these transactions with the protocol AND the officially released code prior to v1.8.0. Technically the protocol allows any number of duplicate IDs _in the same block_ using this code path followed by at-most 1 duplicate ID in the following block. However, the code prior to v1.8.0 limited this to exactly 1 and 1 outside of the protocol.
Again, after v1.8.0 this should be functionally impossible to achieve and with the optional deployment of NO_DUPLICATE_DEFERRED_ID it will be impossible at the protocol layer.
@b1bart this is super helpful, thanks for answering! At this point, should we leave the issue open or it makes sense to close it?
@alexprut Let's keep it open until EOSIO/eosio.cdt#971 is addressed. @iamveritas
Most helpful comment
@alexprut
Not at this time, we can look into documenting it further in the future. While this behavior is allowed by the protocol prior to deployment of
NO_DUPLICATE_DEFERRED_IDreleased inv1.8.0, the conditions for its appearance were also mitigated in thev1.8.0release. Seeing recent incidences implies that there is a block-signing node running custom code or code prior tov1.8.0(which is rare due to other activated protocol features in most networks).No, delayed transactions are distinct from deferred transactions and this only occurs with deferred transactions. Delayed transactions are explicitly constructed and signed by a user but contain a delay to meet authorization requirements. Deferred transactions are implicitly created as a result of contract execution.
I will file an issue to get the ambiguity in those documents corrected.
It is worth noting that seeing these transactions with same IDs and a status of
executeddoes mean that the contents of the transaction were executed each time. Even though the IDs are the same, each of these executions was individually authorized and scheduled by the source contract so _there is no accidental duplication of actions_.This is not intentional however, it is a hallmark of the conditions that create these transactions with the protocol AND the officially released code prior to
v1.8.0. Technically the protocol allows any number of duplicate IDs _in the same block_ using this code path followed by at-most 1 duplicate ID in the following block. However, the code prior tov1.8.0limited this to exactly 1 and 1 outside of the protocol.Again, after
v1.8.0this should be functionally impossible to achieve and with the optional deployment ofNO_DUPLICATE_DEFERRED_IDit will be impossible at the protocol layer.