Skip to content

feat(ethflow-watcher): workspace + skeleton (BLEU-831)#8

Open
brunota20 wants to merge 1 commit into
dev/m2-basefrom
feat/ethflow-watcher-skeleton-bleu-831
Open

feat(ethflow-watcher): workspace + skeleton (BLEU-831)#8
brunota20 wants to merge 1 commit into
dev/m2-basefrom
feat/ethflow-watcher-skeleton-bleu-831

Conversation

@brunota20

Copy link
Copy Markdown
Collaborator

Summary

Mirror of the `twap-monitor` skeleton (BLEU-825) for the EthFlow path:

  • `modules/ethflow-watcher/` added to workspace
  • `[lib] crate-type = ["cdylib"]` for WASM Component output
  • Deps pre-pulled so BLEU-832 / BLEU-833 don't churn Cargo.toml: `cowprotocol` (no-default-features), `alloy-primitives`, `alloy-sol-types`, `wit-bindgen`
  • `src/lib.rs` binds against `shepherd:cow/shepherd`; `init` logs once, `on_event(Event::Logs)` logs a placeholder until BLEU-832 decodes `OrderPlacement`

Independent of the twap-monitor stack — branches from `dev/m2-base` directly.

Linear: BLEU-831.

Test plan

  • `cargo build --target wasm32-wasip2 --release -p ethflow-watcher` — emits a 67 KB `ethflow_watcher.wasm` (within ~3 KB of twap-monitor's skeleton).
  • `cargo check --target wasm32-wasip2 -p ethflow-watcher`.
  • `cargo clippy --target wasm32-wasip2 -p ethflow-watcher -- -Dwarnings`.
  • Engine load — gated on `module.toml` (BLEU-834).

Mirror of the twap-monitor skeleton (BLEU-825) for the EthFlow
path. Adds modules/ethflow-watcher/ as a workspace member, with
[lib] crate-type = ["cdylib"] for WASM Component output, and the
same dep set (cowprotocol no-default-features, alloy-primitives,
alloy-sol-types, wit-bindgen) pre-pulled so BLEU-832 (event
decode) and BLEU-833 (EIP-1271 submit + retry) can layer in
without churning Cargo.toml.

src/lib.rs binds against shepherd:cow/shepherd, init logs once,
on_event logs Event::Logs as a placeholder until BLEU-832 decodes
the CoWSwapEthFlow OrderPlacement payload.

cargo build --target wasm32-wasip2 --release -p ethflow-watcher
emits a 67 KB .wasm (within ~3 KB of twap-monitor's skeleton —
identical world + deps, identical link footprint). Engine load is
gated on module.toml (BLEU-834).
@linear-code

linear-code Bot commented Jun 15, 2026

Copy link
Copy Markdown

BLEU-831

brunota20 added a commit that referenced this pull request Jun 15, 2026
- Cargo.toml: clarify in comment that cowprotocol = "1.0.0-alpha"
  is the cowdao-grants/cow-rs crate (homepage / repository fields
  on crates.io point there) and cross-reference ADR-0004. Bump
  alloy declarations (provider / rpc-client / transport[-ws])
  from 1.5 to 1.8 (latest 1.x at 1.8.3); 2.x is held off because
  alloy-provider@2 pulls alloy-signer@2 while cowprotocol still
  pins alloy-signer@1.8.3 — they'd collide via cargo-deny's
  multiple-versions check. alloy-primitives stays at 1.6 (its own
  release cadence; 1.6.0 is max stable today).

- host/error.rs: drop the hand-rolled write!-loop hex encoder
  for alloy_primitives::hex::encode. alloy is already in the dep
  graph via the chain backend, so this is a net code-loss with
  no extra link cost.

- host/provider_pool.rs: gate ProviderPool::empty() behind
  #[cfg(test)]. It is only referenced from the inline test
  module, so the non-test build now does not link an unused
  constructor.

- manifest/error.rs: convert to thiserror::Error derives.
  ParseError becomes a clean enum with #[from] impls for
  std::io::Error / toml::de::Error, and UnknownCapability
  switches to a struct variant with a `name` field. Display
  strings preserved. manifest/load.rs adopts the `?` conversion
  now that From is in scope.
brunota20 added a commit that referenced this pull request Jun 15, 2026
Two structural changes that share the HostState / main.rs hot path,
landed together to avoid an inconsistent intermediate revision.

## ModuleStore: cached prefix per module (review on local_store_redb.rs)

Per mfw78's main concern, the namespace prefix is no longer
recomputed on every get / set / delete / list-keys call. Introduces
`ModuleStore`: a per-module handle carrying the pre-computed
`[u8; 32]` keccak prefix plus an `Arc<Database>` ref. Hashing
happens once, in `LocalStore::module(name)`.

  let store: LocalStore = LocalStore::open(path)?;
  let twap: ModuleStore = store.module("twap-monitor")?; // hash once
  twap.set("watch:...", &bytes)?;                        // concat-only
  twap.list_keys("watch:")?;                              // concat-only

HostState now carries `store: ModuleStore` directly; the previous
`(LocalStore, module_namespace: String)` pair collapsed to just the
`ModuleStore`. The `module_namespace` field stays on HostState
purely for log tagging (the host's `logging::log` impl tags every
line with it) — the namespace identity is encoded in `ModuleStore`'s
prefix.

Tests adapt: the suite previously called `store.set("ns", "k",
"v")`; it now calls `store.module("ns")?.set("k", "v")`. Added a
new test (`module_handles_share_underlying_data`) confirming
cloning a `ModuleStore` is an Arc bump, not a fresh DB view.

## Fuel + memory limits (review on engine_config.rs + engine.example.toml)

Per mfw78's gas-metering concern, surfaces the wasmtime budget on
`engine.toml` so the operator can cap a runaway module. Both knobs
are `Option<u64>` with built-in defaults (1B fuel, 64 MiB memory) —
operators only write the keys they want to override.

  [engine.limits]
  fuel_per_event = 1_000_000_000
  memory_bytes   = 67_108_864

main.rs wires the budget into wasmtime:

  config.consume_fuel(true);
  let limits = StoreLimitsBuilder::new().memory_size(cap).build();
  store.limiter(|s| &mut s.limits);
  store.set_fuel(limits_cfg.fuel())?;       // initial seed
  // ... init ...
  store.set_fuel(limits_cfg.fuel())?;       // refuel for on_event

HostState gains a `limits: StoreLimits` field. `ModuleLimits` lives
in engine_config.rs with `fuel()` / `memory()` accessors that
resolve the override against the defaults. Smoke test logs the
applied budget:

  applied module resource limits fuel=1000000000 memory_bytes=67108864
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant