Skip to content

[DONT MERGE] Seismic => upstream diff#60

Open
cdrappi wants to merge 275 commits intomainfrom
seismic
Open

[DONT MERGE] Seismic => upstream diff#60
cdrappi wants to merge 275 commits intomainfrom
seismic

Conversation

@cdrappi
Copy link
Contributor

@cdrappi cdrappi commented Jan 24, 2025

No description provided.

cdrappi and others added 30 commits December 13, 2024 09:48
Signed-off-by: Gregory Edison <gregory.edison1993@gmail.com>
Co-authored-by: Léa Narzis <78718413+lean-apple@users.noreply.github.com>
Co-authored-by: Arsenii Kulikov <klkvrr@gmail.com>
Co-authored-by: Matthias Seitz <matthias.seitz@outlook.de>
Co-authored-by: Darshan Kathiriya <8559992+lakshya-sky@users.noreply.github.com>
Co-authored-by: dkathiriya <lakshya-sky@users.noreply.github.com>
Co-authored-by: Ryan Schneider <ryanleeschneider@gmail.com>
Co-authored-by: Tien Nguyen <htiennv@gmail.com>
Co-authored-by: Roman Krasiuk <rokrassyuk@gmail.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-merge-queue <118344674+github-merge-queue@users.noreply.github.com>
Co-authored-by: Alexey Shekhirin <a.shekhirin@gmail.com>
Co-authored-by: Querty <98064975+Quertyy@users.noreply.github.com>
Co-authored-by: Federico Gimenez <fgimenez@users.noreply.github.com>
Co-authored-by: joshieDo <93316087+joshieDo@users.noreply.github.com>
Co-authored-by: Hai | RISE <150876604+hai-rise@users.noreply.github.com>
Co-authored-by: Minhyuk Kim <kimminhyuk1004@gmail.com>
Co-authored-by: Dan Cline <6798349+Rjected@users.noreply.github.com>
Co-authored-by: Emilia Hane <elsaemiliaevahane@gmail.com>
Co-authored-by: morito <ikeda.morito@gmail.com>
Co-authored-by: Alessandro Mazza <121622391+alessandromazza98@users.noreply.github.com>
Co-authored-by: frisitano <35734660+frisitano@users.noreply.github.com>
Co-authored-by: kien-rise <157339831+kien-rise@users.noreply.github.com>
Co-authored-by: Woolfgm <160153877+Dahka2321@users.noreply.github.com>
Co-authored-by: Steven <112043913+stevencartavia@users.noreply.github.com>
Co-authored-by: Ahmet Yazıcı <75089142+yaziciahmet@users.noreply.github.com>
Co-authored-by: Skylar Ray <137945430+sky-coderay@users.noreply.github.com>
Co-authored-by: Elvis <43846394+Elvis339@users.noreply.github.com>
Co-authored-by: Harsh Vardhan Roy <42067944+royvardhan@users.noreply.github.com>
Co-authored-by: greg <82421016+greged93@users.noreply.github.com>
Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com>
Co-authored-by: angel-ding-cb <141944320+angel-ding-cb@users.noreply.github.com>
Co-authored-by: Miguel Oliveira <migueloliveiradev@gmail.com>
Co-authored-by: faheelsattar <faheelsattar@yahoo.com>
Co-authored-by: Tuan Tran <tropicaldog17@gmail.com>
Co-authored-by: Ayodeji Akinola <akinayodeji4all@gmail.com>
Co-authored-by: Tien Nguyen <116023870+htiennv@users.noreply.github.com>
Co-authored-by: Victor Castell <0x@vcastellm.xyz>
Co-authored-by: Christian Drappi <c@seismic.systems>
Co-authored-by: phexyz <32248504+phexyz@users.noreply.github.com>
Co-authored-by: Spencer Solit <sol@seismic.systems>
Co-authored-by: Ameya Deshmukh <ad@seismic.systems>
This is a no-op change. I just force rebased the seismic branch on
seismic-evm repo to clean up its history. So the commit is different but
it's pointing to the exact same code (old commit kept as head of
seismic-pre-rebase branch).
This matches CLAUDE.md recommended settings, so I think it should be
committed. This way vscode will format rust files properly.
Move seismic-features.md under docs/seismic, to follow the same
convention as other repos (makes it easier for LLMs to find these docs).

