Skip to content

feat: add signet-rpc-storage crate with ETH RPC endpoints#75

Open
prestwich wants to merge 35 commits intomainfrom
feat/rpc-storage-scaffolding
Open

feat: add signet-rpc-storage crate with ETH RPC endpoints#75
prestwich wants to merge 35 commits intomainfrom
feat/rpc-storage-scaffolding

Conversation

@prestwich
Copy link
Member

@prestwich prestwich commented Feb 11, 2026

Summary

  • Adds the signet-rpc-storage crate providing Ethereum JSON-RPC endpoints backed by signet-storage (hot + cold), independent of reth's FullNodeComponents
  • StorageRpcCtx wraps UnifiedStorage, BlockTags, system constants, optional TxCache, and RPC gas cap
  • BlockTags provides atomic latest/safe/finalized block tracking with sync/async resolution
  • Implements 24 supported ETH namespace endpoints:
    • Simple queries: blockNumber, chainId
    • Block queries: getBlockByHash/Number, getBlockTransactionCount*, getBlockReceipts, getBlockHeader*
    • Transaction queries: getTransactionByHash, getRawTransactionByHash, *ByBlockAndIndex, getTransactionReceipt
    • Account state (hot storage): getBalance, getStorageAt, getTransactionCount, getCode
    • EVM execution: call, estimateGas via signet-evm/trevm
    • Transaction submission: sendRawTransaction via TxCache
    • Logs: getLogs with bloom filter matching
  • 30 unsupported methods return explicit "not supported" errors
  • Uses signet-storage 0.3.0 from crates.io

Test plan

  • cargo clippy -p signet-rpc-storage --all-features --all-targets — clean
  • cargo clippy -p signet-rpc-storage --no-default-features --all-targets — clean
  • cargo +nightly fmt — clean
  • cargo t -p signet-rpc-storage — 33 tests pass
  • cargo doc -p signet-rpc-storage — docs build successfully

🤖 Generated with Claude Code

@prestwich prestwich requested a review from a team as a code owner February 11, 2026 21:36
@prestwich prestwich changed the title feat: add signet-rpc-storage crate scaffolding feat: add signet-rpc-storage crate with ETH RPC endpoints Feb 12, 2026
@prestwich
Copy link
Member Author

[Claude Code]

Review Summary

What's here

  • 24 ETH JSON-RPC endpoints (22 supported + 23 explicitly unsupported)
  • Clean crate structure: ctx, resolve, eth/{endpoints, helpers, error, mod}
  • 23 integration tests covering all supported endpoints except eth_call and eth_estimateGas
  • No TODOs, no todo!(), no unimplemented!(), no naked unwrap() in production code
  • Clippy clean on both --all-features and --no-default-features

Issues flagged (inline comments)

Severity Location Issue
High endpoints.rs:647-651 sendRawTransaction fire-and-forget — forwarding errors silently discarded
Medium endpoints.rs:720-722 getLogs range validation — reversed from > to silently accepted
Low helpers.rs:274-276 unreachable!() in build_receipt_envelope — future alloy TxType variants will panic
Info tests/eth_rpc.rs eth_call and eth_estimateGas not yet tested (EVM state setup needed)

Codebase health

  • Zero TODO/FIXME comments
  • Zero panic!/unwrap in non-test code
  • Consistent error handling pattern (.map_err(|e| e.to_string()))
  • Good use of tokio::try_join! for concurrent cold storage reads
  • Tracing spans on EVM execution paths (eth_call, eth_estimateGas)

prestwich and others added 5 commits February 12, 2026 07:51
Add the foundational scaffolding for the signet-rpc-storage crate, which
provides an Ethereum JSON-RPC server backed by signet-storage's unified
storage backend, independent of reth's FullNodeComponents.

This includes:
- Workspace dependency additions (signet-storage, signet-cold, signet-hot,
  signet-storage-types)
