Skip to content

Upgrade to commonware 2026.5#77

Merged
faddat merged 188 commits into
refcell:mainfrom
Nunchi-trade:nunchi/upgrade
May 30, 2026
Merged

Upgrade to commonware 2026.5#77
faddat merged 188 commits into
refcell:mainfrom
Nunchi-trade:nunchi/upgrade

Conversation

@faddat

@faddat faddat commented May 30, 2026

Copy link
Copy Markdown
Collaborator

This PR marks a significant evolution for Kora:

  • e2e tests in ci run
  • devnets larger than 4 nodes are possible
  • block times with a devnet on a hetzner ax41 are about 25ms
  • Kora passes a number of ethereum tests
  • Kora will undergo a public testnet beginning around June 1 or so

There are still lots of unfinished things, but Kora is a stable EVM now.

Before testnet, we will:

  • improve documentation
  • run various automated and manual tests for both performance and stability

Now is a great time to contribute by looking for stability issues in Kora. We know that some exist, but haven't found them all, that's a large part of the reason for the testnet.

faddat and others added 30 commits April 30, 2026 17:07
- Added new dependencies to `Cargo.lock` for `alloy-primitives` and `k256`.
- Updated `Justfile` to improve load generator commands with additional RPC URL options for better transaction broadcasting.
- Refactored `setup.rs` to dynamically generate genesis allocations, improving maintainability and reducing hardcoded values.
- Enhanced `loadgen` to support multiple RPC endpoints, ensuring transactions are submitted to all validators for optimal performance.
- Adjusted gas limit in configuration files to accommodate increased transaction throughput.
- Introduced a new document detailing the procedure for setting up a public Kora testnet, including prerequisites, artifact generation, and DKG ceremony instructions.
- Updated the README to reference the new public testnet runbook for users interested in multi-host public testnet configurations.
docs: add public testnet standup runbook and update README
…testnet setup

- Introduced `keygen.bash` for automated key generation with specified parameters for validators and peers.
- Created `genesis.json` to define the initial state of the blockchain with allocations for multiple addresses.
- Added `peers.json` to configure validator and bootstrapper information for the network.
- Implemented setup files for three validator nodes, including their public keys and ports.
- Removed outdated endpoint verification instructions from `public-testnet.md` to streamline documentation.
- Added support for initializing the ledger with optional genesis allocation application.
- Introduced new methods for restoring persisted snapshots in both `LedgerView` and `LedgerService`.
- Updated `Cargo.toml` files to include new dependencies for `commonware-consensus` and `commonware-storage`.
- Enhanced the runner to recover finalized state from archives, improving state management during node operation.
- Implemented `restore_persisted_digest` method in both `LedgerView` and `LedgerService` to allow restoration of finalized digests as the current persisted QMDB state.
- Enhanced the `NodeRunner` to utilize the new method for recovering finalized ledger heads from finalization archives, improving state recovery processes.
…out settings

- Added new constants for consensus timeouts, including leader, certification, retry, fetch, activity, and skip timeouts.
- Refactored the `NodeRunner` implementation to utilize these new constants, improving code readability and maintainability.
…tegy initialization

- Removed `commonware-parallel` dependency from `Cargo.lock`.
- Updated default values for various parameters in `ActorInitializer`, `ArchiveInitializer`, `BroadcastInitializer`, and `PeerInitializer` to enhance performance and resource management.
- Introduced a new method `init_with_strategy` in `ActorInitializer` to allow custom verification strategies during initialization.
- Adjusted test cases to reflect the updated default values and ensure correctness.
…iguration

- Added KORA_RUNTIME_DIR environment variable to allow users to override the default runtime storage directory for Commonware.
- Updated README and documentation to reflect the new configuration option.
- Refactored runtime storage directory logic in the runner to utilize the new environment variable.
- Enhanced Docker setup to mount the runtime directory as a tmpfs for improved performance during development.
…polish

