Repository navigation
Conversation
…sh,Number}AndIndex In hl-node-compliant mode, eth_getBlockBy*, receipts, logs and tx counts hide system txs, but the by-index transaction lookups indexed the full block. Index N therefore returned a different tx than the block lists at position N (and than hl-node returns), often a system tx. Shift the requested index by the block's system tx count, and shift transactionIndex in the response back. Block tags are resolved to a number first so the count and the lookup refer to the same block. Non-compliant mode is unchanged.
75057da to
5de251b
Compare
|
Resolving If the two lookups can observe different canonical snapshots during a reorg, consider this regression case: header A at height N has one system tx; N is replaced by B with two before the lookup. Compliant index 0 is mapped using A’s count to full index 1, which on B is still a system tx. Both the structured and raw number-based methods need to keep the count and transaction tied to the same block. Carrying the resolved hash into a by-hash lookup, or rejecting/retrying a changed identity, would cover that case. This is a source-review scenario, not a reproduced node reorg or a claim about the live validation reported above. |
The system tx count and the transaction now always come from the same block, even if the block at that height changed between the two lookups.
|
Good point, thanks. HyperEVM blocks are final, so I don’t expect this to happen in practice, but it’s cheap to rule out. In d46f5cb the by-number handlers resolve the block once to its hash plus system tx count (sealed_header_by_id), then do the lookup by hash. The count and the transaction now always come from the same block, and the by-number methods go through the same path as the by-hash ones. Re-checked on a mainnet node running this commit: 177 lookups on 59 random recent blocks. By-number, by-hash and rpc.hyperliquid.xyz agree on all of them, and the raw variants agree too. Out-of-range indexes and unknown blocks return null. |
|
Thanks, that pins both indexed lookup paths to the same sealed header as the system-tx count. Agreed on finality—the example was a defensive consistency case, not an observed HyperEVM reorg. Appreciate you checking the raw variants too. |
|
Thanks! Landed on |
Problem
With
--hl-node-compliant(or?hl=true),eth_getBlockBy*,eth_getBlockReceipts,eth_getTransactionReceipt, logs and the tx-count methods hide system txs. The by-index lookups were not covered by the compliance layer and still index the full block:eth_getTransactionByBlockHashAndIndexeth_getTransactionByBlockNumberAndIndexeth_getRawTransactionByBlockHashAndIndexeth_getRawTransactionByBlockNumberAndIndexSo index
Nreturns a different tx than the oneeth_getBlockBy*lists at positionN(and than hl-node /rpc.hyperliquid.xyzreturn), often a system tx.Example, mainnet block 49,493,297 (
0x7543f6df…c2ee3), index0x1:eth_getTransactionByBlockHashAndIndex0x2a350753…622f7e(matchestransactions[1]of the block)0xfa20609f…3d04bf(a system tx)This breaks Arbitrum Nitro nodes of Orbit chains that settle on HyperEVM: Nitro looks up batch transactions with
eth_getTransactionByBlockHashAndIndexand then stalls, retrying forever onFix
Add the four methods to
EthBlockApi, following the same pattern as the other compliance overrides:system_tx_countbefore the lookup, and shifttransactionIndexin the response back;latest, …) to a concrete block number first, so the system tx count and the lookup refer to the same block;Testing
nulllike hl-node.cargo testpasses.cargo clippy --workspace --tests --all-featureswith-D warningson current stable (1.99) fails withclippy::double_must_useon every#[rpc]trait in the crate, including ones this PR doesn't touch (e.g.call_forwarder.rs,tx_forwarder.rs,sync_server.rs); no other warnings.Related: #160 (another system-tx difference vs hl-node).