- StorageRpcCtx context struct with Arc<Inner> pattern
- BlockTags atomic block tag tracker for Latest/Safe/Finalized
- Block ID and block tag resolution utilities
- Stub eth module (endpoints to be added in follow-up)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implement all ETH namespace JSON-RPC endpoints backed by cold/hot storage
instead of reth. Converts eth.rs placeholder into eth/ directory module
with error types, helpers, and 24 supported endpoint handlers:

- Simple queries: blockNumber, chainId
- Block queries: getBlockByHash/Number, getBlockReceipts, headers
- Transaction queries: getTransactionByHash, getTransactionReceipt, raw txs
- Account state (hot storage): getBalance, getStorageAt, getCode, getTransactionCount
- EVM execution: call, estimateGas (via signet-evm/trevm)
- Transaction submission: sendRawTransaction (via TxCache)
- Logs: getLogs with bloom filter matching

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add 23 integration tests covering all endpoint categories: simple
queries, block/transaction lookups, account state, logs, and error
cases. Tests exercise the router through the axum service layer using
tower's oneshot().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- send_raw_transaction: log warning on forwarding failure instead of
  silently discarding the error
- get_logs: reject reversed block ranges (from > to) with an explicit
  error instead of silently returning empty results
- build_receipt_envelope: remove catch-all arm so new TxType variants
  from alloy produce a compile error instead of a runtime panic

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Regular txs execute before system txs, not the other way around.

Drive-by from #74 (comment)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@prestwich prestwich force-pushed the feat/rpc-storage-scaffolding branch from 4341320 to 601c156 Compare February 12, 2026 12:51
prestwich and others added 3 commits February 12, 2026 08:07
- Extract `resolve_evm_block` method on `StorageRpcCtx` to deduplicate
  the block resolution + header fetch + revm db creation shared by
  `call()` and `estimate_gas()`. Resolves headers directly (by hash or
  by tag→number) to avoid redundant cold storage lookups.
- Replace glob import `use endpoints::*` with explicit imports.
- Remove unused `revm_state()` method from `StorageRpcCtx`.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ounds

- Move `resolve_block_id` and `resolve_block_number_or_tag` from free
  functions in resolve.rs to `resolve_block_id` and `resolve_block_tag`
  methods on `StorageRpcCtx`. This eliminates repeated `ctx.tags()` and
  `ctx.cold()` threading at every call site.
- `resolve_block_tag` returns `u64` directly (infallible) instead of
  `Result`, simplifying callers like `get_logs`.
- Remove `H::RoTx: Send + Sync + 'static` bounds from all endpoint
  functions, router, and ctx methods — the trait already provides these.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace the bare `rpc_gas_cap` constructor parameter with a
`StorageRpcConfig` struct that bundles all RPC configuration.
This moves `max_blocks_per_filter` from a hard-coded constant to
a configurable value, adds `max_logs_per_response` enforcement
in `eth_getLogs`, and pre-creates a tracing semaphore for future
debug endpoint concurrency limiting.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
prestwich and others added 8 commits February 12, 2026 09:59
Add gas oracle, filters, subscriptions, debug tracing, and signet
namespaces to signet-rpc-storage. Port 15 endpoints from the old
reth-backed signet-rpc crate to the storage-backed architecture.

New modules:
- gas_oracle: cold-storage gas price oracle (suggest_tip_cap)
- interest/: filter manager, subscription manager, block notifications
- debug/: traceBlockByNumber, traceBlockByHash, traceTransaction
- signet/: sendOrder, callBundle

Wired eth endpoints: gasPrice, maxPriorityFeePerGas, feeHistory,
newFilter, newBlockFilter, uninstallFilter, getFilterChanges,
getFilterLogs, subscribe, unsubscribe.

Integration tests cover gas/fee queries, filter lifecycle, and
debug tracing with noop tracer.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Use `SealedHeader` with `.hash()` / `.into_inner()` instead of
  `header.hash_slow()`
- Use `RecoveredTx` (pre-recovered sender) instead of manual
  `recover_sender` calls
- Use `ColdReceipt` with per-tx `gas_used` instead of computing
  deltas from cumulative gas
- Delegate `get_logs` to cold storage instead of manual bloom
  filtering and block iteration
- Remove `BlockRangeInclusiveIter`, `collect_matching_logs`,
  `build_receipt_from_parts`, and `recover_sender` helpers
- Simplify `build_rpc_transaction` and `build_receipt` to be
  infallible

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Addresses PR review feedback:
- resolve_block_id now uses hot HotDbRead::get_header_number instead of
  cold storage, making it synchronous and avoiding async overhead
- Add resolve_header for direct header fetches from hot storage,
  eliminating the double header lookup in header_by
- Change not_supported() to return method_not_found() (JSON-RPC -32601)
  instead of internal_error (-32603)
- Update ResolveError to use Storage/Db variants instead of Cold
- Update tests to write headers to both hot and cold storage

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Swap return types to use RpcBlock/RpcReceipt/RpcTransaction/RpcHeader
type aliases, rename tx_by_block_and_index to match rpc naming, fix
not_supported error message, and split call into run_call + call.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Align rpc-storage behavioral semantics with the rpc crate:
- subscribe: require filter for Logs, reject filter for NewHeads via TryFrom impl
- send_raw_transaction: return Result from spawned task instead of swallowing errors
- uninstall_filter/unsubscribe: add HandlerCtx and wrap in spawn_blocking

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…to 0.5

resolve_evm_block previously mapped Pending to Latest without modifying
the header, causing eth_estimateGas (which defaults to Pending) and
eth_call with explicit Pending to see wrong block.number, timestamp,
and base_fee. Now synthesizes a next-block header matching signet-rpc's
block_cfg() behavior.

Also refactors callBundle to use resolve_evm_block instead of duplicating
the pending header logic inline, and passes max_logs to cold.get_logs()
for early termination (signet-cold 0.5 API).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Member Author

@prestwich prestwich left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are there ways that we can DRY endpoint logic or definitions?

prestwich and others added 2 commits February 15, 2026 12:00
Move response/serialization types (EmptyArray, BlockTransactions,
RpcBlock, LazyReceipts) and type aliases from eth/endpoints.rs into
eth/types.rs, and parameter types (TraceBlockParams,
TraceTransactionParams) from debug/endpoints.rs into debug/types.rs.
Consolidate duplicate RpcTransaction/RpcReceipt aliases from
eth/helpers.rs into eth/types.rs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace the one-notification-per-iteration drain pattern with
permit_many batching for better throughput and fairness. Bumps ajj
to 0.6.2 for permit_many/notification_capacity support.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…tracking

Move NodeStatus from signet-node-types to signet-node, move
ServeConfig/RpcServerGuard from signet-rpc to signet-node, and remove
the journal hash tracking system (JournalHashes table, journal module,
GENESIS_JOURNAL_HASH, and all related parameters/methods).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Member Author

@prestwich prestwich left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Claude Code]

PR Review: signet-rpc-storage crate

The crate is well-organized and test coverage is solid. However, there are two likely bugs (leaked thread in SubCleanerTask, unsubscribe is a no-op), a conformance gap (eth_syncing), and a design issue with spawn_blocking being used for async work. See inline comments for details.

Design-level observations (not tied to a specific line):

StorageRpcConfig should have a builder — Per project conventions: "A struct is considered complex enough to warrant a builder if it has more than 4 fields." StorageRpcConfig has 11 fields.

Duplicated Either enumfilters.rs and subs.rs both define an Either enum with nearly identical semantics but different variants. Should be unified or renamed (FilterItem / SubscriptionItem).

Duplicated buffer/output typesFilterOutput and SubscriptionBuffer are structurally identical VecDeque-backed enums with Log/Block variants, len(), is_empty(), extend(), pop_front(). This could be a single generic type.

Error handling via String is inconsistent — Most endpoints return Result<T, String>, losing structured error info, while run_call/estimate_gas/create_access_list return ResponsePayload<T, CallErrorData>, and debug endpoints return ResponsePayload<T, DebugError>. The crate defines three good error types (EthError, DebugError, SignetError) but most endpoints discard them with .map_err(|e| e.to_string()).

- Fix SubCleanerTask thread leak (missing break on Weak upgrade failure)
- Fix missing tasks.insert in subscribe() preventing unsubscribe
- Implement eth_syncing with concrete SyncingResponse type
- Fix reward percentile cursor overflow in fee_history
- Switch cold-storage endpoints from spawn_blocking to spawn
- Add StorageRpcConfigBuilder for 11-field config struct
- Unify FilterOutput/SubscriptionBuffer into generic EventBuffer<B>
- Replace hard-coded 12s block time with slot_duration() from constants
- Add EthError::TransactionMissing variant
- Remove dead code (Either enums, unused methods, allow(dead_code))
- Fix license comment typos, min() style, mut rebinding nits

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
prestwich and others added 2 commits February 16, 2026 07:32
* refactor: rewrite block processor to use signet-hot storage

Replace the reth ProviderFactory-based storage with HotKv for rollup
state reads. The processor becomes a stateless executor that reads from
hot storage, runs the EVM, and returns ExecutedBlock. Extraction is
moved to the node (PR3) to avoid lifetime issues with borrowed Extracts.

- Replace Db: NodeTypesDbTrait generic with H: HotKv
- Replace state_provider_database() with revm_state() using RevmRead
- Remove on_host_commit() and commit_evm_results()
- Add process_block() returning ExecutedBlock
- Add build_executed_block() for type conversion
- Remove signet-db, signet-node-types, reth-exex, reth-node-api deps
- Add signet-hot, signet-storage-types deps
- Remove Chain/PrimitivesOf/ExExNotification type aliases from lib.rs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: rewrite signet-node to use unified storage and rpc-storage

Replace reth's ProviderFactory/BlockchainProvider with UnifiedStorage
and swap signet-rpc for signet-rpc-storage. The node now holds
Arc<UnifiedStorage<H>> and shares state with the RPC context through
BlockTags (atomic block tag tracking) and broadcast::Sender
(new block notifications).

Key changes:
- StorageRpcCtx accepts Arc<UnifiedStorage<H>> for shared ownership
- Node struct uses HotKv generic instead of NodeTypesDbTrait
- Block processing uses signet-extract's Extractor + ExtractableChainShim
- Genesis loading via HistoryWrite::load_genesis + UnsafeDbWrite::commit
- Fix metrics bug: record_notification_received now correctly increments
  the received counter instead of the processed counter

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: rewrite node-tests to use unified storage and align gas oracle

Replace TmpDb/ProviderFactory with MemKv/UnifiedStorage in all node test
infrastructure. Update signet-storage crates to v0.6.2 to fix MemKv
intra-transaction read visibility.

Align the cold-storage gas oracle with reth's GasPriceOracle by adding
default_gas_price (1 Gwei), ignore_price (2 wei), and max_price (500
Gwei) to StorageRpcConfig.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: delete signet-db, signet-node-types, and signet-rpc

These crates are fully replaced by signet-storage, signet-hot, and
signet-rpc-storage respectively. Remove 6,700+ lines of dead code and
clean up 22 unused workspace dependencies.

Replace reth-db tempdir_path with tempfile in signet-node-config.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: rename signet-rpc-storage to signet-rpc

Reclaim the signet-rpc name now that the old reth-backed crate is
deleted. Rename directory, package, and all import paths.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: restore RUN EVM ascii art banner

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: resolve clippy empty_line_after_doc_comments warning in ascii banner

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address PR review — bugs, style, and test infra

