Skip to content

fix(evm-rpc): validate transaction nonce as a wide quantity for Tempo 0x76 uint64 nonces - #598

Open
SQD-Trevor-Agent wants to merge 1 commit into
masterfrom
alert-fix/lOEteH-tempo-uint64-nonce
Open

SQD-Trevor-Agent wants to merge 1 commit into
masterfrom
alert-fix/lOEteH-tempo-uint64-nonce

Conversation

@SQD-Trevor-Agent

Copy link
Copy Markdown

Cause (proven)

dump-tempo-moderato-0 (namespace evm-archive) was in CrashLoopBackOff (14+ restarts), which also tripped the "no data" alert. The fatal error, from the pod's previous-container logs:

DataValidationError: server returned unexpected result: invalid value at /transactions:
  fullTransactions: invalid value at /0/nonce: "0xffffffffffffffff" is not a safe integer
  at /squid/evm/evm-rpc/lib/rpc.js:1025  (EvmRpcClient.receiveResult, eth_getBlockByNumber ["0x2580bc7", true])

Block 0x2580bc7 (39324103) on Tempo testnet (chainId 0xa5bf = 42431) contains a type 0x76 Tempo transaction whose nonce is a full uint64 (0xffffffffffffffff, paired with a separate nonceKey for account abstraction). The Transaction schema in evm/evm-rpc/src/rpc-data.ts validated nonce with SMALL_QTY, which casts to a JS number and rejects anything above Number.MAX_SAFE_INTEGER (2^53-1). Every fetch of this block therefore failed validation with a non-retryable DataValidationError and killed the dumper — a deterministic crash-loop, not a transient one.

The data is legitimate on-chain data, not corruption: the rest of the transaction validates, calculateTransactionsRoot reproduces the block's transactionsRoot (0x75823a8f…) and recoverTxSender recovers the correct from for all txs including the 0x76 one — the verification/RLP path already treats nonce as a wide value via BigInt(tx.nonce) (verification.ts:655). Only the schema validator was too narrow.

This corrects an oversight in the original Tempo support (#446), which added the 0x76 fields and encoding but left nonce: SMALL_QTY.

Fix

Validate Transaction.nonce as QTY (hex quantity → bigint) instead of SMALL_QTY. This is a pure validation relaxation: the evm-rpc pipeline validates but never casts the result (getResultValidator returns the raw object), the exported Transaction source type is unchanged (string both before and after), and the dumper writes the untouched raw RPC JSON via toRawBlock — so there is no change to on-disk data for any network, only that legitimate wide nonces stop crashing validation.

Test (red → green)

Added fixture evm/evm-rpc/test/fixtures/tempoModerato/39324103/block.json — the real failing block (5 txs, one 0x76 with nonce: "0xffffffffffffffff"). It is auto-discovered by test/verification.test.ts.

  • pre-fix: tempoModerato block 39324103 > schema validation fails (expected ValidationFailure to be undefined)
  • post-fix: all 6 checks pass — schema validation, blockHash verification, transactionsRoot verification, transaction sender recovery, etc.
  • transactionsRoot verification and transaction sender recovery pass both pre- and post-fix, proving the uint64 nonce is genuine on-chain data that encodes/recovers correctly.
  • Full @subsquid/evm-rpc suite green (442 passed | 29 skipped; one unrelated pre-existing base-mainnet sender-recovery test is flaky on the default 5s timeout and passes at --testTimeout=30000). rush build -t @subsquid/evm-rpc clean; tsc --noEmit clean; rush change --verify passes.

Falsification

If dump-tempo-moderato-0 still exits with a DataValidationError after this change, the failure is on a different field — re-read the stack. If transactionsRoot verification for the fixture ever fails, the 0x76 RLP encoding (not the nonce width) is wrong.

Related

Related to #551 (retry transient malformed block results), different root cause: #551 handles a transient proxy glitch that drops nonce (retrying self-heals). This block's nonce is present, valid, and deterministic — retrying would loop forever; the validator itself must accept it. Not related to #591 (prestate-tracer state-diff nonce). TempoSignedAuthorization.nonce and evm-normalization's qty2Int(src.nonce) keep the narrower number handling and are out of scope here (not exercised by this block; the dumper does not call them).

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

Successfully merging this pull request may close these issues.

1 participant