Tighten devnet loadgen account handling
…les to root

Update the HEALTHCHECK_MODE comment in the Dockerfile to list the actual
modes supported by healthcheck.sh (dkg, p2p, ready) instead of the
misleading "validator" and "setup" references.

Move the negated README patterns from docker/.dockerignore to the root
.dockerignore, since docker-bake.hcl sets context=".." (repo root) and
Docker only reads the context-level .dockerignore.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The `signature_v` function was truncating the EIP-155 `v` value from
`u128` to `u64` with a silent fallback to `u64::MAX` on overflow. For
legacy transactions with very large chain IDs, this would persist an
invalid `v` value, breaking signature verification and producing
nonsensical RPC responses.

Widen the `v` field to `u128` in `IndexedTransaction` and `TxMetadata`
(matching the `to_eip155_value` return type), and to `U256` in
`RpcTransaction` (matching Ethereum JSON-RPC convention). This
eliminates the truncation entirely so the full EIP-155 range is
represented without data loss.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Ensure gas_price is always <= max_price unless base fee alone exceeds
  the cap. Replace clamp_fee with explicit bounds that respect the hard
  cap while still allowing a usable price when base fee is above max.

- Fix EIP-1559 gas price sampling to use effective gas price
  (min(max_fee, base_fee + tip)) instead of raw tx.gas_price, which for
  type-2 txs was max_fee_per_gas and biased estimates upward.

- Handle indexed EIP-1559 txs that lack max_fee/max_priority_fee fields
  in effective_priority_fee by returning zero instead of computing a
  misleading tip from gas_price - base_fee.

- Add focused tests for effective_priority_fee with EIP-1559 txs,
  gas price sampling with type-2 txs, and max_price enforcement.

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

Address PR review feedback:
- Replace silent `continue` with `ConsensusError::SnapshotNotFound` error
  in the post-commit compaction loop so inconsistent store state is surfaced
  rather than masked.
- Add `change_len()` and `changes_is_empty()` inspection helpers to
  `OverlayState` and assert overlay emptiness in the compaction regression
  test, ensuring a future refactor cannot clear `snapshot.changes` while
  leaving the overlay change set intact.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
wpank and others added 29 commits May 29, 2026 14:27
* fix(consensus): log and count equivocation events instead of silently discarding

Replace `_ => {}` catch-all arms in `seed_report_inner()` and
`NodeStateReporter::report()` with explicit match arms for
ConflictingNotarize, ConflictingFinalize, and NullifyFinalize.
Each equivocation event now logs at warn level with the signer
index and view number, increments an RPC-visible equivocation
counter on NodeState, and bumps a labelled Prometheus counter
(kora_equivocations_total) so operators can alert on Byzantine
behavior.

Closes #270

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

* style: fix rustfmt formatting in reporters and runner

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

---------

Co-authored-by: will pankiewicz <will@macbook.local>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
The health check's `ready` mode previously only checked eth_blockNumber
advancement, which has a blind spot: a node can serve stale RPC data
while being disconnected from consensus. This adds a Step 4 that queries
kora_nodeStatus to detect consensus-disconnected nodes:

- Immediate failure if partitionStatus is "partitioned" (below BFT quorum)
- Optional HEALTHCHECK_MIN_PEERS absolute peer floor
- Finalized-count stall detection using the same threshold as block stalls

The kora_nodeStatus check is soft: if the RPC method is unavailable
(older binary, secondary node), the script falls back to the existing
eth_blockNumber stall detection.

Closes #295