- Fix log_index per-receipt → per-block (kind.rs)
- Fix hash/height mismatch in update_highest_processed_height (node.rs)
- Fix serve_ipc panic: expect → ? (serve.rs)
- Use seal_unchecked to avoid redundant header re-hashing (processor.rs)
- Refactor imperative event loop → functional chain (processor.rs)
- Add #[instrument(skip_all)] to run_evm and build_executed_block
- Add TODO for two-reader consistency risk (processor.rs)
- Group signet_hot imports across 6 RPC files
- Move supported methods above "Unsupported" comment (eth/mod.rs)
- Hoist function-scoped imports to module level (eth_rpc.rs)
- Fix stale signet_rpc_storage reference (eth_rpc.rs)
- Differentiate HTTP/WS doc comments, fix Result type (serve.rs)
- Wrap cold storage polling loop in 30s timeout (context.rs)
- Remove dead signet_events_in_range method (context.rs)
- Update README to reflect new API types

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
- Remove `not_supported` pattern; unregistered methods return
  `method_not_found` by default in ajj (threads 14, 15)
- Simplify `SubscriptionNotification`: hardcode `jsonrpc`/`method` in
  manual `Serialize` impl instead of storing as fields (threads 18, 19)
- Change `send_order` return type to `ResponsePayload<(), SignetError>`
  and add fire-and-forget doc comment (threads 5, 7)
- Use `ctx.resolve_header()` (hot storage) instead of
  `cold.get_header_by_number()` in debug endpoints (threads 12, 13)
- Replace `DebugError::Cold(String)` / `Hot(String)` with concrete
  `#[from]` error types; remove `Clone` derive and `into_string`
  (thread 10)
- Parallelize gas oracle transaction reads with `JoinSet` (thread 21)
- Add `tokio-stream` and `tokio-util` to workspace deps (thread 22)
- Add blob gas vec compatibility comment (thread 23)
- Add `State<Db>` / `DatabaseCommit` documentation (thread 20)
- Update README with namespace overview and unsupported methods (thread 16)
- Add blank lines in lib.rs between module groups (thread 2)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
.map_err(Into::<eyre::Report>::into)?
.wrap_err("parent ru block not present in DB")
.inspect_err(|e| error!(%e))?;
let parent_header = signet_types::primitives::SealedHeader::new(parent_header.into_inner());
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is this type conversion doing? why can't we use it without converting. add a table of types to the comment response

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Claude Code]

Here is the type table:

Expression Type Source
get_header() returns signet_storage_types::SealedHeader = alloy::consensus::Sealed<Header> alloy sealed wrapper
.into_inner() yields alloy::consensus::Header unwraps alloy seal
signet_types::primitives::SealedHeader::new(...) signet_types::primitives::SealedHeader re-wraps with OnceLock<BlockHash>

The conversion is not redundant — it bridges two different SealedHeader types. SignetDriver::new() requires signet_types::primitives::SealedHeader. The precomputed hash from storage is discarded, but the signet type lazily recomputes it via OnceLock.

prestwich and others added 2 commits February 16, 2026 10:17
… Paris

`EthereumHardfork` is a bitflags type where each hardfork is an
independent bit. All callers of `load_genesis()` were passing only
`EthereumHardfork::Paris`, so `genesis_header()` never set
`base_fee_per_gas` (a London feature) because the London bit was unset.
The test context worked around this by patching the header after the
fact.

This adds `genesis_hardforks()` to signet-genesis, which derives the
correct set of active hardfork flags by inspecting the chain config's
activation blocks and timestamps. Per-network LazyLock statics and a
`GenesisSpec::genesis_hardforks()` method are also provided. The
workaround in the test context is removed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… PairedHeights

- Unify BlockTags + notification sender into ChainNotifier shared struct
- Replace log-only cold_lag check with proper storage reconciliation
  (unwind to min of hot/cold tips on startup)
- Fix PairedHeights 0/0 fallback to use genesis heights with let-else
- Remove TODO about reader snapshots and redundant map_err
- Replace fully-qualified HotDbRead/HistoryRead syntax with method calls

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

