feat: encode+decode the 8 largest mainnet txns via direct query - #142
Closed
creditcoinprotoclaw wants to merge 8 commits into
Closed
feat: encode+decode the 8 largest mainnet txns via direct query#142creditcoinprotoclaw wants to merge 8 commits into
creditcoinprotoclaw wants to merge 8 commits into
Conversation
Add singleTxnGasLimit = 25_000_000n and reject any proof whose gas crosses it. Checked in three places: after gasForVerification, after gasForDecoding, and after totalGas. Mirrors the same change in creditcoin3 prover-check.ts.
Add a deterministic worst-case coverage path that queries the 8 largest documented Ethereum Mainnet transactions directly by hash (instead of streaming live blocks and hoping to re-encounter them), encodes them via both the ethers (TS) and alloy (Rust) encoders, and decodes them downstream. - src/bin/encode-largest-txns.ts: ethers encoder, queries the 8 fixed block/tx pairs directly, fails on any missing/oversized txn. - rust/bin/encode_largest_txns.rs: alloy counterpart, same fixtures. - rust/Cargo.toml: register the new encode-largest-txns bin. - .github/workflows/compare-encoding-largest-txns.yml: mainnet-only (Sepolia dropped), encodes + diffs alloy vs ethers, then decodes on cc3-devnet. step timeouts bumped to 5 mins so a PR run completes. cc <@U028EMRHS3S>
atodorov
marked this pull request as draft
July 27, 2026 09:28
Amend per review: - Drop rust/bin/encode_largest_txns.rs (and its Cargo.toml bin entry); keep this path ethers-only. - Drop the alloy-encode and compare-data jobs from the workflow; it now just encodes (ethers) then decodes. - Encoder no longer throws on a failed txn. Each of the 8 fixtures is attempted and any failure is logged with an ENCODE_ERROR: prefix so we see ALL failing large txns in one run instead of bailing on the first. A single grep-based CI gate fails the pipeline afterwards. cc <@U028EMRHS3S>
Mirror the encode-side change into decode-blocks.ts: the 4 gas-cap checks in decodeFromDisk no longer throw. Each violation is logged with a DECODE_ERROR: prefix (including the tx hash) so a single run surfaces EVERY failing large txn instead of bailing on the first. The largest-txns workflow's decode step now tees its output and a grep-based gate fails the pipeline afterwards. The '0 files found' setup guard still throws (genuine misconfiguration, not a per-txn failure). cc <@U028EMRHS3S>
Switch the grep-able ENCODE_ERROR / DECODE_ERROR / MAX_ENCODED_SIZE log lines from console.error to console.log per review. The tee'd CI logs still capture them (2>&1) and the grep gates are unchanged. cc <@U028EMRHS3S>
Remove the pull_request trigger from both existing stream-encode workflows on this branch. The new compare-encoding-largest-txns workflow covers PR-time encode/decode verification, so running the full mainnet/Sepolia stream encoders on every PR is redundant and slow. Both still run on their 12h schedule and via workflow_dispatch. cc <@U028EMRHS3S>
The ethers-encode RPC URL had a corrupted secret reference:
rpc?key=*** secrets.GOOGLE_ETHEREUM_RPC_KEY }}
instead of:
rpc?key=${{ secrets.GOOGLE_ETHEREUM_RPC_KEY }}
With the '${{' eaten, the encoder connected to the Google WS endpoint
with key='***' (and a stray shell arg), so the very first getTransaction
request hung with no response until the 5-min step timeout — which is
exactly why the job logged only the first txn and then died with no
error. Restoring the interpolation fixes it.
cc <@U028EMRHS3S>
… bin Per review: drop the separate encode-largest-txns.ts and put the direct-query behaviour into encode-blocks.ts behind an ENCODE_LARGEST_TXNS env flag. - encode-blocks.ts: add LARGEST_MAINNET_TXNS + encodeLargestTxns(); dispatch to it when ENCODE_LARGEST_TXNS is set, else stream as before. encodeTransaction now logs ENCODE_ERROR: and returns null instead of asserting non-null; encodeAndWriteToDisk skips on null. MAX_ENCODED_SIZE guard switched to console.log. No throw in the largest-txns loop — every fixture is attempted. - workflow: call encode-blocks.js with ENCODE_LARGEST_TXNS=1 instead of the deleted encode-largest-txns.js. Smoke-tested locally against a public mainnet WS: all 8 txns encode, 8 files written. cc <@U028EMRHS3S>
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.
What
Builds on #141 (
feat/decode-blocks-single-txn-gas-limit). Adds a deterministic worst-case coverage path that exercisesencode-blocks/decode-blocksagainst the 8 largest transactions ever observed on Ethereum Mainnet — the ones previously only documented as a comment inencode-blocks.ts.Instead of streaming the live head and hoping to re-encounter blocks of that size, this queries those exact block/tx pairs directly by hash, encodes them via both encoders, diffs, then decodes them downstream.
Sepolia support is dropped — these are mainnet-only fixtures.
Changes
src/bin/encode-largest-txns.ts— ethers encoder; queries the 8 fixed block/tx pairs directly. Fails the run on any missing/unretrievable txn (unlike the streaming encoder, these are fixed historical fixtures and must always encode). Keeps theMAX_ENCODED_SIZEgrep guard.rust/bin/encode_largest_txns.rs— alloy counterpart, same 8 fixtures, same fail-hard semantics.rust/Cargo.toml— registers the newencode-largest-txnsbin..github/workflows/compare-encoding-largest-txns.yml— mainnet-only workflow: alloy-encode + ethers-encode the 8 txns → compare (diff) → decode on cc3-devnet. Encode/decode/compare step timeouts bumped to 5 mins so the whole thing completes as a PR run.Why
The comment-only documentation of the largest txns didn't actually get exercised deterministically. Querying them directly guarantees every CI run validates the true worst-case ABI-encoding size against both encoders and the on-chain decoder.
Testing
tsc --noEmit✅prettier --check .✅cargo build --release✅ (both bins)cargo fmt --check✅cargo clippy --release✅The real end-to-end (RPC + devnet decode) runs in the new workflow on this PR.