Also made minor updates, incorporating changes from
https://github.com/SeismicSystems/documentation
Current behavior of eth_getProof is that it returns proofs for any
slots, including private slots.
We've already decided that eth_getStorageAt should return 0x00 for
private slots, so eth_getProof should follow this behavior.

### Design Options

There are 3 places where we could have prevented this:
1. (lowest level): disallow even generating proofs inside our
seismic-trie fork
2. disallow generating
[StorageProof](https://github.com/SeismicSystems/seismic-reth/blob/22816a566d49bdeeb7b40f696be876a7b90c67d8/crates/trie/common/src/proofs.rs#L732)
structs for private slots
3. (highest-level: what this PR implements): retract slot+proof when
converting StorageProof->EIP1186StorageProof (which is returned by the
eth_getProof rpc)

Opting for option 3. One downside is that there is confidential
information potentially sticking around in memory, which has chances of
leaking to logs (see this
[issue](SeismicSystems/seismic-trie#17)) or
being extracted from TEE from exploits somehow.

The upside is that we can try to make our fork as minimal as possible
and leave all the low-level librairies almost stock (I think there is a
world where we can even completely get rid of our seismic-trie fork).

This choice also mimicks how we implement CLOAD/CSTORE in the evm: the
journal/storage layer behaves exactly the same as for sload/cload and
will return any data: its the job of the evm instruction evaluation
(highest-level) to enforce the privacy semantics and halt when SLOAD
from the journal has returned a private slot.
… order genesis.json (#312)

3 main things:
1. changed contracts URL to point to contracts' new location in seismic
monorepo
2. fixed binary cargo.toml by adding required "fmt" feature to
tracing-subscriber
3. made produced dev.json genesis file lexicographically ordered to get
better reproducibility going forward (will be easy to git diff for
differences when we change some contracts' bytecode for example)
Bounded cache with HashSet + VecDeque for O(1) contains and FIFO
eviction. Supports sequential appends, gap backfilling, and full
rebuilds for reorg recovery via a `canonical_hash_at` closure.
… validation

Replace per-transaction client iteration with O(1) cache lookups.
The cache is populated at startup and updated via on_new_head_block,
which uses the same consensus-driven source as the RPC layer, fixing
the intermittent "recent_block_hash not found" error caused by
database lag.
…315)

This PR adds the following:

## Adversarial fuzzing framework

A proptest-based fuzzing framework (`reth-seismic-fuzz`) that
stress-tests all Seismic-specific code paths for panics. Any panic in
production code is treated as a security bug since it can crash the
node.

### What's tested

- **Precompile crash-freedom**: All 5 stateless seismic precompiles
(AES-GCM encrypt/decrypt, ECDH, HKDF, secp256k1-sign) fuzzed with
arbitrary bytes and gas limits, including boundary-length inputs near
each precompile's expected input size.

- **EVM execution crash-freedom**: Full `SeismicEvm.transact()` with
arbitrary transactions across all tx types except EIP-4844 (Legacy,
EIP-2930, EIP-1559, Seismic 0x4A) and contract deployments.

- **Flagged storage crash-freedom**: Dynamically-constructed bytecode
with SLOAD, CLOAD (0xB0), and CSTORE (0xB1) opcodes on arbitrary storage
slots, exercising the privacy boundary enforcement between public and
private storage.

- **Differential correctness**: Same non-seismic transaction executed on
both SeismicEvm and plain revm, comparing success/failure outcome, gas
usage, output bytes, and error reasons. Any divergence is a regression.

- **Transaction encoding roundtrips**: EIP-2718 and Compact codec
encode/decode roundtrips, plus raw arbitrary bytes fed into decoders to
verify crash-freedom on the P2P attack surface.

### Bug fix: `Decompress` panic on corrupt database entries

The zstd decompressor in `ReusableDecompressor::decompress`
(`zstd-compressors/src/lib.rs`) panics via `assert!` when it encounters
malformed data (e.g. "Unknown frame descriptor", "Dictionary mismatch").
This panic is reachable through any DB read that touches a corrupt entry
— including P2P request handlers serving data to remote peers.

This is a known issue in upstream reth. A user reported it in
[paradigmxyz/reth#16052](paradigmxyz/reth#16052):
their node ran for 6 hours with a corrupt snapshot, surviving its own
sync loop (which handled MDBX-level corruption gracefully), until a
random peer requested data from the corrupt region. The P2P handler hit
the zstd assert and the entire node crashed.

**Fix**: The `Decompress` trait implementations in
`db-api/src/models/mod.rs` (the bridge between `Compact::from_compact`
and the DB read path) now wrap `from_compact` in `catch_unwind`. If the
zstd decompressor (or any other `from_compact` code) panics, it's caught
and converted to `DatabaseError::Decode`. The existing error handling at
every layer above — staged sync pipeline, P2P request handler, RPC —
handles `DatabaseError` gracefully. The node stays up.

**Validation**: The `db_corruption.rs` integration test writes a valid
transaction to MDBX, overwrites it with corrupt bytes (zstd flag set,
garbage payload) via `RawTable`, then reads it back through the
production code path (`tx.get::<Transactions>()` → `decode_one` →
`Decompress::decompress`). It asserts that:
1. The read returns `Err(DatabaseError::Decode)` instead of panicking
2. The zstd decompressor panic actually fired internally (captured via
`set_hook`)
This PR introduces EIP-4844 (blob transaction) coverage to the fuzz
testing framework.

## What changed

- Removed the EIP-4844 skip guards in `tx_encoding.rs` that were
blocking roundtrip fuzz coverage. The `arbitrary(skip)` on the EIP-4844
variant in `seismic-alloy` has been removed upstream, so `proptest` now
generates blob transactions naturally (~20% of cases). The "known
encoding limitations" comment was stale — both EIP-2718 and `Compact`
roundtrips pass for EIP-4844.

- Added `tx_type = 3` (EIP-4844) to the `FuzzSeismicTx` generator in
`tx_gen.rs`. The selector changed from `% 4` to `% 5`, and blob-specific
fields (`blob_hashes`, `max_fee_per_blob_gas`) are populated when
generating blob transactions. This means EVM execution, differential,
and flagged storage fuzz tests now exercise EIP-4844 code paths.

- Updated `into_eth_compatible_tx` to include EIP-4844 in differential
testing (it's a standard Ethereum tx type).

## What's now fuzzed

- `tx_roundtrip_2718` — EIP-4844 encode/decode roundtrip
- `tx_roundtrip_compact` — EIP-4844 `Compact`/zstd roundtrip
- `evm_transact_never_panics` — EVM execution with `tx_type=3` and blob
fields
- `differential_eth_vs_seismic_outcome` — `SeismicEvm` vs plain `revm`
with blob txs
Just a small change where enclave uses tracing instead of println so
that --quiet actually doesnt show the enclave logs.
Only incorporates this one commit:
SeismicSystems/enclave#173
Adds automated PR review via Claude Code GitHub Action.

Reviews trigger on every PR open/push and on `@claude` mentions in PR
comments. Scoped to read-only tools (gh pr diff/view/comment, git).

Review focus includes Seismic-specific concerns:
- Confidential tx (0x4a) encryption handling and plaintext leak
prevention
- Enclave/TEE purpose key safety
- EVM execution and confidential state isolation
- TxPool RecentBlockCache correctness
- RPC extension safety
- Clippy strictness (no unwrap/expect/indexing/panic/unreachable/todo)

Requires `ANTHROPIC_API_KEY` secret to be set in repo Settings > Secrets
and variables > Actions.
@github-actions
Copy link
Contributor

PR Review Summary

Changes

This PR ([DONT MERGE] Seismic => upstream diff) captures the full delta between the seismic branch and upstream main — 527 files changed, +50k/-5.8k lines. It introduces Seismic-specific crates for chainspec, hardforks, EVM execution, txpool, RPC, payload building, node orchestration, and enclave/TEE integration for confidential transactions (type 0x4A).


Blocking Issues

1. try_build_and_sign is a stub returning a garbage transaction
File: crates/seismic/rpc/src/eth/mod.rs (~lines 100–130)

try_build_and_sign silently returns a hardcoded legacy tx with zeroed signature (Signature::new(U256::ZERO, U256::ZERO, false)) and zeroed hash (B256::ZERO), ignoring both the signer and the actual input. This is indistinguishable from a real result at the type level — callers have no way to detect the stub. Replace with unimplemented!() or a compile error until properly implemented.


2. Hardcoded RngMode::Execution with explicit warning comment
File: crates/seismic/primitives/src/transaction/signed.rs (~line 195)

let rng_mode = RngMode::Execution; // TODO WARNING: chose a default value

The comment itself flags this as a known incorrect default. RngMode controls how the seismic EVM RNG is seeded — using Execution unconditionally in from_recovered_tx (which is called from simulation, pending-block, and call paths) will cause divergence between simulation and actual execution results. This must be resolved before merge.


3. Debug log of full consensus tx (potentially including input) in payload builder
File: crates/seismic/payload/src/builder.rs (~line 202)

debug!("default_seismic_payload: tx: {:?}", tx);  // tx is full SeismicTransactionSigned

Missing target: qualifier and formats the entire consensus transaction via {:?}, which may include the encrypted input field. If from_recovered_tx has decrypted the payload by this point, this logs plaintext calldata. Remove or replace with a hash-only log.


4. Debug log of full recovered transaction (ciphertext + sender) in send_raw_transaction
File: crates/seismic/rpc/src/eth/transaction.rs (~line 37)

tracing::debug!(target: "reth-seismic-rpc::eth", ?recovered, "serving seismic_eth_api::send_raw_transaction");

?recovered formats the full Recovered<SeismicTransactionSigned> — sender address, nonce, encryption pubkey, and ciphertext body — on every eth_sendRawTransaction call. Replace with:

tracing::debug!(target: "reth-seismic-rpc::eth", tx_hash=%recovered.tx_hash(), sender=%recovered.signer(), "serving seismic_eth_api::send_raw_transaction");

5. Debug log of full TxEnv (potentially post-decryption) in eth_call
File: crates/seismic/rpc/src/eth/call.rs (~line 175)

tracing::debug!("reth-seismic-rpc::eth create_txn_env {:?}", env);

Missing target: qualifier and logs the full TxEnv including the data field. For seismic call paths, signed_read_to_plaintext_tx may have already decrypted the calldata before this log fires — making this a potential plaintext leak in a hot path. Remove this log.


6. Debug log of full SeismicTransaction<TxEnv> in execution hot path
File: crates/seismic/primitives/src/transaction/signed.rs (~line 322)

tracing::debug!("from_recovered_tx: tx: {:?}", tx);

from_recovered_tx is called during EVM execution. By the time this log fires, data in the TxEnv may be decrypted calldata. This fires on every transaction execution. Remove entirely.


7. Mock enclave server gated only by runtime CLI flag, not compile-time feature
File: crates/seismic/node/src/enclave.rs (~lines 22–33)

The mock server and all get_unsecure_sample_* code paths are reachable in production binaries — a single --enclave.mock-server flag enables them. An operator misconfiguration or deployment error would silently use mock keys in production. Gate the mock server behind a compile-time feature flag:

#[cfg(any(test, feature = "mock-enclave"))]
if config.mock_server { ... }

Emit a compile error if mock-enclave is enabled on a release build.


Suggestions

  1. SEISMIC_DEV_OLD / dev-old chain spec should be removedcrates/seismic/chainspec/src/lib.rs. Has a TODO comment "remove once we launch devnet with consensus". Dead code that increases attack surface and creates confusion about which chain spec is canonical.

  2. Hardcoded Anvil keys in genesis manifestcrates/seismic/chainspec/res/genesis/manifest.toml line ~30 has a TODO acknowledging Anvil keys are hardcoded. Ensure this file is excluded from any non-dev genesis derivation pipeline.

  3. RwLock poison recovery should emit a warningcrates/seismic/txpool/src/validator.rs lines ~163, 180, 201 use unwrap_or_else(|e| e.into_inner()) on poisoned locks. The fail-open behavior for expiration checks (recovered cache has current_block_number = 0, so all expiry checks pass) should at minimum log a warn! or error! when poison recovery occurs.

  4. validate_signed_read_for_write allows signed_read = true on contract creationcrates/seismic/txpool/src/validator.rs. The check rejects signed_read for non-create calls but silently allows it for deploys. If signed reads are intended only for read-only calls this is a bug; if deploying with signed_read is intentional, add a comment.

  5. Error codes are placeholderscrates/seismic/rpc/src/eth/ext.rs lines ~335, 344 use -32000 with a TODO comment. Assign specific codes in the -32099 to -32001 range so callers can distinguish decryption/encryption errors from generic server errors.

  6. debug! in ext.rs logs full raw transaction bytescrates/seismic/rpc/src/eth/ext.rs line ~296 logs full SeismicRawTxRequest (ciphertext bytes). Replace with size and variant only.

  7. eth_call and eth_estimateGas debug logs leak full requestcrates/seismic/rpc/src/eth/ext.rs lines ~258, 314 log full SeismicCallRequest / SeismicTransactionRequest including input bytes and from field on every call. Replace with summary logs.

  8. Test utilities not gated by #[cfg(test)]crates/seismic/node/src/utils.rs exposes pub mod test_utils with allow(clippy::unwrap_used) but is reachable in production builds. Gate with #[cfg(any(test, feature = "test-utils"))].

  9. evm_env hardcodes SeismicSpecId::MERCURYcrates/seismic/evm/src/lib.rs lines ~125–127 have a TODO to use the correct spec. Acceptable for now but must be wired up before introducing new hardforks.

  10. println! in proptestcrates/seismic/primitives/src/transaction/signed.rs line ~836 has a bare println! inside a proptest. Remove to avoid noisy test output.


Positive Notes

  • Architecture follows reth patterns cleanly. Each seismic concern is a separate crate (chainspec, hardforks, evm, txpool, rpc, payload, node) with clean boundaries. Upstream types are extended via traits rather than forked.
  • Purpose key management is correct. The OnceLock<GetPurposeKeysResponse> pattern in purpose_keys.rs initializes once at startup and panics (rather than returning mock keys) if called before initialization — the right fail-closed behavior.
  • Enclave boot failure is fatal. The retry loop in enclave.rs with a final panic! ensures the node cannot start without real keys.
  • RecentBlockCache is well-implemented. Handles reorgs (full rebuild), gaps (backfill), and sequential append correctly. Test suite covers all three update paths including same-height reorgs.
  • Receipt conversion is complete. SeismicRethReceiptBuilder and SeismicReceiptConverter handle all six transaction types with no unmatched variants.
  • Error types are specific. SeismicEthApiError correctly maps enclave/storage errors to RPC error objects, and FromEvmHalt<SeismicHaltReason> propagates seismic halt reasons through the RPC layer.
  • Fuzz test suite exists with differential, EVM execution, flagged storage, and transaction encoding targets.
  • RwLock poison recovery is deliberate (not accidental), and the fail-closed behavior for block hash validation (empty cache rejects all hashes) is the correct security-sensitive behavior.

…e-review (#321)

## Summary
- Remove `synchronize` from PR triggers to break the
push→review→new-issues→push loop; re-reviews now happen on-demand via
`@claude` comments only
- Add exhaustive initial review mode that catches all issues in a single
pass and stamps the reviewed commit SHA
- Add incremental re-review mode that diffs only new changes since the
last review and tracks resolution of previously flagged issues
- Use `fetch-depth: 0` for full git history and add
`PR_NUMBER`/`IS_REREVIEW` env vars for cleaner prompt interpolation

## Test plan
- [ ] Open a test PR to verify the initial review triggers on `opened`
and produces a single exhaustive comment with the reviewed commit SHA
- [ ] Push a follow-up commit and confirm no automatic re-review fires
- [ ] Comment `@claude` on the PR and verify the re-review mode
activates, diffs against the last reviewed SHA, and uses the re-review
output format
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.

9 participants