Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions crates/nexum-runtime/src/engine_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ pub struct EngineConfig {
#[serde(default)]
pub engine: EngineSection,
/// Per-module wasmtime resource limits. Applies uniformly to every
/// module; per-module overrides land in 0.3.
/// module.
#[serde(default)]
pub limits: ModuleLimits,
/// Per-chain RPC URLs keyed by EIP-155 chain id. Numeric TOML keys
Expand All @@ -176,10 +176,7 @@ pub struct EngineConfig {
#[serde(default)]
pub extensions: HashMap<String, toml::Value>,
/// Modules the supervisor should boot. Each entry resolves a
/// `(component.wasm, module.toml)` pair on the local filesystem
/// for 0.2 - content-addressed resolution (Swarm / OCI /
/// `[[content.sources]]`) lands in 0.3 per
/// `docs/03-module-discovery.md`.
/// `(component.wasm, module.toml)` pair on the local filesystem.
#[serde(default)]
pub modules: Vec<ModuleEntry>,
/// Provider components the supervisor should boot alongside the
Expand Down Expand Up @@ -271,8 +268,8 @@ fn default_log_backfill_concurrency() -> usize {
/// `[engine.metrics]` config. When `enabled = true` the engine starts
/// a Prometheus HTTP exporter on `bind_addr` and serves `/metrics`.
///
/// Default: disabled. Operators opt in explicitly so the M3 / M4
/// runbook smoke runs do not bind a port unintentionally.
/// Default: disabled. Operators opt in explicitly so a run does not
/// bind a port unintentionally.
#[derive(Debug, Deserialize)]
pub struct MetricsSection {
#[serde(default)]
Expand Down
6 changes: 3 additions & 3 deletions crates/nexum-runtime/src/host/impls/identity.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! `nexum:host/identity`: deferred to 0.3 (keystore / KMS backend).
//! `accounts()` returns an empty roster so guests can probe-then-skip;
//! signing returns `unsupported`.
//! `nexum:host/identity`: unimplemented stub. `accounts()` returns an
//! empty roster so guests can probe-then-skip; signing returns
//! `unsupported`.

use crate::bindings::nexum;
use crate::bindings::nexum::host::types::Fault;
Expand Down
7 changes: 3 additions & 4 deletions crates/nexum-runtime/src/host/impls/messaging.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
//! `nexum:host/messaging`: the Waku backend is deferred to 0.3, so
//! `publish` reports `unsupported` and `query` returns empty, the same
//! posture as `identity::accounts`. The per-store topic scope is enforced
//! ahead of that stub: a provider carrying a
//! `nexum:host/messaging`: unimplemented stub. `publish` reports
//! `unsupported` and `query` returns empty. The per-store topic scope is
//! enforced ahead of that stub: a provider carrying a
//! `[[adapters]].messaging_topics` grant may only publish within it, so
//! the egress boundary is live even though delivery is not.

Expand Down
3 changes: 2 additions & 1 deletion crates/nexum-runtime/src/host/impls/remote_store.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//! `nexum:host/remote-store`: deferred to 0.3 (Swarm backend).
//! `nexum:host/remote-store`: unimplemented stub; every call returns the
//! unsupported fault.

use crate::bindings::nexum;
use crate::bindings::nexum::host::types::Fault;
Expand Down
7 changes: 3 additions & 4 deletions crates/nexum-runtime/src/host/provider_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,9 @@ const DEFAULT_POLL_INTERVAL: Duration = Duration::from_secs(2);

/// Transport retry-layer parameters. `watch_canonical_logs_from` surfaces
/// RPC errors to the caller and ends the stream on the first one unless
/// the transport retries it (per alloy's own guidance on that builder).
/// This layer heals transient blips below the poller, so a momentary node
/// hiccup does not force a re-open - and a re-open is exactly where a gap
/// could reappear.
/// the transport retries it. This layer heals transient blips below the
/// poller, so a momentary node hiccup does not force a re-open, which is
/// exactly where a gap could reappear.
const RPC_MAX_RETRIES: u32 = 10;
const RPC_RETRY_BACKOFF_MS: u64 = 300;
/// Compute-units-per-second budget the retry layer paces rate-limited
Expand Down
19 changes: 7 additions & 12 deletions crates/nexum-runtime/src/manifest/mod.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,16 @@
//! `module.toml` parser and capability-enforcement helpers (0.2 scope).
//! `module.toml` parser and capability-enforcement helpers.
//!
//! 0.2 intentionally ships a slim subset of the manifest spec:
//!
//! - `[capabilities].required` is parsed and validated (names must be in
//! the known capability set; the 0.2 reference engine always provides
//! all of them, so this is a sanity check + future-proofing).
//! - `[capabilities].optional` is parsed and logged; trap-stub fallback
//! for absent optionals is deferred to 0.3.
//! - `[capabilities].required` is parsed and validated: names must be in
//! the known capability set, which the engine always provides.
//! - `[capabilities].optional` is parsed and logged.
//! - `[capabilities.http].allow` is parsed and consulted by the
//! wasi:http gate before any outbound call.
//! - `[config]` is flattened to `Vec<(String, String)>` and passed to the
//! module's `init`. Typed `config-value` variant is deferred to 0.3.
//! module's `init`.
//!
//! When the manifest file is missing or has no `[capabilities]` section,
//! a deprecation warning is emitted and the engine falls back to 0.1
//! behaviour (treat every linked capability as required). This fallback
//! will be removed in 0.3.
//! a deprecation warning is emitted and the engine falls back to treating
//! every linked capability as required.
//!
//! ## Layout
//!
Expand Down
15 changes: 7 additions & 8 deletions crates/nexum-runtime/src/manifest/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ pub struct Manifest {
pub config: toml::Table,
/// Event subscriptions the runtime wires before calling
/// `_init`. See `docs/02-modules-events-packaging.md` for the
/// schema; 0.2 implements `block` and `chain-log` kinds, `cron` is
/// parsed and ignored (deferred to 0.3).
/// schema. Implements `block` and `chain-log` kinds; `cron` is
/// parsed and ignored.
#[serde(default, rename = "subscription")]
pub subscriptions: Vec<Subscription>,
/// Extension-owned sections: every non-core top-level key, parsed
Expand All @@ -54,15 +54,15 @@ pub type ExtensionSections = BTreeMap<String, toml::Value>;
/// fails loudly rather than silently disabling an event source.
#[derive(Debug, Clone)]
pub enum Subscription {
/// New-block events. Fan-out is shared per chain - the
/// New-block events. Fan-out is shared per chain: the
/// supervisor opens one subscription per chain id and routes to
/// every module that asked for blocks on that chain.
Block {
/// EVM chain id.
chain_id: u64,
},
/// Chain-log events matching `address` + topic-0. Fan-out is
/// per-module - the supervisor opens one subscription per
/// per-module: the supervisor opens one subscription per
/// `[[subscription]]` entry and tags emitted events with the
/// owning module.
ChainLog {
Expand All @@ -71,7 +71,7 @@ pub enum Subscription {
/// Contract address as `0x`-prefixed 20-byte hex. Optional.
address: Option<String>,
/// Topic-0 of the event the module wants to consume. `0x`-
/// prefixed 32-byte hex. Optional - when absent the
/// prefixed 32-byte hex. Optional: when absent the
/// subscription matches every event from the address(es).
event_signature: Option<String>,
/// Resume across engine restarts. When `true` the host persists a
Expand All @@ -87,10 +87,9 @@ pub enum Subscription {
/// tolerates dropping the oldest missed blocks.
max_lookback: Option<u64>,
},
/// Cron-scheduled tick. 0.2 parses but does not dispatch; the
/// Cron-scheduled tick. Parsed but not dispatched; the
/// supervisor emits a warning so the operator knows the
/// declaration is currently inert. `schedule` is preserved so a
/// 0.3 dispatcher can pick it up without re-parsing the manifest.
/// declaration is currently inert. `schedule` is preserved verbatim.
Cron {
/// Standard 5-field cron expression.
#[allow(dead_code)]
Expand Down
2 changes: 1 addition & 1 deletion crates/nexum-runtime/src/runtime/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -670,7 +670,7 @@ mod tests {

/// `open_block_streams` spawns one independent reconnect task per chain.
/// Per-chain task isolation means a slow or reconnecting chain does not
/// delay events from other chains each chain has its own mpsc channel
/// delay events from other chains: each chain has its own mpsc channel
/// and backoff timer.
#[tokio::test]
async fn open_block_streams_opens_one_task_per_chain() {
Expand Down
7 changes: 3 additions & 4 deletions crates/nexum-runtime/src/runtime/restart_policy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,13 @@
//! | ... | doubles |
//! | 9+ | capped at 5 minutes |
//!
//! State is in-memory per supervisor process. Persistence across
//! engine restarts is out of scope (a separate 0.3 / M5 follow-up
//! that lands alongside `submitted:{uid}` cross-restart dedup).
//! State is in-memory per supervisor process; it does not persist
//! across engine restarts.

use std::time::Duration;

/// Hard cap on the restart backoff. After ~8 doublings we plateau
/// here. Tuneable in 0.3 via `engine.toml::[engine.restart]`.
/// here.
pub const RESTART_MAX_BACKOFF: Duration = Duration::from_secs(300);

/// Compute the wait window the supervisor honours before the next
Expand Down
6 changes: 3 additions & 3 deletions crates/nexum-runtime/src/supervisor/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ async fn run_does_not_bail_when_both_stream_kinds_are_empty() {
// supervisor boundary, without loading a real wasm module.

/// Block and chain-log streams are both consumed within the same `run()`
/// session the `biased` select does not starve either event kind. One
/// session: the `biased` select does not starve either event kind. One
/// item of each kind is queued before the loop starts; `run()`'s returned
/// tally must show both were drained. A regression that breaks either
/// select arm (or reorders the `biased` polling so one side never fires)
Expand Down Expand Up @@ -259,8 +259,8 @@ async fn run_delivers_block_and_chain_log_events_without_starvation() {
/// After `run()` returns on the shutdown path, all reconnect tasks are
/// drained: the Shutdown arm calls `tasks.shutdown()`, which aborts every
/// handle and then joins each one, so no task detaches and outlives the
/// engine. (The companion contract a task parked on a dropped receiver
/// exits with `ReceiverGone` on its own is asserted directly in
/// engine. (The companion contract, a task parked on a dropped receiver
/// exiting with `ReceiverGone` on its own, is asserted directly in
/// `event_loop::tests::reconnect_task_exits_receiver_gone_when_receiver_drops`;
/// it cannot be observed here because `TaskSet::shutdown` aborts first.)
/// Issue #58.
Expand Down
4 changes: 2 additions & 2 deletions crates/nexum-runtime/src/test_utils/harness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,7 @@ chain_id = 1
rt.wait().await.expect("clean shutdown");
}

/// Blocks pushed in order arrive at the module in the same order
/// Blocks pushed in order arrive at the module in the same order:
/// the per-chain stream, the select, and the dispatch path preserve
/// delivery order. Issue #56's ordering guarantee, asserted on the
/// module's own log records rather than inferred from termination.
Expand Down Expand Up @@ -693,7 +693,7 @@ chain_id = 1
/// so a block that was picked up finishes its wasmtime call and its
/// log record survives `wait()`. The test first proves the dispatch
/// completed (log line present), then shuts down and re-reads the same
/// record after the engine is fully torn down if teardown dropped or
/// record after the engine is fully torn down: if teardown dropped or
/// truncated completed work, the second read fails. Issue #58.
#[tokio::test]
async fn harness_shutdown_preserves_completed_dispatch() {
Expand Down
8 changes: 4 additions & 4 deletions crates/nexum-sdk-test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
//!
//! The traits report failures as [`nexum_sdk::host::Fault`] rather than
//! the `Fault` `wit_bindgen::generate!` emits per-module. A module
//! bridges with a trivial converter on its own crate boundary - see the
//! bridges with a trivial converter on its own crate boundary; see the
//! tutorial for the exact shape.
//!
//! Domain test crates compose these mocks with their own scripted
Expand Down Expand Up @@ -600,11 +600,11 @@ impl RemoteStoreHost for MockRemoteStore {
///
/// # Fidelity vs the real `redb` store
///
/// Two gaps remain (deferred to the `MockRuntime` refactor, #94):
/// - **No transaction semantics** - `redb` wraps each `on_event` in an
/// Two gaps vs `redb`:
/// - **No transaction semantics**: `redb` wraps each `on_event` in an
/// implicit write transaction (commit on `Ok`, rollback on trap); this
/// mock commits every `set` immediately.
/// - **No concurrent access** - the backing `RefCell` is single-threaded,
/// - **No concurrent access**: the backing `RefCell` is single-threaded,
/// whereas `redb` uses MVCC.
#[derive(Default)]
pub struct MockLocalStore {
Expand Down
21 changes: 8 additions & 13 deletions crates/nexum-sdk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@
//! use them regardless of which world it exports. Domain layers such as
//! the CoW SDK depend on this crate and add their own surface on top.
//!
//! The crate is the shared companion to the per-module
//! `wit_bindgen::generate!` invocation: modules keep their own
//! wit-bindgen call (which emits the world-specific `Guest` trait,
//! `Fault` shape, and host import shims into the module's own
//! crate) and pull helpers and canonical primitive types from here.
//! Modules keep their own `wit_bindgen::generate!` call, which emits
//! the world-specific `Guest` trait, `Fault` shape, and host import
//! shims into the module's own crate, and pull helpers and canonical
//! primitive types from here.
//!
//! ## What lives here
//!
Expand Down Expand Up @@ -69,14 +68,10 @@
//! sink so module authors emit `tracing::info!(...)` with no host
//! parameter to thread.
//!
//! ## Why no `wit_bindgen::generate!` here
//!
//! The macro emits types into the calling crate (the module's
//! cdylib). Re-exporting wit-bindgen output from a library crate
//! would duplicate symbols and break the component-export contract.
//! Helpers in this SDK therefore take primitive types (`&[u8]`,
//! `Option<&str>`, slices) rather than the per-module `Fault`
//! type; modules unpack their `Fault` on the way in.
//! Helpers take primitive types (`&[u8]`, `Option<&str>`, slices)
//! rather than the per-module `Fault` type, so this library emits no
//! wit-bindgen output of its own; modules unpack their `Fault` on the
//! way in.
//!
//! [`Address`]: alloy_primitives::Address
//! [`B256`]: alloy_primitives::B256
Expand Down
9 changes: 3 additions & 6 deletions crates/nexum-sdk/src/wit_bindgen_macro.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
//! Declarative macro that generates the `WitBindgenHost` adapter
//! every module ships in `lib.rs`.
//!
//! Before this macro existed, each module hand-rolled ~80 lines of
//! mechanical glue: the `struct WitBindgenHost;` plus the core trait
//! impls plus the fault, chain-error, and level conversions. The code
//! differed across modules in zero places that were not bugs.
//! every module ships in `lib.rs`: the `struct WitBindgenHost;` plus
//! the core trait impls and the fault, chain-error, and level
//! conversions.
//!
//! The adapter is capability-selected: the `caps: [...]` form emits
//! only the pieces backed by the module's declared capabilities
Expand Down
11 changes: 5 additions & 6 deletions tools/load-gen/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
//! Anvil-side load generator for shepherd's M4 load test.
//! Anvil-side load generator for the runtime load test.
//!
//! Connects to an Anvil fork of Sepolia, impersonates the pinned test
//! EOA (no signer required - `anvil_impersonateAccount` skips
//! EOA (no signer required: `anvil_impersonateAccount` skips
//! signature verification), and submits N `ComposableCoW.create(...)`
//! plus M `CoWSwapEthFlow.createOrder(...)` calls per new block. The
//! resulting `ConditionalOrderCreated` and `OrderPlacement` events are
//! what shepherd's twap-monitor and ethflow-watcher dispatch on.
//! what the twap-monitor and ethflow-watcher modules dispatch on.
//!
//! Knobs (`--help` for the full list):
//! - `--anvil <url>` WebSocket URL of the Anvil fork
//! - `--twap-per-block N` calls to ComposableCoW.create per block
//! - `--ethflow-per-block M` calls to CoWSwapEthFlow.createOrder per block
//! - `--duration <minutes>` wall-clock window the loop runs for
//!
//! Pinned identities mirror `docs/operations/e2e-prep.md`:
//! EOA, ComposableCoW, TWAP handler, CoWSwapEthFlow, WETH9, COW token,
//! Safe. These are constant across the Sepolia fork.
//! Pinned identities: EOA, ComposableCoW, TWAP handler, CoWSwapEthFlow,
//! WETH9, COW token, Safe. These are constant across the Sepolia fork.

#![cfg_attr(not(test), warn(unused_crate_dependencies))]

Expand Down
Loading