Co-authored-by: will pankiewicz <will@macbook.local>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…(#338)

Prevent unbounded iteration DoS in eth_getLogs by:

1. Clamping to_block to chain tip in BlockIndex::get_logs() so requests
   with toBlock far beyond the head no longer iterate billions of
   empty HashMap lookups while holding a read lock.

2. Enforcing a maximum block range of 10,000 in IndexedStateProvider,
   returning an InvalidParams error when exceeded (aligned with Infura).

3. Implementing EIP-234 blockHash filter support: blockHash is mutually
   exclusive with fromBlock/toBlock, resolves to a single-block range,
   and returns an error for nonexistent hashes.

4. Rejecting fromBlock > toBlock with an explicit error.

Closes #256

Co-authored-by: will pankiewicz <will@macbook.local>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix(rpc): wire eth_syncing to actual catch-up state

eth_syncing was hardcoded to return false, hiding post-recovery
catch-up status from load balancers, monitoring, and wallets.

Wire the existing catch-up detection logic through NodeState so that
eth_syncing returns a SyncInfo object (startingBlock, currentBlock,
highestBlock) while the node is replaying blocks after snapshot
recovery, and false once verification has advanced past the threshold.

Closes #266

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

* style: apply nightly rustfmt formatting fixes

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

---------

Co-authored-by: will pankiewicz <will@macbook.local>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix(rpc): add missing withdrawals fields to RpcBlock response

Post-Shanghai Ethereum blocks require `withdrawals` and `withdrawalsRoot`
fields. Their absence caused client-side deserialization failures when
tools expected the standard block shape. Since Kora has no beacon chain,
withdrawals is always empty and the root is the empty trie hash.

Closes #290

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

* style: fix rustfmt formatting in RPC test helpers

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

---------

Co-authored-by: will pankiewicz <will@macbook.local>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix(rpc): disable nonce/balance/basefee checks for eth_call and eth_estimateGas simulations

simulate_call() enforced full transaction validation (nonce, balance,
base fee) during eth_call and eth_estimateGas. This caused failures for
any account with nonce > 0 when callers omit the nonce field (standard
behavior for all Ethereum tooling), and for all callers that omit
gasPrice (also standard). Geth and Reth disable these checks for
simulation RPCs.

Set disable_nonce_check, disable_balance_check, and disable_base_fee
on the CfgEnv in simulate_call() so simulations behave like standard
Ethereum clients.

Closes #280
Closes #287

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

* fix(deps): enable revm features for simulation balance/basefee check bypass

The `disable_balance_check` and `disable_base_fee` fields on `CfgEnv`
are gated behind `optional_balance_check` and `optional_no_base_fee`
cargo features respectively. Enable them so `simulate_call` can skip
these validation checks during eth_call/eth_estimateGas.

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

---------

Co-authored-by: will pankiewicz <will@macbook.local>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…tabaseCommit (#303)

Add `.filter(|(_, v)| v.is_changed())` before collecting storage slots
in both `extract_changes()` and the `DatabaseCommit::commit()` impl.
Previously, every storage slot touched by SLOAD was written to QMDB
even when its value was unchanged, causing significant write
amplification (2-10x for typical DeFi transactions).

Closes #274

Co-authored-by: will pankiewicz <will@macbook.local>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…(#305)

* fix(config): preserve and validate genesis chain_id during bootstrap

The genesis.json chain_id field was silently discarded via `..` in the
GenesisJson destructuring. Add chain_id to BootstrapConfig so it
survives loading, and validate at validator startup that it matches the
node's configured chain_id. A mismatch now produces a clear error
instead of silent misconfiguration.

Closes #284

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

* style(e2e): fix rustfmt formatting in harness.rs

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

---------

Co-authored-by: will pankiewicz <will@macbook.local>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
… (#312)

All cryptographic key material (Ed25519 identity seeds and BLS12-381
threshold shares) was written via std::fs::write which inherits the
process umask, typically producing world-readable 0644 files. Replace
every key-write site with OpenOptions::mode(0o600) so files are created
owner-read/write only.

Affected write sites (5 total):
- bin/keygen/src/setup.rs: validator and secondary identity keys
- bin/keygen/src/dkg_deal.rs: trusted-dealer BLS share.key
- crates/node/dkg/src/output.rs: interactive DKG share.key
- crates/node/config/src/node.rs: runtime-generated validator.key

Closes #281

Co-authored-by: will pankiewicz <will@macbook.local>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix(indexer): prune old BlockIndex entries to prevent OOM

BlockIndex stores blocks, transactions, receipts, and logs in five
unbounded HashMaps that grow forever, eventually OOM-killing the
validator. Add a `prune_before(min_block_number)` method that evicts
all index entries for blocks below the retention window and call it
after each finalized block insertion.

The retention window of 10,000 blocks (~5 min at 33 blocks/s) exceeds
the 256-block EVM BLOCKHASH requirement, so `recent_block_hashes`
continues to work correctly.

Closes #262

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

* fix(indexer): remove explicit ref patterns in closure for Rust 2024 edition

Rust 2024 edition disallows explicit `&` dereference patterns inside
implicitly-borrowing closures. Replace `|(&num, _)|` with `|(num, _)|`
and dereference via `*` / `**` operators instead.

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

---------

Co-authored-by: will pankiewicz <will@macbook.local>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…#314)

* fix(consensus): activate timestamp validation in block verification

`validate_header_against_parent()` in revm.rs enforced timestamp
monotonicity and future-drift bounds, but was never called during
block verification. This meant a malicious leader could propose blocks
with non-increasing or far-future timestamps without rejection.

Add two timestamp checks to `verify_block()` in app.rs:

1. Monotonicity: block timestamp must be strictly greater than the
   parent timestamp (matching the contract in `Block::next_timestamp`).
2. Future-drift: block timestamp must not exceed the validator's
   wall-clock time by more than 15 seconds.

The parent timestamp is threaded through the verify chain: the
`verify()` method captures the already-verified parent's timestamp
from the ancestry stream and tracks it across the oldest-to-newest
verification loop. Both checks are skipped during catch-up mode
(certificate-trusted blocks).

Closes #261

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

* style: collapse nested if-let for clippy collapsible_if lint

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

---------

Co-authored-by: will pankiewicz <will@macbook.local>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix(runtime): use available CPU cores for tokio worker threads

The commonware runtime was initialized with Config::default() which
hard-codes 2 worker threads, starving consensus under load. Add a
configurable worker_threads field to NodeConfig that defaults to
min(available_parallelism, 8) and wire it into both the validator
runner and secondary node runtime initialization paths. Reject
worker_threads=0 at config validation time.

Closes #255

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

* style: fix rustfmt formatting for simplex::Engine::new call

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

---------

Co-authored-by: will pankiewicz <will@macbook.local>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…t (#316)

Add sensible default RUST_LOG filter with per-component levels when
RUST_LOG is not explicitly set. Add LOG_FORMAT=json env var support
for structured JSON log output in production log pipelines.

Closes #291

Co-authored-by: will pankiewicz <will@macbook.local>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…PC alive (#318)

Three fixes for unsafe shutdown behavior:

1. Watchdog: `Error::Closed` now returns instead of calling `abort()`.
   When SIGTERM fires, the runtime drops all contexts, which resolves
   watched handles with `Error::Closed`. Previously this raced to
   `std::process::abort()` (SIGABRT / exit 134), bypassing all cleanup.
   Now the watchdog recognizes this as normal shutdown and returns cleanly.

2. Signal handler: adds a 200ms grace window after the shutdown signal
   so in-flight QMDB commits and log drains can complete before the
   runtime tears down task contexts.

3. RPC handles: `drop(rpc.start())` immediately cancelled both the HTTP
   and JSON-RPC server tasks. Changed to `let _rpc_handle = rpc.start()`
   so the handle lives until the enclosing scope returns, keeping RPC
   alive during normal operation and stopping it cleanly on shutdown.

Closes #257

Co-authored-by: will pankiewicz <will@macbook.local>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat(metrics): add unpersisted snapshot depth gauge for persistence pipeline observability

Add kora_unpersisted_snapshot_depth and kora_snapshot_store_total Prometheus
gauges so operators can detect when the QMDB persistence pipeline falls behind
block production. The gauges are updated on every finalized block in the
FinalizedReporter, giving continuous visibility into snapshot store health.

- Add InMemorySnapshotStore::unpersisted_count() with unit test
- Add LedgerView/LedgerService::snapshot_store_stats() accessor
- Register both gauges in AppMetrics
- Wire gauge updates in handle_finalized_update after each finalization

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

* style: fix rustfmt formatting in ledger and reporters tests

Apply cargo fmt formatting to setup_ledger calls in ledger tests and
Block::new/assert_eq! calls in reporters tests to pass CI format check.

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

---------

Co-authored-by: will pankiewicz <will@macbook.local>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
… (#321)

* fix(execution): make block beneficiary configurable via fee_recipient

Add `fee_recipient` field to `ExecutionConfig` so operators can specify
an address to receive EIP-1559 priority fees instead of burning them to
`Address::ZERO`.  The setting is threaded through all block context
construction sites (RevmApplication, RevmContextProvider,
ProposalBuilder) and the RPC miner field to ensure deterministic
re-execution.

Closes #275

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

* fix(ci): resolve format and clippy failures

Reformat simplex::Engine::new() call to match rustfmt style (args on
separate lines) and replace match-on-Option with map_or_else to satisfy
clippy::option_if_let_else.

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

* fix(config): resolve use-of-moved-value in serialize_optional_address

Replace map_or_else with match to avoid moving serializer into two
closures, which fails because Serializer is not Copy.

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

* fix(rpc): mark IndexedStateProvider::new as const fn

Clippy missing_const_for_fn lint.

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

---------

Co-authored-by: will pankiewicz <will@macbook.local>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix: repair main after merge regressions

* ci: cover workspace and e2e tests

* ci: run full kora e2e suite
* fix(rpc): compute block size instead of returning 0x0

Add a `size` field to `IndexedBlock` and populate it at index time by
summing the raw EIP-2718 transaction envelope bytes plus a fixed 508-byte
header overhead (approximate RLP-encoded header size). Use the stored
value in `indexed_block_to_rpc` instead of hardcoding `U64::ZERO`.

Closes #272

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

* style: fix rustfmt formatting in reporters and runner

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

---------

Co-authored-by: will pankiewicz <will@macbook.local>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
SeedReporter only fires on nodes that independently construct the
finalization certificate, not on nodes that receive it from the network.
With larger validator sets (7+), some nodes may never store a seed for a
given digest. Relax the assertion to only verify seed consistency across
nodes that have them, rather than requiring all nodes have seeds.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat(metrics): add EVM execution time histogram and RPC request counter

Add two new operational metrics to AppMetrics:

- `kora_evm_execution_seconds` (Histogram): Records pure EVM execution
  time per block, excluding proposal overhead (snapshot lookup, tx
  selection, state root computation). Observed in both build_block and
  verify_block where exec_elapsed was already computed but only logged.

- `kora_rpc_requests_total` (Counter): Counts every incoming JSON-RPC
  request, including those rejected by rate limiting. Incremented in the
  RateLimitedRpcService middleware before rate-limit checks.

Closes #288

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

* style: fix rustfmt formatting for simplex::Engine::new call

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

* fix: add missing rpc_requests_total field and regenerate Cargo.lock

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

* fix: reset Cargo.lock to main (revert over-eager lockfile regeneration)

The previous `cargo generate-lockfile` upgraded commonware-cryptography
from 2026.4.0 to 2026.5.0, which broke the `From<SigningKey>` impl and
triggered RUSTSEC-2025-0055. Reset to main's lockfile with only the
minimal addition of prometheus-client to kora-rpc's dependency list.

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

---------

Co-authored-by: will pankiewicz <will@macbook.local>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
… (#320)

* fix(rpc): return pending nonce from txpool in eth_getTransactionCount

When called with block tag "pending", eth_getTransactionCount now
queries the transaction pool for the sender's next expected nonce and
returns max(finalized_nonce, pool_nonce). This allows wallets and
scripts that submit multiple transactions sequentially to obtain
strictly increasing nonces without waiting for prior transactions to
finalize.

Closes #273

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

* style: fix formatting and clippy warnings

Collapse nested `if` statements in `get_transaction_count` to satisfy
`clippy::collapsible_if`, and reformat function call arguments and
assert_eq! macros to match `cargo fmt` (nightly, style_edition 2024).

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

---------

Co-authored-by: will pankiewicz <will@macbook.local>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…317)

* fix(rpc): compute block-level logsBloom from receipt Bloom filters

The block-level logsBloom was hardcoded to 256 zero bytes, breaking
Bloom-filter-based log pruning in eth_getLogs and light client queries.

Add a `logs_bloom` field to `IndexedBlock` and compute it as the bitwise
OR of all receipt-level Bloom filters during block indexing. The RPC
layer now returns the real aggregate Bloom instead of zeros.

Closes #285

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

* style: fix rustfmt formatting in reporters and runner

Expand function arguments onto separate lines for Block::new,
assert_eq!, and simplex::Engine::new calls to satisfy cargo fmt.

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

---------

Co-authored-by: will pankiewicz <will@macbook.local>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Jacob Gadikian <jacobgadikian@gmail.com>
…ec (#307)

Use error code 3 (execution reverted) instead of -32015, and pass raw
revert bytes in the JSON-RPC `data` field instead of stringifying them
into the message. This enables standard tooling (ethers.js, viem,
Foundry, Hardhat) to decode revert reasons and custom errors.

Closes #254

Co-authored-by: will pankiewicz <will@macbook.local>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Jacob Gadikian <jacobgadikian@gmail.com>
…#302)

Add `.enable_ws_ping(PingConfig::new())` to both `Server::builder()`
call sites so the server sends periodic WebSocket ping frames and
detects zombie connections that no longer respond with pong.

Closes #289

Co-authored-by: will pankiewicz <will@macbook.local>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Jacob Gadikian <jacobgadikian@gmail.com>
…559) (#346)

* fix(executor): wire calculate_base_fee() into block production (EIP-1559)

The base fee was hardcoded to INITIAL_BASE_FEE (1 gwei) for every block.
A correct calculate_base_fee() existed but was never called during block
construction. This wires the existing function into all block production
and verification paths so the base fee adjusts dynamically based on
parent block gas usage per the EIP-1559 algorithm.

Changes:
- RevmApplication: add block_fees cache to track per-block gas_used and
  base_fee_per_gas keyed by consensus digest; seed genesis on startup
- block_context() now takes parent_digest and computes the base fee via
  calculate_base_fee() from the cached parent gas data
- build_block/verify_block record each block's fee data after execution
- RevmContextProvider (finalization path): look up parent block from the
  BlockIndex to compute dynamic base fee for re-execution
- replay_finalized_block: re-index blocks with real gas_used from
  execution so subsequent replay blocks derive correct base fees
- seed_block_fee_cache: populate the fee cache from the BlockIndex after
  restart recovery so the first new blocks use correct base fees

Closes #260

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

* fix(runner): clone block_index Arc before move and fix rustfmt formatting

The block_index Arc was moved into with_block_index() and then borrowed
later in seed_block_fee_cache(), causing E0382. Clone the Arc before the
move. Also reformat simplex::Engine::new() call to satisfy rustfmt
style_edition=2024 line-width rules.

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

* fix: add missing receipts_root and transactions_root to replay IndexedBlock

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

* fix: add missing size field to replay IndexedBlock

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

---------

Co-authored-by: will pankiewicz <will@macbook.local>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Jacob Gadikian <jacobgadikian@gmail.com>
The logs_bloom field was added to IndexedBlock by #317 but the
replay_finalized_block function was not updated, causing a compile error.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add `set_batch_request_config(BatchRequestConfig::Limit(N))` to both
`Server::builder()` call sites so that oversized batches are rejected
before consuming rate-limit tokens or server resources.

A configurable `max_batch_size` field (default 100) is added to
`RpcServerConfig` and wired through `RpcServer` and `JsonRpcServer`.

Closes #253

Co-authored-by: will pankiewicz <will@macbook.local>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Jacob Gadikian <jacobgadikian@gmail.com>
* fix(rpc): add CORS middleware to jsonrpsee JSON-RPC server

The CORS infrastructure (build_cors_layer, CorsConfig) was only applied
to the axum HTTP status server (/health, /status), not to the jsonrpsee
JSON-RPC server that handles all eth_*, net_*, web3_*, and kora_* RPC
methods. This caused browsers to block all cross-origin requests to the
JSON-RPC endpoint, making browser-based dApps unable to interact with
the node.

Apply the same CORS layer to the jsonrpsee server via
set_http_middleware() in both RpcServer::start() and
JsonRpcServer::start(). Add a cors_config field and with_cors() builder
method to JsonRpcServer for parity with RpcServer.

Closes #263

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

* fix(rpc): use tower 0.4 ServiceBuilder for jsonrpsee set_http_middleware

jsonrpsee 0.24 depends on tower 0.4, so its `set_http_middleware` method
expects a `tower::ServiceBuilder` from tower 0.4. The crate also depends
on tower 0.5 (for `ConcurrencyLimitLayer` and other middleware), which
causes a type mismatch when tower 0.5's `ServiceBuilder` is passed to
jsonrpsee's API.

Add a renamed `tower_04` dependency (tower 0.4) and use
`tower_04::ServiceBuilder` specifically for the two `set_http_middleware`
call sites. The `CorsLayer` from tower-http 0.6 works with both tower
versions since they share the same `tower-layer` 0.3.x types.

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

* chore: regenerate Cargo.lock

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

* fix: reset Cargo.lock to main (revert over-eager lockfile regeneration)

The previous `cargo generate-lockfile` upgraded commonware-cryptography
from 2026.4.0 to 2026.5.0, breaking the `From<SigningKey>` impl and
triggering RUSTSEC-2025-0055. Reset to main's lockfile which already
contains tower 0.4.13; the only delta is wiring it into kora-rpc.

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

---------

Co-authored-by: will pankiewicz <will@macbook.local>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
…… (#452)

* chore(dependencies): update commonware packages to version 2026.5.0 and add new dependencies

- Updated commonware packages in Cargo.toml to version 2026.5.0.
- Removed the specific version for sha2 in Cargo.lock.
- Added new packages: ark-ed-on-bls12-381-bandersnatch and commonware-formatting.
- Removed unused dependency ed25519-consensus from keygen.
- Introduced nextest configuration for e2e tests.
- Refactored imports in keygen source files for clarity and consistency.

* fix(block): update next_timestamp logic to allow same second blocks and improve timestamp validation

- Refactored `next_timestamp` to allow blocks produced in the same second to share the same timestamp.
- Updated related tests to reflect the new behavior and ensure correct handling of `u64::MAX` timestamps.
- Adjusted comments in the code to clarify the timestamp validation rules, emphasizing that timestamps should not move backwards.

* tidy

* chore(dependencies): update deny.toml to address new RUSTSEC advisories

- Added RUSTSEC-2025-0055 to the ignore list due to ark-relations dependency issues.
- Removed deprecated dependencies from the skip list in deny.toml for better clarity.
@faddat faddat merged commit 446b4c7 into refcell:main May 30, 2026
7 checks passed
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.

4 participants