/// Get the active spec id at the given timestamp.
fn spec_id(&self, timestamp: u64) -> SpecId {
crate::revm_spec(&self.chain_spec, timestamp)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this in favor of holding an EthereumHardforks instance

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Claude Code]

Done. The processor is now instantiated per-block with an EthereumHardfork bitflags value computed by the caller. Deleted utils.rs (containing revm_spec and assert_in_range) and removed reth-chainspec from the block processor. The node constructs a fresh processor for each block in process_committed_chain via EthereumHardfork::active_hardforks(&config, block_number, timestamp). Only alias_oracle and blob_cacher moved to SignetNode fields — the rest are already accessible from existing fields.

.signet_events(signet_events)
.zenith_header(zenith_header)
.build()
.map_err(|e| eyre::eyre!("failed to build ExecutedBlock: {e}"))
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be wrap_err. under what circumstances could this fail?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Claude Code]

Done — changed to wrap_err("failed to build ExecutedBlock"). This can only fail if a required builder field is missing (MissingFieldError). All four fields are set above so this is purely defensive.

/// Build an [`ExecutedBlock`] from processor outputs.
#[instrument(skip_all)]
fn commit_evm_results<'a>(
fn build_executed_block(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is invoked on the output of run_evm.
could we refactor to havre run_evm return this? suggest improved flows that minimize passing args

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Claude Code]

Done — build_executed_block is merged into run_evm, which now returns eyre::Result<ExecutedBlock> directly. Metrics recording moved inside run_evm. process_block simplifies to record_extracts + run_evm.

The builder previously only loaded genesis into hot storage. Cold-backed
RPC queries for block 0 would fail. Now prebuild checks cold
independently and writes the genesis block if absent.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
if let Some(chain) = notification.reverted_chain() {
reverted = self.on_host_revert(&chain).wrap_err("error encountered during revert")?;
self.on_host_revert(&chain).wrap_err("error encountered during revert")?;
changed = true;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is not necessarily correct, as notifications may conceivably be no-ops

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Claude Code]

Fixed — both on_host_revert and process_committed_chain now return bool. on_host_revert returns false when the chain tip is at or below the rollup genesis (early return, no unwind). process_committed_chain returns false when no blocks pass the height filter.

self.process_committed_chain(&chain)
.await
.wrap_err("error encountered during commit")?;
changed = true;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Claude Code]

Addressed with the same fix — see reply above.


// Update the RPC's block information
self.update_canon_heights(ru_height)?;
let reader = self.storage.reader()?;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a repeated pattern. load, check last, drop. DRY it

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Claude Code]

Done — added a last_rollup_block(&self) -> eyre::Result<u64> helper that encapsulates the reader + last_block_number + drop pattern. Replaced all four occurrences (in start, start_inner, process_committed_chain, and update_status).


use alloy::{consensus::Transaction, primitives::U256};
use signet_cold::{ColdStorageError, ColdStorageReadHandle, HeaderSpecifier};

Copy link
Member Author

@prestwich prestwich Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: no newline

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Claude Code]

Fixed — removed the blank line between imports and let the formatter re-order them.

Copy link
Member Author

@prestwich prestwich left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how is the storage backend configured in node config?

… merge gas cache

- Bump signet-sdk crates from 0.16.0-rc.8 to 0.16.0-rc.11
- Migrate to new block primitives (Sealed<Header>, SealedBlock<T>)
- Replace ChainSpec with EthereumHardfork bitflags in block processor
- Restructure processor to be instantiated per-block instead of held
- Merge build_executed_block into run_evm, change map_err to wrap_err
- Fix changed flag: on_host_revert/process_committed_chain return bool
- DRY reader/last_block/drop pattern into last_rollup_block() helper
- Remove blank line between imports in gas_oracle.rs
- Merge PR #80: add lock-free GasOracleCache for tip suggestions

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
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.

2 participants