Repository navigation
fix: bridge-off eth blocks include transactions (Curio reorg check) - #180
Merged
Merged
Conversation
Reiers
added a commit
that referenced
this pull request
Oct 26, 2026
… returns unresolved count; Lotus accessList form in index fixture test)
This was referenced Oct 26, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Stock Curio-PDP's reorg check (
tasks/pdpv0/task_reorg_check.go,ReorgCheckEthAPI) walks the chain with go-ethereum's ethclient and looks for its tx hashes inside eth blocks:BlockByNumber(nil)->eth_getBlockByNumber("latest", true)BlockByHash(parentHash)->eth_getBlockByHash(hash, true), repeated down the chainblk.Transactions()->tx.Hash()matched against its sent txs;TransactionReceiptfor its own txsOther Curio eth calls (
message/watch_eth.go, sender, replace, GC):TransactionReceipt,TransactionByHash,HeaderByNumber(nil)(=eth_getBlockByNumber("latest", false)),BlockNumber. Curio does not calleth_getTransactionByBlock*AndIndexoreth_getBlockTransactionCountBy*.Bridge-off Lantern returned every block with
transactions: []andtransactionsRoot0x00. go-ethereum'sgetBlockrejects that combination outright ("server returned empty transaction list but block header indicates transactions"), so every walk failed. Even a parseable empty body would have made Curio think its txs had been reorged out.Fix (Lotus v1.38.3
newEthBlockFromFilecoinTipSetparity, bridge-off)chain/ethtx/legacy.go) eth tx. Secp / BLS messages go through Lotus' native conversion: ABI-wrapped params, InvokeContract / EAM CreateExternal payload decode, f410 / masked-ID addressing against the post-execution state, the reverted-recipient sentinel, and a CID-derived hash.fullTx=falsereturns the hashes.gasUsed= sum of the receipts,logsBloom= the chain-indexer bloom (emitter + topics of every EVM-shaped event),gasLimit= 10B x blocks, Lotus constants for sha3Uncles / zero roots / zero miner,transactionsRoot0x00 with txs and EmptyRootHash without (so go-ethereum accepts both).latestandeth_blockNumber= head's parent (the newest executed tipset, so receipts exist);pending= head (gasUsed 0, unknown bloom); numbers above latest give "requested a future epoch (beyond 'latest')"; null rounds give "requested epoch was a null round (N)";earliestis unsupported;safe/finalized= head-30 / head-900.eth_getLogsuses and accepts the same block hash.eth_getTransactionByBlockNumberAndIndex, plus neweth_getTransactionByBlockHashAndIndexandeth_getBlockTransactionCountByNumber/ByHash(count uses the deduped list, like LotusBlockMsgsForTipset).eth_getTransactionByHash/ receipts now also serve native messages and legacy txs locally, receipttypefollows the tx, and delegated txs renderaccessList: nullexactly like Lotus.fullTx=falsefalls back to the header-only block, which keepsHeaderByNumber(base fee for sends) working.fullTx=truereturns the error instead of a misleading empty body.Verification
TestEthBlockLocal_MatchesLotuscompares against Glif, field by field, on calibration blocks 0x3feed0 (tx 0xfd05...8865, 42 txs, 3-block tipset), 0x3feec7 (tx 0xb3dc...9903, 51 txs including 1 EIP-155 legacy tx) and 0x3feeb0 (1 native secp SubmitWindowedPoSt). It covers by number and by hash,fullTxfalse and true, tx by number/hash + index, and counts by number/hash, and finds 0 diffs. The header store holds only a partial head tipset (1 of 4 blocks at 4189905), solatestmust resolve to the full 3-block tipset. The same test replays Curio's walk (latest, then BlockByHash(parentHash) down to 0x3feec7) with go-ethereum's header/body consistency checks, and both Curio txs turn up in their canonical blocks.TestEthBlockLocal_Tagspins the tag and error semantics and the cache.Glif load-balances Lotus 1.38.3 and Forest. The two backends render one field differently:
accessListon delegated txs (Lotusnull, Forest[]or omitted on legacy). The test normalizes recorded responses to the Lotus form (asLotusShape), and the existing receipt test does the same. One Lotus backend had cached 0x3feed0 before indexing it and serves the "unknown" full bloom. In that case the recorder uses the OR of Glif'seth_getBlockReceiptsblooms, which is what the Lotus indexer stores.go vet ./...andgo test ./...pass (CGO_ENABLED=0).Remaining gaps
eth_getLogsstill reportstransactionHashas the message CID digest for delegated txs. Lotus reports the eth tx hash (pre-existing, separate fix).pending(the head) is built from the pre-state: gasUsed 0, full bloom. Native-message address lookups could differ only for actors created by the head's own messages.safe/finalizeduse the static head-30 / head-900, with no EC-finality calculator or F3.