diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b2e1e98..83a0de4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -94,18 +94,18 @@ jobs: Required environment variables: - - `SEQ_ETH_RPC_URL` - - `SEQ_CHAIN_ID` - - `SEQ_APP_ADDRESS` - - `SEQ_BATCH_SUBMITTER_PRIVATE_KEY` (or `SEQ_BATCH_SUBMITTER_PRIVATE_KEY_FILE`) + - `CARTESI_SEQUENCER_BLOCKCHAIN_HTTP_ENDPOINT` + - `CARTESI_SEQUENCER_BLOCKCHAIN_ID` + - `CARTESI_SEQUENCER_APP_ADDRESS` + - `CARTESI_SEQUENCER_AUTH_PRIVATE_KEY` (or `CARTESI_SEQUENCER_AUTH_PRIVATE_KEY_FILE`) Example: ```bash - SEQ_ETH_RPC_URL=http://127.0.0.1:8545 \ - SEQ_CHAIN_ID=31337 \ - SEQ_APP_ADDRESS=0x1111111111111111111111111111111111111111 \ - SEQ_BATCH_SUBMITTER_PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 \ + CARTESI_SEQUENCER_BLOCKCHAIN_HTTP_ENDPOINT=http://127.0.0.1:8545 \ + CARTESI_SEQUENCER_BLOCKCHAIN_ID=31337 \ + CARTESI_SEQUENCER_APP_ADDRESS=0x1111111111111111111111111111111111111111 \ + CARTESI_SEQUENCER_AUTH_PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 \ ./sequencer ``` EOF diff --git a/AGENTS.md b/AGENTS.md index 4be52e4..f3138c9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -92,7 +92,7 @@ See [`docs/recovery/README.md`](docs/recovery/README.md) Step 5 for the "everyth Staleness is only checked against L1 **safe** state, never latest. Stale batches in latest that haven't reached safe yet will eventually become safe, and the check will fire at that point. This avoids reacting to L1 reorgs. -When the sequencer's view of L1 stops advancing — most often because the RPC gateway is stalled or returning stale reads, occasionally because L1 itself is unhealthy — the DB-based staleness check sees a frozen `current_safe_block` and may fail to trigger. The danger detector uses two wall-clock signals: the recorded L1 safe block timestamp must remain younger than `SEQ_L1_READ_STALE_AFTER_BLOCKS`, and unresolved batches are also checked with `estimated_missed_blocks = (now − last_safe_progress_ms) / seconds_per_block` by adjusting the danger threshold downward. This prevents silently issuing doomed soft confirmations during stale-provider periods or L1 outages. +When the sequencer's view of L1 stops advancing — most often because the RPC gateway is stalled or returning stale reads, occasionally because L1 itself is unhealthy — the DB-based staleness check sees a frozen `current_safe_block` and may fail to trigger. The danger detector uses two wall-clock signals: the recorded L1 safe block timestamp must remain younger than `CARTESI_SEQUENCER_L1_READ_STALE_AFTER_BLOCKS`, and unresolved batches are also checked with `estimated_missed_blocks = (now − last_safe_progress_ms) / seconds_per_block` by adjusting the danger threshold downward. This prevents silently issuing doomed soft confirmations during stale-provider periods or L1 outages. ### Formal verification @@ -163,7 +163,7 @@ Top-level layout follows the system's data flow. Each sequencer module correspon - Included txs are persisted as frame/batch data in `batches`, `frames`, `user_ops`, `safe_inputs`, and `sequenced_l2_txs`. Recovery metadata lives in `safe_accepted_batches`; batch lifecycle state (sealed/invalidated) lives on the `batches` row itself as write-once timestamps. - Frame fee is persisted in `frames.fee` and is fixed for the lifetime of that frame. The next frame's fee is sampled from `batch_policy_derived.recommended_fee` at rotation. - Wallet state (balances, nonces) is in-memory today — not persisted. -- **EIP-712 domain fields:** `name`, `version`, `chainId`, `verifyingContract`. `chainId` and `verifyingContract` come from `SEQ_CHAIN_ID` and `SEQ_APP_ADDRESS` (validated against the RPC chain id at startup). All four fields must be present on both sides — both the sequencer and the on-chain scheduler construct the domain via `sequencer_core::build_input_domain`, the canonical shared constructor. +- **EIP-712 domain fields:** `name`, `version`, `chainId`, `verifyingContract`. `chainId` and `verifyingContract` come from `CARTESI_SEQUENCER_BLOCKCHAIN_ID` and `CARTESI_SEQUENCER_APP_ADDRESS` (validated against the RPC chain id at startup). All four fields must be present on both sides — both the sequencer and the on-chain scheduler construct the domain via `sequencer_core::build_input_domain`, the canonical shared constructor. ### InputBox payload classification @@ -235,21 +235,21 @@ Snapshot endpoints (`/finalized_state`, `/finalized_state/inclusion_block`, `/la **Required:** -- `SEQ_ETH_RPC_URL` -- `SEQ_CHAIN_ID` -- `SEQ_APP_ADDRESS` -- `SEQ_BATCH_SUBMITTER_PRIVATE_KEY` or `SEQ_BATCH_SUBMITTER_PRIVATE_KEY_FILE` +- `CARTESI_SEQUENCER_BLOCKCHAIN_HTTP_ENDPOINT` +- `CARTESI_SEQUENCER_BLOCKCHAIN_ID` +- `CARTESI_SEQUENCER_APP_ADDRESS` +- `CARTESI_SEQUENCER_AUTH_PRIVATE_KEY` or `CARTESI_SEQUENCER_AUTH_PRIVATE_KEY_FILE` **Optional:** -- `SEQ_HTTP_ADDR` (default `127.0.0.1:3000`) -- `SEQ_DATA_DIR` (default `sequencer-data`; DB file `sequencer.db` inside it) -- `SEQ_LONG_BLOCK_RANGE_ERROR_CODES` -- `SEQ_BATCH_SUBMITTER_IDLE_POLL_INTERVAL_MS` (default 5000) -- `SEQ_BATCH_SUBMITTER_CONFIRMATION_DEPTH` (default 2) -- `SEQ_PREEMPTIVE_MARGIN_BLOCKS` (default 300, ~1h at 12s/block) -- `SEQ_L1_READ_STALE_AFTER_BLOCKS` (default derived before the danger threshold) -- `SEQ_SECONDS_PER_BLOCK` (default 12) +- `CARTESI_SEQUENCER_HTTP_ADDR` (default `127.0.0.1:3000`) +- `CARTESI_SEQUENCER_DATA_DIR` (default `sequencer-data`; DB file `sequencer.db` inside it) +- `CARTESI_SEQUENCER_LONG_BLOCK_RANGE_ERROR_CODES` +- `CARTESI_SEQUENCER_BATCH_SUBMITTER_IDLE_POLL_INTERVAL_MS` (default 5000) +- `CARTESI_SEQUENCER_BATCH_SUBMITTER_CONFIRMATION_DEPTH` (default 2) +- `CARTESI_SEQUENCER_PREEMPTIVE_MARGIN_BLOCKS` (default 300, ~1h at 12s/block) +- `CARTESI_SEQUENCER_L1_READ_STALE_AFTER_BLOCKS` (default derived before the danger threshold) +- `CARTESI_SEQUENCER_SECONDS_PER_BLOCK` (default 12) ## Coding Conventions @@ -289,10 +289,10 @@ cargo clippy --all-targets --all-features -- -D warnings Run server: ```bash -SEQ_ETH_RPC_URL=http://127.0.0.1:8545 \ -SEQ_CHAIN_ID=31337 \ -SEQ_APP_ADDRESS=0x1111111111111111111111111111111111111111 \ -SEQ_BATCH_SUBMITTER_PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 \ +CARTESI_SEQUENCER_BLOCKCHAIN_HTTP_ENDPOINT=http://127.0.0.1:8545 \ +CARTESI_SEQUENCER_BLOCKCHAIN_ID=31337 \ +CARTESI_SEQUENCER_APP_ADDRESS=0x1111111111111111111111111111111111111111 \ +CARTESI_SEQUENCER_AUTH_PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 \ cargo run -p sequencer ``` diff --git a/README.md b/README.md index 57bf29d..95cd4e6 100644 --- a/README.md +++ b/README.md @@ -64,22 +64,22 @@ The batch submitter posts closed batches to L1's InputBox contract. Each batch c ## Running ```bash -SEQ_ETH_RPC_URL=http://127.0.0.1:8545 \ -SEQ_CHAIN_ID=31337 \ -SEQ_APP_ADDRESS=0x1111111111111111111111111111111111111111 \ -SEQ_BATCH_SUBMITTER_PRIVATE_KEY=0xac09...f2ff80 \ +CARTESI_SEQUENCER_BLOCKCHAIN_HTTP_ENDPOINT=http://127.0.0.1:8545 \ +CARTESI_SEQUENCER_BLOCKCHAIN_ID=31337 \ +CARTESI_SEQUENCER_APP_ADDRESS=0x1111111111111111111111111111111111111111 \ +CARTESI_SEQUENCER_AUTH_PRIVATE_KEY=0xac09...f2ff80 \ cargo run -p sequencer ``` -Required: `SEQ_ETH_RPC_URL`, `SEQ_CHAIN_ID`, `SEQ_APP_ADDRESS`, `SEQ_BATCH_SUBMITTER_PRIVATE_KEY` (or `_FILE`). +Required: `CARTESI_SEQUENCER_BLOCKCHAIN_HTTP_ENDPOINT`, `CARTESI_SEQUENCER_BLOCKCHAIN_ID`, `CARTESI_SEQUENCER_APP_ADDRESS`, `CARTESI_SEQUENCER_AUTH_PRIVATE_KEY` (or `_FILE`). -Optional: `SEQ_HTTP_ADDR` (default `127.0.0.1:3000`), `SEQ_DATA_DIR` (default `sequencer-data` — SQLite file is `sequencer.db` inside; created if missing), `SEQ_PREEMPTIVE_MARGIN_BLOCKS` (default `300`), `SEQ_SECONDS_PER_BLOCK` (default `12`), `SEQ_LONG_BLOCK_RANGE_ERROR_CODES` (default `-32005,-32600,-32602,-32616`), `SEQ_BATCH_SUBMITTER_PRIVATE_KEY_FILE` (alternative to `SEQ_BATCH_SUBMITTER_PRIVATE_KEY`; first line of the file is the key), `SEQ_BATCH_SUBMITTER_IDLE_POLL_INTERVAL_MS`, `SEQ_BATCH_SUBMITTER_CONFIRMATION_DEPTH`. +Optional: `CARTESI_SEQUENCER_HTTP_ADDR` (default `127.0.0.1:3000`), `CARTESI_SEQUENCER_DATA_DIR` (default `sequencer-data` — SQLite file is `sequencer.db` inside; created if missing), `CARTESI_SEQUENCER_PREEMPTIVE_MARGIN_BLOCKS` (default `300`), `CARTESI_SEQUENCER_SECONDS_PER_BLOCK` (default `12`), `CARTESI_SEQUENCER_LONG_BLOCK_RANGE_ERROR_CODES` (default `-32005,-32600,-32602,-32616`), `CARTESI_SEQUENCER_AUTH_PRIVATE_KEY_FILE` (alternative to `CARTESI_SEQUENCER_AUTH_PRIVATE_KEY`; first line of the file is the key), `CARTESI_SEQUENCER_BATCH_SUBMITTER_IDLE_POLL_INTERVAL_MS`, `CARTESI_SEQUENCER_BATCH_SUBMITTER_CONFIRMATION_DEPTH`. Fixed protocol identity (EIP-712): - domain name: `CartesiAppSequencer` - domain version: `1` -- `chain_id` and `verifying_contract` come from `SEQ_CHAIN_ID` and `SEQ_APP_ADDRESS` +- `chain_id` and `verifying_contract` come from `CARTESI_SEQUENCER_BLOCKCHAIN_ID` and `CARTESI_SEQUENCER_APP_ADDRESS` Most queue sizes, polling intervals, and safety limits are now internal runtime constants instead of public launch-time configuration. diff --git a/docs/recovery/README.md b/docs/recovery/README.md index 2d81d8f..34606c8 100644 --- a/docs/recovery/README.md +++ b/docs/recovery/README.md @@ -322,7 +322,7 @@ The most common real-world trigger for `L1ViewStale` is a stalled RPC gateway: t **Other workers during L1 outages**: the inclusion lane and API are purely local (SQLite) and continue operating. The input reader retries L1 polling with error logging. All L1-dependent workers log errors at the `error` level to alert operators. -The `seconds_per_block` parameter (default: 12 for Ethereum) is configurable via `SEQ_SECONDS_PER_BLOCK`. The L1 read-staleness threshold is configurable via `SEQ_L1_READ_STALE_AFTER_BLOCKS`; if unset, startup derives it before the write danger threshold. These estimates are conservative — they may cause earlier detection if blocks are slower than assumed. This is correct: better to crash early than to issue doomed soft confirmations. +The `seconds_per_block` parameter (default: 12 for Ethereum) is configurable via `CARTESI_SEQUENCER_SECONDS_PER_BLOCK`. The L1 read-staleness threshold is configurable via `CARTESI_SEQUENCER_L1_READ_STALE_AFTER_BLOCKS`; if unset, startup derives it before the write danger threshold. These estimates are conservative — they may cause earlier detection if blocks are slower than assumed. This is correct: better to crash early than to issue doomed soft confirmations. ## Dead Batches diff --git a/docs/threat-model/README.md b/docs/threat-model/README.md index 733c040..8797ecc 100644 --- a/docs/threat-model/README.md +++ b/docs/threat-model/README.md @@ -64,20 +64,20 @@ These are preconditions the sequencer takes as given. They are neither "trust" n The wall-clock fallback in [`sequencer/src/recovery/mod.rs`](../../sequencer/src/recovery/mod.rs) estimates missed blocks as: ``` -estimated_missed_blocks = (now - last_sync_ms) / SEQ_SECONDS_PER_BLOCK +estimated_missed_blocks = (now - last_sync_ms) / CARTESI_SEQUENCER_SECONDS_PER_BLOCK ``` This assumes a **known, bounded-variance relationship** between elapsed wall-clock time and mined L1 block count. The assumption has three parts: -1. **Known average block time** — `SEQ_SECONDS_PER_BLOCK` (default 12s, Ethereum mainnet) accurately reflects the target chain's block cadence. +1. **Known average block time** — `CARTESI_SEQUENCER_SECONDS_PER_BLOCK` (default 12s, Ethereum mainnet) accurately reflects the target chain's block cadence. 2. **Bounded variance** — over the danger-threshold window (~4h on mainnet), the delta between `elapsed_seconds / avg_block_time` and actual mined blocks is small. On Ethereum mainnet this holds: slot proposers occasionally skip, but >99% of slots produce a block. 3. **Wall clock is monotonic and accurate** — the host's `SystemTime::now()` does not jump backward significantly or drift. Handled by saturating subtraction against clock backward jumps, but not against systematic drift. **Where it matters.** Only on the fallback path — when L1 is unreachable and we cannot observe block numbers directly. When L1 is up, observed block numbers are authoritative and this assumption is not consulted. **Violation modes.** -- **Chain with unstable block time.** A chain where average block time drifts substantially (e.g., PoW networks under major hashrate swings) would make the estimate less reliable. Mitigation: `SEQ_SECONDS_PER_BLOCK` should be tuned conservatively (overestimate block time → underestimate missed blocks → more cautious recovery triggers). -- **Operator misconfigures `SEQ_SECONDS_PER_BLOCK`.** Typo or copy-paste error pointing at the wrong chain's cadence. Operator-trust scope. +- **Chain with unstable block time.** A chain where average block time drifts substantially (e.g., PoW networks under major hashrate swings) would make the estimate less reliable. Mitigation: `CARTESI_SEQUENCER_SECONDS_PER_BLOCK` should be tuned conservatively (overestimate block time → underestimate missed blocks → more cautious recovery triggers). +- **Operator misconfigures `CARTESI_SEQUENCER_SECONDS_PER_BLOCK`.** Typo or copy-paste error pointing at the wrong chain's cadence. Operator-trust scope. - **Significant host clock drift.** A sequencer host whose clock lags or leads the real-world by minutes per day could slowly desynchronize its danger estimates from reality. **Corollary for test design.** To deterministically exercise the wall-clock fallback, tests must maintain this coupling: when advancing the L1 block count, they should also advance (or simulate) the corresponding wall-clock interval. Our e2e harness does the reverse — it rewinds `l1_safe_head.synced_at_ms` to an older timestamp, which is semantically equivalent to advancing the wall clock. diff --git a/docs/watchdog/README.md b/docs/watchdog/README.md index 9559f75..6f0b97c 100644 --- a/docs/watchdog/README.md +++ b/docs/watchdog/README.md @@ -28,18 +28,18 @@ just setup && just canonical-build-machine-image && just watchdog-lua-deps # Path A — full smoke (Anvil + sequencer + CM + compare), one command: just test-watchdog-compare-harness -# Path B — two terminals: stack prints WATCHDOG_* exports, then init + tick: +# Path B — two terminals: stack prints CARTESI_WATCHDOG_* exports, then init + tick: just devnet-for-watchdog # terminal 1 — leave running # terminal 2: paste exports, then: -export WATCHDOG_LUA_ROOT="$(pwd)" -export WATCHDOG_LUA_BIN=lua -export WATCHDOG_LUA_DEPS=.deps/lua +export CARTESI_WATCHDOG_LUA_ROOT="$(pwd)" +export CARTESI_WATCHDOG_LUA_BIN=lua +export CARTESI_WATCHDOG_LUA_DEPS=.deps/lua ./watchdog/sequencer-watchdog init ./watchdog/sequencer-watchdog tick ``` The `sequencer-watchdog` wrapper wraps `init`/`tick` with an advisory `flock` -on `$WATCHDOG_STATE_DIR/run.lock`. Production schedulers must also prevent +on `$CARTESI_WATCHDOG_STATE_DIR/run.lock`. Production schedulers must also prevent overlapping ticks (`flock`, systemd, or Kubernetes `concurrencyPolicy: Forbid`). @@ -51,7 +51,7 @@ The watchdog cycle and any test that hits HTTP need a native **`lcurl.so`** buil ```bash just watchdog-lua-deps # idempotent; writes .deps/lua/lcurl.so -export WATCHDOG_LUA_DEPS="$(pwd)/.deps/lua" +export CARTESI_WATCHDOG_LUA_DEPS="$(pwd)/.deps/lua" ``` You also need **`cartesi-machine`** on `PATH` (in-process `cartesi` @@ -166,12 +166,12 @@ then `head.json` is atomically replaced to point at it. `init` stores the operator-provided bootstrap CM snapshot into this layout. `tick` requires both `config.json` and `head.json`; it never bootstraps from env. -`WATCHDOG_L1_RPC_URL` is intentionally read at tick time, not persisted in +`CARTESI_WATCHDOG_BLOCKCHAIN_HTTP_ENDPOINT` is intentionally read at tick time, not persisted in `config.json`, so operators can rotate RPC endpoints without rewriting watchdog state. -- `WATCHDOG_CM_SNAPSHOT_DIR` -- `WATCHDOG_CM_SNAPSHOT_SAFE_BLOCK` +- `CARTESI_WATCHDOG_CM_SNAPSHOT_DIR` +- `CARTESI_WATCHDOG_CM_SNAPSHOT_SAFE_BLOCK` ## How it runs @@ -198,16 +198,16 @@ host scheduling should provide the same non-overlap guarantee. Each tick: Runtime knobs: -- `WATCHDOG_L1_RPC_URL`: current L1 JSON-RPC endpoint for tick. -- `WATCHDOG_RETRY_ATTEMPTS`: bounded retry attempts per run, default `3`. -- `WATCHDOG_RETRY_DELAY_SEC`: delay between retry attempts, default `5`. +- `CARTESI_WATCHDOG_BLOCKCHAIN_HTTP_ENDPOINT`: current L1 JSON-RPC endpoint for tick. +- `CARTESI_WATCHDOG_RETRY_ATTEMPTS`: bounded retry attempts per run, default `3`. +- `CARTESI_WATCHDOG_RETRY_DELAY_SEC`: delay between retry attempts, default `5`. ## Local Tests | Command | What it exercises | |---------|-------------------| | `just test-watchdog` | Lua unit tests (fake HTTP/RPC/CM; no live chain) | -| `just test-watchdog-e2e` | Real CM: advance, inspect; optional live compare if `WATCHDOG_E2E_SEQUENCER_URL` set | +| `just test-watchdog-e2e` | Real CM: advance, inspect; optional live compare if `CARTESI_WATCHDOG_E2E_SEQUENCER_URL` set | | `just test-watchdog-compare-harness` | **Full E2E**: Anvil + devnet sequencer + `/finalized_state` + CM inspect + Lua `init`/`tick` | | `just test-rollups-e2e` | All rollups e2e scenarios; includes watchdog genesis/non-genesis compare plus `watchdog_non_genesis_divergence_test` (needs Sepolia CM image) | | `just test-watchdog-divergence-drill` | Synthetic divergence signal drill (`watchdog_event` + exit `2`) | @@ -220,7 +220,7 @@ just doctor # fail fast before long harness runs just canonical-build-machine-image # once, if out/ image is missing just canonical-build-machine-image-sepolia # rollups-e2e divergence trial (auto-built by test-rollups-e2e) just watchdog-lua-deps -export WATCHDOG_LUA_DEPS="$(pwd)/.deps/lua" +export CARTESI_WATCHDOG_LUA_DEPS="$(pwd)/.deps/lua" ``` ### Lua unit tests @@ -244,7 +244,7 @@ Scenarios (verbose `step NN/NN` logging): - `prerequisites` — `cartesi-machine` on PATH and machine image present. - `cm-inspect-state-query` — real `--cmio-inspect-state` with query `state`. - `machine-cartesi-store-reload-advance` — store checkpoint snapshot, reload, advance again (in-process binding). -- `compare-runner-with-sequencer` — skipped unless `WATCHDOG_E2E_SEQUENCER_URL` is set. +- `compare-runner-with-sequencer` — skipped unless `CARTESI_WATCHDOG_E2E_SEQUENCER_URL` is set. Rebuild the machine image after changing the canonical scheduler/dapp. A stale image makes `cm-inspect-state-query` skip with `inspect endpoint not implemented`. @@ -282,7 +282,7 @@ exists; it does **not** detect a stale guest. If you pulled SSZ/inspect changes, | `finalized_state bytes mismatch (len 87 vs expected 76)` | Wrong golden (Sepolia fixture vs devnet sequencer) and/or raw HTTP chunked framing | Harness expects **devnet** SSZ; `lcurl` decodes chunked responses automatically | | `CM inspect bytes mismatch (len 27 vs expected 76)` | **Stale CM image** still returns JSON `{"balances":{},"nonces":{}}` from pre-SSZ inspect | `just canonical-build-machine-image` then rerun harness | | `inspect endpoint not implemented` | Older guest without inspect handler | Same rebuild as above | -| Harness passes step 1–2 but Lua compare fails | `WATCHDOG_LUA_DEPS` or checkpoint/bootstrap | Set `export WATCHDOG_LUA_DEPS="$(pwd)/.deps/lua"`; see [`getting-started.md`](getting-started.md) env table | +| Harness passes step 1–2 but Lua compare fails | `CARTESI_WATCHDOG_LUA_DEPS` or checkpoint/bootstrap | Set `export CARTESI_WATCHDOG_LUA_DEPS="$(pwd)/.deps/lua"`; see [`getting-started.md`](getting-started.md) env table | Manual equivalent of the recipe: diff --git a/docs/watchdog/design-notes.md b/docs/watchdog/design-notes.md index a85ffc9..3a67303 100644 --- a/docs/watchdog/design-notes.md +++ b/docs/watchdog/design-notes.md @@ -46,7 +46,7 @@ checkpoint layout. `tick` never bootstraps from env; missing `head.json` is an operator error. `config.json` stores stable deployment identity (`sequencer_url`, -`input_box_address`, `app_address`, retry knobs). `WATCHDOG_L1_RPC_URL` is read +`input_box_address`, `app_address`, retry knobs). `CARTESI_WATCHDOG_BLOCKCHAIN_HTTP_ENDPOINT` is read at tick time rather than persisted, because provider URLs and credentials are operational inputs that may rotate. diff --git a/docs/watchdog/getting-started.md b/docs/watchdog/getting-started.md index c297bd3..02bf3d7 100644 --- a/docs/watchdog/getting-started.md +++ b/docs/watchdog/getting-started.md @@ -94,7 +94,7 @@ This builds `sequencer-devnet`, spawns the stack, waits for `GET /finalized_stat just devnet-for-watchdog ``` -This starts Anvil and `sequencer-devnet` on **ephemeral local ports** (not fixed 8545/3000) and prints a block of `export WATCHDOG_*=...` lines. **Copy those exports** into Terminal 2. +This starts Anvil and `sequencer-devnet` on **ephemeral local ports** (not fixed 8545/3000) and prints a block of `export CARTESI_WATCHDOG_*=...` lines. **Copy those exports** into Terminal 2. Leave Terminal 1 running until you are done; Ctrl+C stops Anvil and the sequencer. @@ -102,10 +102,10 @@ Leave Terminal 1 running until you are done; Ctrl+C stops Anvil and the sequence The watchdog needs a **finalized** SSZ dump. Right after boot, the cheap endpoint may return **404** until the sequencer has promoted a snapshot. -In another shell (use the printed `WATCHDOG_SEQUENCER_URL`): +In another shell (use the printed `CARTESI_WATCHDOG_SEQUENCER_URL`): ```bash -curl -s "$WATCHDOG_SEQUENCER_URL/finalized_state/inclusion_block" +curl -s "$CARTESI_WATCHDOG_SEQUENCER_URL/finalized_state/inclusion_block" ``` When you see JSON like `{"inclusion_block":0,"l2_tx_index":0}` (numbers may differ), the watchdog can compare. If it stays 404 for a long time, check sequencer logs in `tests/e2e/results/` and that L1 is mining (devnet Anvil auto-mines by default). @@ -113,7 +113,7 @@ When you see JSON like `{"inclusion_block":0,"l2_tx_index":0}` (numbers may diff Optional — inspect SSZ size: ```bash -curl -s -D - "$WATCHDOG_SEQUENCER_URL/finalized_state" -o /tmp/finalized-state.bin +curl -s -D - "$CARTESI_WATCHDOG_SEQUENCER_URL/finalized_state" -o /tmp/finalized-state.bin head -c 32 /tmp/finalized-state.bin | xxd ``` @@ -123,9 +123,9 @@ From repo root, after `just watchdog-lua-deps`: ```bash # Paste exports from Terminal 1, then initialize once and run one tick: -export WATCHDOG_LUA_ROOT="$(pwd)" -export WATCHDOG_LUA_BIN=lua -export WATCHDOG_LUA_DEPS=.deps/lua +export CARTESI_WATCHDOG_LUA_ROOT="$(pwd)" +export CARTESI_WATCHDOG_LUA_BIN=lua +export CARTESI_WATCHDOG_LUA_DEPS=.deps/lua ./watchdog/sequencer-watchdog init ./watchdog/sequencer-watchdog tick ``` @@ -162,14 +162,14 @@ Full operator runbook: **[`operator-deployment.md`](operator-deployment.md)**. | Variable | Required | Description | |----------|----------|-------------| -| `WATCHDOG_SEQUENCER_URL` | yes | e.g. `http://127.0.0.1:54321` | -| `WATCHDOG_L1_RPC_URL` | tick | Current L1 JSON-RPC; not persisted by `init` | -| `WATCHDOG_INPUTBOX_ADDRESS` | yes | InputBox contract | -| `WATCHDOG_APP_ADDRESS` | yes | Rollup application contract | -| `WATCHDOG_STATE_DIR` | yes | Persistent watchdog state (`config.json`, `head.json`, checkpoints) | -| `WATCHDOG_CM_SNAPSHOT_DIR` | init | Genesis CM image dir | -| `WATCHDOG_CM_SNAPSHOT_SAFE_BLOCK` | with above | Usually `0` on fresh devnet | -| `WATCHDOG_LUA_DEPS` | yes | `.deps/lua` after `just watchdog-lua-deps` | +| `CARTESI_WATCHDOG_SEQUENCER_URL` | yes | e.g. `http://127.0.0.1:54321` | +| `CARTESI_WATCHDOG_BLOCKCHAIN_HTTP_ENDPOINT` | tick | Current L1 JSON-RPC; not persisted by `init` | +| `CARTESI_WATCHDOG_CONTRACTS_INPUT_BOX_ADDRESS` | yes | InputBox contract | +| `CARTESI_WATCHDOG_APP_ADDRESS` | yes | Rollup application contract | +| `CARTESI_WATCHDOG_STATE_DIR` | yes | Persistent watchdog state (`config.json`, `head.json`, checkpoints) | +| `CARTESI_WATCHDOG_CM_SNAPSHOT_DIR` | init | Genesis CM image dir | +| `CARTESI_WATCHDOG_CM_SNAPSHOT_SAFE_BLOCK` | with above | Usually `0` on fresh devnet | +| `CARTESI_WATCHDOG_LUA_DEPS` | yes | `.deps/lua` after `just watchdog-lua-deps` | See `watchdog/config.lua` for the full list. @@ -181,12 +181,12 @@ See `watchdog/config.lua` for the full list. |---------|----------------| | `install libcurl dev package` | Install `libcurl4-openssl-dev` (or distro equivalent); see [Host dependencies](README.md#host-dependencies-watchdog-lua-deps) | | `lua.h: No such file or directory` when building lcurl | Install `liblua5.4-dev` (Debian/WSL), or set `LUA_INC` to your Lua headers directory (Homebrew/nix) before `just watchdog-lua-deps` | -| `lcurl` / `cURL` not found at runtime | Run `just watchdog-lua-deps`, set `WATCHDOG_LUA_DEPS=.deps/lua` | +| `lcurl` / `cURL` not found at runtime | Run `just watchdog-lua-deps`, set `CARTESI_WATCHDOG_LUA_DEPS=.deps/lua` | | `cartesi Lua module is required` | Install Cartesi Machine; use nix/direnv shell; ensure `cartesi-machine` on `PATH` | | `inspect endpoint not implemented` | Rebuild CM image: `just canonical-build-machine-image` | | CM inspect ~27 bytes / JSON in error | Stale image (old JSON inspect); rebuild: `just canonical-build-machine-image` | | HTTP 404 on `/finalized_state/inclusion_block` | Sequencer not promoted yet; wait or drive L1 + batches | -| `state_mismatch` at genesis | Wrong `WATCHDOG_CM_SNAPSHOT_*` or stale CM image vs sequencer build | +| `state_mismatch` at genesis | Wrong `CARTESI_WATCHDOG_CM_SNAPSHOT_*` or stale CM image vs sequencer build | | `inclusion_block_regressed` | Watchdog state ahead of sequencer (reset state dir or fix bootstrap block) | | `flock` lock conflict | Another tick is still running or the scheduler allows overlap. With the container `flock`, a leftover `run.lock` path alone is harmless. | | `could not determine which binary to run` | Use `just test-watchdog-compare-harness` (not bare `cargo run -p rollups-e2e`) | diff --git a/docs/watchdog/operator-deployment.md b/docs/watchdog/operator-deployment.md index 59ed1bb..a254a70 100644 --- a/docs/watchdog/operator-deployment.md +++ b/docs/watchdog/operator-deployment.md @@ -35,14 +35,14 @@ Use this checklist for any live deployment. Chain-specific values are in the tab ### 1. Network access -- [ ] Watchdog host can reach **internal** `WATCHDOG_SEQUENCER_URL` (not only the public `/tx` URL). +- [ ] Watchdog host can reach **internal** `CARTESI_WATCHDOG_SEQUENCER_URL` (not only the public `/tx` URL). - [ ] Watchdog host can reach **L1 JSON-RPC** with `eth_getLogs` (archive recommended if replaying long history). - [ ] `/finalized_state` is **not** exposed on the public internet. Verify snapshot API before CM bootstrap: ```bash -curl -sS -o /dev/null -w "%{http_code}\n" "$WATCHDOG_SEQUENCER_URL/finalized_state/inclusion_block" +curl -sS -o /dev/null -w "%{http_code}\n" "$CARTESI_WATCHDOG_SEQUENCER_URL/finalized_state/inclusion_block" # expect 200 when a finalized snapshot exists (404 = not promoted yet or wrong host) ``` @@ -87,7 +87,7 @@ COPY --from=ghcr.io/cartesi/sequencer-watchdog:vX /usr/local/lib/lua/ /usr/local COPY --from=ghcr.io/cartesi/sequencer-watchdog:vX /usr/local/share/lua/ /usr/local/share/lua/ COPY --from=ghcr.io/cartesi/sequencer-watchdog:vX /usr/local/share/cartesi-machine/ /usr/local/share/cartesi-machine/ -ENV WATCHDOG_LUA_DEPS=/opt/watchdog/lib \ +ENV CARTESI_WATCHDOG_LUA_DEPS=/opt/watchdog/lib \ LUA_PATH="/opt/watchdog/lua/?.lua;/opt/watchdog/lua/?/init.lua;/usr/local/share/lua/5.4/?.lua;/usr/local/share/lua/5.4/?/init.lua;;" \ LUA_CPATH="/opt/watchdog/lib/?.so;/usr/local/lib/lua/5.4/?.so;;" \ LD_LIBRARY_PATH="/usr/local/lib" \ @@ -102,19 +102,19 @@ ENTRYPOINT ["/usr/local/bin/sequencer-watchdog"] docker pull ghcr.io/cartesi/sequencer-watchdog:vX docker run --rm \ - -e WATCHDOG_SEQUENCER_URL="https://" \ - -e WATCHDOG_INPUTBOX_ADDRESS="0x..." \ - -e WATCHDOG_APP_ADDRESS="0x..." \ - -e WATCHDOG_STATE_DIR=/watchdog-state \ - -e WATCHDOG_CM_SNAPSHOT_DIR=/cm-bootstrap \ - -e WATCHDOG_CM_SNAPSHOT_SAFE_BLOCK="" \ + -e CARTESI_WATCHDOG_SEQUENCER_URL="https://" \ + -e CARTESI_WATCHDOG_CONTRACTS_INPUT_BOX_ADDRESS="0x..." \ + -e CARTESI_WATCHDOG_APP_ADDRESS="0x..." \ + -e CARTESI_WATCHDOG_STATE_DIR=/watchdog-state \ + -e CARTESI_WATCHDOG_CM_SNAPSHOT_DIR=/cm-bootstrap \ + -e CARTESI_WATCHDOG_CM_SNAPSHOT_SAFE_BLOCK="" \ -v /var/lib/watchdog/state:/watchdog-state \ -v /var/lib/watchdog/cm-bootstrap:/cm-bootstrap:ro \ ghcr.io/cartesi/sequencer-watchdog:vX init docker run --rm \ - -e WATCHDOG_L1_RPC_URL="https://" \ - -e WATCHDOG_STATE_DIR=/watchdog-state \ + -e CARTESI_WATCHDOG_BLOCKCHAIN_HTTP_ENDPOINT="https://" \ + -e CARTESI_WATCHDOG_STATE_DIR=/watchdog-state \ -v /var/lib/watchdog/state:/watchdog-state \ ghcr.io/cartesi/sequencer-watchdog:vX tick ``` @@ -150,29 +150,29 @@ Today `WalletApp::default()` / `WalletConfig::sepolia()` align with Sepolia stag | Variable | Where it comes from | |----------|---------------------| -| `WATCHDOG_SEQUENCER_URL` | Ops: internal HTTP base (see network diagram) | -| `WATCHDOG_L1_RPC_URL` | Ops: current chain RPC for `tick` (archive for historical `getLogs`; not persisted by `init`) | -| `WATCHDOG_APP_ADDRESS` | This rollup’s Cartesi **application** contract | -| `WATCHDOG_INPUTBOX_ADDRESS` | InputBox on that L1 ([Cartesi deployed contracts](https://docs.cartesi.io/cartesi-rollups/2.0/deployment/self-hosted.md)) | -| `WATCHDOG_STATE_DIR` | Persistent volume on watchdog host | -| `WATCHDOG_CM_SNAPSHOT_DIR` | Bootstrap CM snapshot (`init` only) | -| `WATCHDOG_CM_SNAPSHOT_SAFE_BLOCK` | L1 block that bootstrap snapshot represents (= finalized `inclusion_block` at bootstrap) | -| `WATCHDOG_LUA_DEPS` | `.deps/lua` | +| `CARTESI_WATCHDOG_SEQUENCER_URL` | Ops: internal HTTP base (see network diagram) | +| `CARTESI_WATCHDOG_BLOCKCHAIN_HTTP_ENDPOINT` | Ops: current chain RPC for `tick` (archive for historical `getLogs`; not persisted by `init`) | +| `CARTESI_WATCHDOG_APP_ADDRESS` | This rollup’s Cartesi **application** contract | +| `CARTESI_WATCHDOG_CONTRACTS_INPUT_BOX_ADDRESS` | InputBox on that L1 ([Cartesi deployed contracts](https://docs.cartesi.io/cartesi-rollups/2.0/deployment/self-hosted.md)) | +| `CARTESI_WATCHDOG_STATE_DIR` | Persistent volume on watchdog host | +| `CARTESI_WATCHDOG_CM_SNAPSHOT_DIR` | Bootstrap CM snapshot (`init` only) | +| `CARTESI_WATCHDOG_CM_SNAPSHOT_SAFE_BLOCK` | L1 block that bootstrap snapshot represents (= finalized `inclusion_block` at bootstrap) | +| `CARTESI_WATCHDOG_LUA_DEPS` | `.deps/lua` | -The sequencer discovers and pins `input_box_address` at startup; use the same values as `SEQ_ETH_RPC_URL` / `SEQ_APP_ADDRESS` configuration. +The sequencer discovers and pins `input_box_address` at startup; use the same values as `CARTESI_SEQUENCER_BLOCKCHAIN_HTTP_ENDPOINT` / `CARTESI_SEQUENCER_APP_ADDRESS` configuration. ### 5. Initialize watchdog state (first run on a live chain) -On a long-lived deployment, **`WATCHDOG_CM_SNAPSHOT_SAFE_BLOCK=0` is usually wrong** unless finalized state is still at genesis. +On a long-lived deployment, **`CARTESI_WATCHDOG_CM_SNAPSHOT_SAFE_BLOCK=0` is usually wrong** unless finalized state is still at genesis. Pick one: 1. **Ops hands off** a CM snapshot directory + block number matching current finalized `inclusion_block`, or -2. **Watchdog reuses** `WATCHDOG_STATE_DIR` from a prior run on this deployment, or +2. **Watchdog reuses** `CARTESI_WATCHDOG_STATE_DIR` from a prior run on this deployment, or 3. **Replay from genesis** (only for new rollups / low block height — slow). Run `init` once to store the bootstrap CM snapshot into the watchdog state -layout. `init` does not need `WATCHDOG_L1_RPC_URL`; the RPC URL is read by +layout. `init` does not need `CARTESI_WATCHDOG_BLOCKCHAIN_HTTP_ENDPOINT`; the RPC URL is read by each `tick` so it can rotate without editing state: ```bash @@ -192,7 +192,7 @@ sequencer-watchdog tick # exit 0 = clean/idle, 1 = transient, 2 = divergence ``` `sequencer-watchdog` wraps `init` and `tick` with a non-blocking `flock` on -`$WATCHDOG_STATE_DIR/run.lock`, which is released by the kernel if the process +`$CARTESI_WATCHDOG_STATE_DIR/run.lock`, which is released by the kernel if the process dies. Use the scheduler's non-overlap primitive as well (for example systemd or Kubernetes CronJob `concurrencyPolicy: Forbid`). A leftover `run.lock` path is only a lock handle; by itself it does not mean a lock is held. @@ -219,21 +219,21 @@ Use Sepolia to validate **the same procedure** you will run on mainnet: internal ### Example env block (fill from ops) ```bash -export WATCHDOG_SEQUENCER_URL="https://" -export WATCHDOG_L1_RPC_URL="https://" -export WATCHDOG_APP_ADDRESS="0x..." -export WATCHDOG_INPUTBOX_ADDRESS="0x..." -export WATCHDOG_STATE_DIR="/var/lib/watchdog/state-sepolia" -export WATCHDOG_CM_SNAPSHOT_DIR="/path/to/canonical-machine-image-sepolia" -export WATCHDOG_CM_SNAPSHOT_SAFE_BLOCK="" -export WATCHDOG_LUA_DEPS="/path/to/sequencer/.deps/lua" +export CARTESI_WATCHDOG_SEQUENCER_URL="https://" +export CARTESI_WATCHDOG_BLOCKCHAIN_HTTP_ENDPOINT="https://" +export CARTESI_WATCHDOG_APP_ADDRESS="0x..." +export CARTESI_WATCHDOG_CONTRACTS_INPUT_BOX_ADDRESS="0x..." +export CARTESI_WATCHDOG_STATE_DIR="/var/lib/watchdog/state-sepolia" +export CARTESI_WATCHDOG_CM_SNAPSHOT_DIR="/path/to/canonical-machine-image-sepolia" +export CARTESI_WATCHDOG_CM_SNAPSHOT_SAFE_BLOCK="" +export CARTESI_WATCHDOG_LUA_DEPS="/path/to/sequencer/.deps/lua" ``` ### Operating the Sepolia sequencer If your team runs the sequencer on Sepolia (not only the public endpoint): -1. `sequencer` / release binary with Sepolia `SEQ_*` (chain id, app address, batch submitter key, L1 RPC). +1. `sequencer` / release binary with Sepolia `CARTESI_SEQUENCER_*` (chain id, app address, batch submitter key, L1 RPC). 2. Inclusion lane promotes finalized snapshots when L1 safe advances — required for `/finalized_state` 200. 3. Snapshot routes on an **internal** bind / port reachable by the watchdog host. 4. Sequencer binary built with **`WalletApp::new(WalletConfig::sepolia())`** (see `sequencer-devnet` vs production binary choice in your release pipeline). @@ -276,14 +276,14 @@ Details: [`README.md`](README.md), [`docs/snapshots/lifecycle.md`](../snapshots/ ## Checkpoint disk usage and backups Each successful promotion stores a full CM snapshot under -`$WATCHDOG_STATE_DIR/checkpoints//`, and the watchdog **keeps only +`$CARTESI_WATCHDOG_STATE_DIR/checkpoints//`, and the watchdog **keeps only the selected one** — after the atomic `head.json` flip it deletes the checkpoint it superseded (crash-safe: `head.json` always names a complete checkpoint). Local disk therefore stays bounded at a single snapshot; no operator cleanup is required. For backups / rollback history, schedule the watchdog tick (it runs one cycle and -exits) and **after it exits** `aws s3 sync $WATCHDOG_STATE_DIR/checkpoints/ +exits) and **after it exits** `aws s3 sync $CARTESI_WATCHDOG_STATE_DIR/checkpoints/ s3://…` (without `--delete`). Because the process has exited there is no race with its store or prune, and omitting `--delete` **accumulates a per-block history in S3** while local disk stays at one snapshot. Restore feeds a chosen @@ -293,7 +293,7 @@ snapshot back through the watchdog/sequencer recovery workflow. | Symptom | Likely cause | |---------|----------------| -| `/finalized_state` missing on public URL | Wrong tier — use internal `WATCHDOG_SEQUENCER_URL` | +| `/finalized_state` missing on public URL | Wrong tier — use internal `CARTESI_WATCHDOG_SEQUENCER_URL` | | `state_mismatch` | CM image / wallet constants ≠ sequencer build; or wrong bootstrap block | | `inclusion_block_regressed` | Stale watchdog state vs sequencer finalized head | | Slow or failing `getLogs` | RPC range limits — watchdog uses same partition strategy as sequencer | diff --git a/docs/watchdog/staging-drills.md b/docs/watchdog/staging-drills.md index fff4d80..7f73cc5 100644 --- a/docs/watchdog/staging-drills.md +++ b/docs/watchdog/staging-drills.md @@ -14,7 +14,7 @@ This document covers staging and manual verification beyond the devnet tutorial. - `cartesi-machine`, `lua`, and `curl` on PATH - `just watchdog-lua-deps` — builds `lcurl.so` into `.deps/lua` (libcurl + Lua headers on host) - JSON is pure Lua (`watchdog/third_party/json.lua`); no cjson compile step -- Staging or local sequencer reachable at `WATCHDOG_SEQUENCER_URL` +- Staging or local sequencer reachable at `CARTESI_WATCHDOG_SEQUENCER_URL` - L1 RPC + InputBox + app addresses matching that deployment - Log collection for `watchdog_event` lines and process exit codes @@ -25,7 +25,7 @@ injected fake deps — no sequencer required. ```bash just watchdog-lua-deps -WATCHDOG_LUA_DEPS=.deps/lua lua watchdog/tests/drill_divergence.lua # exits 2 +CARTESI_WATCHDOG_LUA_DEPS=.deps/lua lua watchdog/tests/drill_divergence.lua # exits 2 # or: just test-watchdog-divergence-drill # wraps the drill; recipe exits 0 ``` @@ -49,16 +49,16 @@ just test-watchdog-compare-harness Or run the Lua compare pass manually after starting a devnet sequencer yourself: ```bash -export WATCHDOG_SEQUENCER_URL=http://127.0.0.1: -export WATCHDOG_L1_RPC_URL=http://127.0.0.1:8545 -export WATCHDOG_INPUTBOX_ADDRESS= -export WATCHDOG_APP_ADDRESS= -export WATCHDOG_STATE_DIR=/tmp/watchdog-state -export WATCHDOG_CM_SNAPSHOT_DIR=examples/canonical-app/out/canonical-machine-image -export WATCHDOG_CM_SNAPSHOT_SAFE_BLOCK=0 -export WATCHDOG_LUA_ROOT="$(pwd)" -export WATCHDOG_LUA_BIN=lua -export WATCHDOG_LUA_DEPS=.deps/lua +export CARTESI_WATCHDOG_SEQUENCER_URL=http://127.0.0.1: +export CARTESI_WATCHDOG_BLOCKCHAIN_HTTP_ENDPOINT=http://127.0.0.1:8545 +export CARTESI_WATCHDOG_CONTRACTS_INPUT_BOX_ADDRESS= +export CARTESI_WATCHDOG_APP_ADDRESS= +export CARTESI_WATCHDOG_STATE_DIR=/tmp/watchdog-state +export CARTESI_WATCHDOG_CM_SNAPSHOT_DIR=examples/canonical-app/out/canonical-machine-image +export CARTESI_WATCHDOG_CM_SNAPSHOT_SAFE_BLOCK=0 +export CARTESI_WATCHDOG_LUA_ROOT="$(pwd)" +export CARTESI_WATCHDOG_LUA_BIN=lua +export CARTESI_WATCHDOG_LUA_DEPS=.deps/lua ./watchdog/sequencer-watchdog init ./watchdog/sequencer-watchdog tick ``` @@ -76,7 +76,7 @@ takes a non-blocking `flock`; production scheduling should also prevent overlapping ticks with systemd, Kubernetes, or an equivalent scheduler guard: ```bash -# ... all WATCHDOG_* vars from config.lua ... +# ... all CARTESI_WATCHDOG_* vars from config.lua ... sequencer-watchdog tick ``` @@ -94,5 +94,5 @@ Exit codes from `sequencer-watchdog tick`: |---------|----------------| | `inspect endpoint not implemented` | Stale CM image — rebuild | | `state_mismatch` at genesis | Checkpoint not aligned with sequencer history | -| Compare skipped in Lua e2e | Set `WATCHDOG_E2E_SEQUENCER_URL` to a live sequencer | +| Compare skipped in Lua e2e | Set `CARTESI_WATCHDOG_E2E_SEQUENCER_URL` to a live sequencer | | CM inspect 27 bytes / harness byte mismatch | Rebuild devnet image: `just canonical-build-machine-image` — see [`README.md`](README.md#troubleshooting-just-test-watchdog-compare-harness) | diff --git a/justfile b/justfile index db67d9a..185df59 100644 --- a/justfile +++ b/justfile @@ -26,7 +26,7 @@ test-watchdog-divergence-drill: watchdog-lua-deps watchdog-lua-deps: @just -f watchdog/justfile lua-deps -# Anvil + rollups + sequencer-devnet; prints WATCHDOG_* exports until Ctrl+C. +# Anvil + rollups + sequencer-devnet; prints CARTESI_WATCHDOG_* exports until Ctrl+C. devnet-for-watchdog: setup ensure-machine-image cargo build -p sequencer --bin sequencer-devnet cargo build -p rollups-e2e --bin devnet-stack @@ -102,4 +102,4 @@ ci: run addr="127.0.0.1:3000" data_dir="sequencer-data": rm -rf {{data_dir}} - SEQ_HTTP_ADDR={{addr}} SEQ_DATA_DIR={{data_dir}} cargo run -p sequencer --release + CARTESI_SEQUENCER_HTTP_ADDR={{addr}} CARTESI_SEQUENCER_DATA_DIR={{data_dir}} cargo run -p sequencer --release diff --git a/scripts/ci-watchdog-docker-smoke.sh b/scripts/ci-watchdog-docker-smoke.sh index a1ff03c..3a23664 100755 --- a/scripts/ci-watchdog-docker-smoke.sh +++ b/scripts/ci-watchdog-docker-smoke.sh @@ -20,7 +20,7 @@ docker build \ -t "${image}" \ . -docker run --rm -e WATCHDOG_PRINT_RELEASE_INFO=1 "${image}" >/dev/null +docker run --rm -e CARTESI_WATCHDOG_PRINT_RELEASE_INFO=1 "${image}" >/dev/null docker run --rm --entrypoint cartesi-machine "${image}" --version >/dev/null docker run --rm --entrypoint flock "${image}" --version >/dev/null docker run --rm --entrypoint lua5.4 "${image}" -e "require('cartesi'); print('cartesi ok')" @@ -40,7 +40,7 @@ trap cleanup EXIT set +e tick_output="$( docker run --rm \ - -e WATCHDOG_STATE_DIR=/state \ + -e CARTESI_WATCHDOG_STATE_DIR=/state \ -v "${state_dir}:/state" \ "${image}" tick 2>&1 )" @@ -66,7 +66,7 @@ for _ in $(seq 1 30); do set +e lock_output="$( docker run --rm \ - -e WATCHDOG_STATE_DIR=/state \ + -e CARTESI_WATCHDOG_STATE_DIR=/state \ -v "${state_dir}:/state" \ "${image}" tick 2>&1 )" diff --git a/scripts/generate-release-manifest.sh b/scripts/generate-release-manifest.sh index 5073d74..2caea61 100755 --- a/scripts/generate-release-manifest.sh +++ b/scripts/generate-release-manifest.sh @@ -83,7 +83,7 @@ manifest = { "artifacts": artifacts, "alignment": { "rule": "All artifacts sharing release_tag were built from git_commit with the same toolchain pins.", - "watchdog_cm_bootstrap": f"Use canonical-machine-image--{tag}.tar.gz with WATCHDOG_CM_SNAPSHOT_DIR; cartesi-machine in the watchdog image matches CARTESI_MACHINE_VERSION.", + "watchdog_cm_bootstrap": f"Use canonical-machine-image--{tag}.tar.gz with CARTESI_WATCHDOG_CM_SNAPSHOT_DIR; cartesi-machine in the watchdog image matches CARTESI_MACHINE_VERSION.", }, } json.dump(manifest, sys.stdout, indent=2) diff --git a/scripts/test-watchdog-divergence-drill.sh b/scripts/test-watchdog-divergence-drill.sh index 16fe8d5..b683f78 100755 --- a/scripts/test-watchdog-divergence-drill.sh +++ b/scripts/test-watchdog-divergence-drill.sh @@ -3,7 +3,7 @@ set -euo pipefail root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" -export WATCHDOG_LUA_DEPS="${WATCHDOG_LUA_DEPS:-${root}/.deps/lua}" +export CARTESI_WATCHDOG_LUA_DEPS="${CARTESI_WATCHDOG_LUA_DEPS:-${root}/.deps/lua}" set +e lua "${root}/watchdog/tests/drill_divergence.lua" diff --git a/sequencer/src/recovery/flusher.rs b/sequencer/src/recovery/flusher.rs index f4fb226..308086a 100644 --- a/sequencer/src/recovery/flusher.rs +++ b/sequencer/src/recovery/flusher.rs @@ -39,7 +39,7 @@ pub struct MempoolFlusher { /// `safe_poll_interval` is one block — matches the natural cadence for /// `get_transaction_count(Safe)` to advance. /// -/// H6 regression: both values must scale with `SEQ_SECONDS_PER_BLOCK`; a fixed +/// H6 regression: both values must scale with `CARTESI_SEQUENCER_SECONDS_PER_BLOCK`; a fixed /// 12s assumption would mis-pace on non-mainnet chains. fn derive_timeouts(seconds_per_block: u64) -> (Duration, Duration) { ( @@ -373,7 +373,7 @@ mod tests { assert_eq!( derive_timeouts(1), (Duration::from_secs(10), Duration::from_secs(1)), - "minimum accepted block time (H8: SEQ_SECONDS_PER_BLOCK >= 1)", + "minimum accepted block time (H8: CARTESI_SEQUENCER_SECONDS_PER_BLOCK >= 1)", ); } diff --git a/sequencer/src/runtime/config.rs b/sequencer/src/runtime/config.rs index ade3097..8fc55b2 100644 --- a/sequencer/src/runtime/config.rs +++ b/sequencer/src/runtime/config.rs @@ -38,10 +38,10 @@ Examples: --app-address 0x1111111111111111111111111111111111111111 \\ --batch-submitter-private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 - SEQ_ETH_RPC_URL=http://127.0.0.1:8545 \\ - SEQ_CHAIN_ID=31337 \\ - SEQ_APP_ADDRESS=0x1111111111111111111111111111111111111111 \\ - SEQ_BATCH_SUBMITTER_PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 \\ + CARTESI_SEQUENCER_BLOCKCHAIN_HTTP_ENDPOINT=http://127.0.0.1:8545 \\ + CARTESI_SEQUENCER_BLOCKCHAIN_ID=31337 \\ + CARTESI_SEQUENCER_APP_ADDRESS=0x1111111111111111111111111111111111111111 \\ + CARTESI_SEQUENCER_AUTH_PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 \\ sequencer\ ", group( @@ -52,32 +52,32 @@ Examples: ) )] pub struct RunConfig { - #[arg(long, env = "SEQ_HTTP_ADDR", default_value = DEFAULT_HTTP_ADDR, value_parser = parse_non_empty_string)] + #[arg(long, env = "CARTESI_SEQUENCER_HTTP_ADDR", default_value = DEFAULT_HTTP_ADDR, value_parser = parse_non_empty_string)] pub http_addr: String, - #[arg(long, env = "SEQ_DATA_DIR", default_value = DEFAULT_DATA_DIR, value_parser = parse_non_empty_string)] + #[arg(long, env = "CARTESI_SEQUENCER_DATA_DIR", default_value = DEFAULT_DATA_DIR, value_parser = parse_non_empty_string)] pub data_dir: String, - #[arg(long, env = "SEQ_ETH_RPC_URL", value_parser = parse_non_empty_string)] + #[arg(long, env = "CARTESI_SEQUENCER_BLOCKCHAIN_HTTP_ENDPOINT", value_parser = parse_non_empty_string)] pub eth_rpc_url: String, /// Error codes that trigger `get_logs` retries with a shorter block range. - #[arg(long, env = "SEQ_LONG_BLOCK_RANGE_ERROR_CODES", value_delimiter = ',', default_values = crate::l1::partition::DEFAULT_LONG_BLOCK_RANGE_ERROR_CODES)] + #[arg(long, env = "CARTESI_SEQUENCER_LONG_BLOCK_RANGE_ERROR_CODES", value_delimiter = ',', default_values = crate::l1::partition::DEFAULT_LONG_BLOCK_RANGE_ERROR_CODES)] pub long_block_range_error_codes: Vec, /// Expected chain ID. Validated against the RPC at startup. - #[arg(long, env = "SEQ_CHAIN_ID")] + #[arg(long, env = "CARTESI_SEQUENCER_BLOCKCHAIN_ID")] pub chain_id: u64, /// Application (EIP-712 verifying contract) address. - #[arg(long, env = "SEQ_APP_ADDRESS", value_parser = parse_address)] + #[arg(long, env = "CARTESI_SEQUENCER_APP_ADDRESS", value_parser = parse_address)] pub app_address: Address, /// Hex-encoded private key for the batch submitter. #[arg( long, - env = "SEQ_BATCH_SUBMITTER_PRIVATE_KEY", + env = "CARTESI_SEQUENCER_AUTH_PRIVATE_KEY", group = "batch_submitter_key_source" )] batch_submitter_private_key: Option, /// Path to a file whose first line contains the batch submitter private key. #[arg( long, - env = "SEQ_BATCH_SUBMITTER_PRIVATE_KEY_FILE", + env = "CARTESI_SEQUENCER_AUTH_PRIVATE_KEY_FILE", group = "batch_submitter_key_source" )] batch_submitter_private_key_file: Option, @@ -85,7 +85,7 @@ pub struct RunConfig { /// How often the batch submitter polls for new work when idle. #[arg( long, - env = "SEQ_BATCH_SUBMITTER_IDLE_POLL_INTERVAL_MS", + env = "CARTESI_SEQUENCER_BATCH_SUBMITTER_IDLE_POLL_INTERVAL_MS", default_value = "5000" )] pub batch_submitter_idle_poll_interval_ms: u64, @@ -93,7 +93,7 @@ pub struct RunConfig { /// Additional confirmations to wait for after a batch-submission tx is included on L1. #[arg( long, - env = "SEQ_BATCH_SUBMITTER_CONFIRMATION_DEPTH", + env = "CARTESI_SEQUENCER_BATCH_SUBMITTER_CONFIRMATION_DEPTH", default_value = "2" )] pub batch_submitter_confirmation_depth: u64, @@ -106,7 +106,11 @@ pub struct RunConfig { /// runway to investigate before the system gives up on the current /// batches — see `docs/recovery/README.md` "Step 1: Danger threshold" /// for the rationale. - #[arg(long, env = "SEQ_PREEMPTIVE_MARGIN_BLOCKS", default_value = "300")] + #[arg( + long, + env = "CARTESI_SEQUENCER_PREEMPTIVE_MARGIN_BLOCKS", + default_value = "300" + )] pub preemptive_margin_blocks: u64, /// Blocks of safe-head age after which the L1 read view is considered too @@ -116,12 +120,12 @@ pub struct RunConfig { /// less than the danger threshold (validated at startup). /// /// Default 600 (~2h at 12s/block). - #[arg(long, env = "SEQ_L1_READ_STALE_AFTER_BLOCKS", default_value = "600", value_parser = clap::value_parser!(u64).range(1..))] + #[arg(long, env = "CARTESI_SEQUENCER_L1_READ_STALE_AFTER_BLOCKS", default_value = "600", value_parser = clap::value_parser!(u64).range(1..))] pub l1_read_stale_after_blocks: u64, /// Assumed L1 block time in seconds. Used to estimate block progression from /// wall-clock time when the L1 provider is unreachable. - #[arg(long, env = "SEQ_SECONDS_PER_BLOCK", default_value = "12", value_parser = clap::value_parser!(u64).range(1..))] + #[arg(long, env = "CARTESI_SEQUENCER_SECONDS_PER_BLOCK", default_value = "12", value_parser = clap::value_parser!(u64).range(1..))] pub seconds_per_block: u64, } @@ -255,7 +259,7 @@ mod tests { ); } - // ── H8 regression: SEQ_SECONDS_PER_BLOCK=0 is rejected by clap ── + // ── H8 regression: CARTESI_SEQUENCER_SECONDS_PER_BLOCK=0 is rejected by clap ── // // The H8 hardening added `value_parser = clap::value_parser!(u64).range(1..)` // on `seconds_per_block` to prevent a divide-by-zero panic in the diff --git a/tests/e2e/src/bin/devnet_stack.rs b/tests/e2e/src/bin/devnet_stack.rs index e49ca4b..65bce31 100644 --- a/tests/e2e/src/bin/devnet_stack.rs +++ b/tests/e2e/src/bin/devnet_stack.rs @@ -3,7 +3,7 @@ //! Local Anvil + rollups devnet + `sequencer-devnet` for manual watchdog runs. //! -//! Prints `WATCHDOG_*` exports, then blocks until Ctrl+C. +//! Prints `CARTESI_WATCHDOG_*` exports, then blocks until Ctrl+C. use rollups_harness::{ HarnessResult, ManagedSequencer, devnet_sequencer_config_no_faketime, paths, @@ -34,21 +34,30 @@ async fn main() -> HarnessResult<()> { eprintln!( "--- export these, then run: ./watchdog/sequencer-watchdog init && ./watchdog/sequencer-watchdog tick ---" ); - eprintln!("export WATCHDOG_SEQUENCER_URL={}", runtime.endpoint()); - eprintln!("export WATCHDOG_L1_RPC_URL={}", runtime.l1_endpoint()); eprintln!( - "export WATCHDOG_INPUTBOX_ADDRESS={}", + "export CARTESI_WATCHDOG_SEQUENCER_URL={}", + runtime.endpoint() + ); + eprintln!( + "export CARTESI_WATCHDOG_BLOCKCHAIN_HTTP_ENDPOINT={}", + runtime.l1_endpoint() + ); + eprintln!( + "export CARTESI_WATCHDOG_CONTRACTS_INPUT_BOX_ADDRESS={}", runtime.input_box_address() ); - eprintln!("export WATCHDOG_APP_ADDRESS={}", runtime.app_address()); - eprintln!("export WATCHDOG_STATE_DIR={}", state_dir.display()); eprintln!( - "export WATCHDOG_CM_SNAPSHOT_DIR={}", + "export CARTESI_WATCHDOG_APP_ADDRESS={}", + runtime.app_address() + ); + eprintln!("export CARTESI_WATCHDOG_STATE_DIR={}", state_dir.display()); + eprintln!( + "export CARTESI_WATCHDOG_CM_SNAPSHOT_DIR={}", machine_image.display() ); - eprintln!("export WATCHDOG_CM_SNAPSHOT_SAFE_BLOCK=0"); + eprintln!("export CARTESI_WATCHDOG_CM_SNAPSHOT_SAFE_BLOCK=0"); eprintln!( - "export WATCHDOG_LUA_DEPS={}/.deps/lua", + "export CARTESI_WATCHDOG_LUA_DEPS={}/.deps/lua", paths::workspace_root().display() ); eprintln!(); @@ -59,8 +68,8 @@ async fn main() -> HarnessResult<()> { ); eprintln!(); eprintln!("Run watchdog (from repo root, after `just watchdog-lua-deps`):"); - eprintln!(" export WATCHDOG_LUA_ROOT=$(pwd)"); - eprintln!(" export WATCHDOG_LUA_BIN=lua"); + eprintln!(" export CARTESI_WATCHDOG_LUA_ROOT=$(pwd)"); + eprintln!(" export CARTESI_WATCHDOG_LUA_BIN=lua"); eprintln!(" ./watchdog/sequencer-watchdog init"); eprintln!(" ./watchdog/sequencer-watchdog tick"); eprintln!(); diff --git a/tests/e2e/src/test_cases.rs b/tests/e2e/src/test_cases.rs index 08e4df9..fa55467 100644 --- a/tests/e2e/src/test_cases.rs +++ b/tests/e2e/src/test_cases.rs @@ -25,7 +25,7 @@ const DEFAULT_MAX_FEE: u16 = 1200; // ── Zone-math constants for the outage-matrix and recovery tests ───────── // // These derive from the sequencer's default config so a change to -// `MAX_WAIT_BLOCKS`, `SEQ_PREEMPTIVE_MARGIN_BLOCKS`, or `SEQ_SECONDS_PER_BLOCK` +// `MAX_WAIT_BLOCKS`, `CARTESI_SEQUENCER_PREEMPTIVE_MARGIN_BLOCKS`, or `CARTESI_SEQUENCER_SECONDS_PER_BLOCK` // flows through here automatically. The compile-time asserts below catch any // drift that would invalidate the zone framing of the tests (e.g., a per-retry // advance that no longer crosses MAX_WAIT in the orchestrator loop). @@ -37,13 +37,13 @@ const DEFAULT_MAX_FEE: u16 = 1200; /// `sequencer_core::MAX_WAIT_BLOCKS`. const MAX_WAIT_BLOCKS: u64 = sequencer_core::MAX_WAIT_BLOCKS; -/// Default `SEQ_PREEMPTIVE_MARGIN_BLOCKS` from `runtime/config.rs`. The +/// Default `CARTESI_SEQUENCER_PREEMPTIVE_MARGIN_BLOCKS` from `runtime/config.rs`. The /// harness spawn path does not override this flag, so the binary uses the /// configured default. If the default changes, update here so /// `DANGER_THRESHOLD_BLOCKS` stays aligned. const DEFAULT_PREEMPTIVE_MARGIN_BLOCKS: u64 = 300; -/// Default `SEQ_SECONDS_PER_BLOCK` from `runtime/config.rs`. The harness +/// Default `CARTESI_SEQUENCER_SECONDS_PER_BLOCK` from `runtime/config.rs`. The harness /// `advance_wall_and_mine` also assumes this value internally. const DEFAULT_SECONDS_PER_BLOCK: u64 = 12; diff --git a/tests/e2e/src/watchdog_compare.rs b/tests/e2e/src/watchdog_compare.rs index fc17589..f376b22 100644 --- a/tests/e2e/src/watchdog_compare.rs +++ b/tests/e2e/src/watchdog_compare.rs @@ -280,35 +280,35 @@ fn compare_env( ) -> Vec<(String, String)> { vec![ ( - "WATCHDOG_LUA_DEPS".into(), + "CARTESI_WATCHDOG_LUA_DEPS".into(), lua_deps.to_string_lossy().into_owned(), ), ( - "WATCHDOG_SEQUENCER_URL".into(), + "CARTESI_WATCHDOG_SEQUENCER_URL".into(), runtime.endpoint().to_string(), ), ( - "WATCHDOG_L1_RPC_URL".into(), + "CARTESI_WATCHDOG_BLOCKCHAIN_HTTP_ENDPOINT".into(), runtime.l1_endpoint().to_string(), ), ( - "WATCHDOG_INPUTBOX_ADDRESS".into(), + "CARTESI_WATCHDOG_CONTRACTS_INPUT_BOX_ADDRESS".into(), runtime.input_box_address().to_string(), ), ( - "WATCHDOG_APP_ADDRESS".into(), + "CARTESI_WATCHDOG_APP_ADDRESS".into(), runtime.app_address().to_string(), ), ( - "WATCHDOG_STATE_DIR".into(), + "CARTESI_WATCHDOG_STATE_DIR".into(), state_dir.to_string_lossy().into_owned(), ), ( - "WATCHDOG_CM_SNAPSHOT_DIR".into(), + "CARTESI_WATCHDOG_CM_SNAPSHOT_DIR".into(), machine_image.to_string_lossy().into_owned(), ), ( - "WATCHDOG_CM_SNAPSHOT_SAFE_BLOCK".into(), + "CARTESI_WATCHDOG_CM_SNAPSHOT_SAFE_BLOCK".into(), GENESIS_SAFE_BLOCK.into(), ), ] @@ -329,8 +329,8 @@ async fn run_lua_main( .arg(command_name) .stdout(Stdio::piped()) .stderr(Stdio::piped()); - command.env("WATCHDOG_LUA_ROOT", workspace); - command.env("WATCHDOG_LUA_BIN", "lua"); + command.env("CARTESI_WATCHDOG_LUA_ROOT", workspace); + command.env("CARTESI_WATCHDOG_LUA_BIN", "lua"); for (key, value) in compare_env(runtime, state_dir, machine_image, lua_deps.as_path()) { command.env(key, value); } diff --git a/tests/harness/src/sequencer.rs b/tests/harness/src/sequencer.rs index 7f402df..ae4402f 100644 --- a/tests/harness/src/sequencer.rs +++ b/tests/harness/src/sequencer.rs @@ -539,7 +539,7 @@ impl ManagedSequencer { /// backward-jump test) should use [`Self::set_faketime_offset`] and /// [`Self::mine_l1_blocks`] directly. /// - /// Assumes `SEQ_SECONDS_PER_BLOCK = 12`. If a test changes that via env, + /// Assumes `CARTESI_SEQUENCER_SECONDS_PER_BLOCK = 12`. If a test changes that via env, /// this helper's block count will be wrong — prefer the direct dials in /// that case. pub async fn advance_wall_and_mine(&mut self, duration: Duration) -> HarnessResult<()> { diff --git a/watchdog/Dockerfile b/watchdog/Dockerfile index 9657de0..bf289d8 100644 --- a/watchdog/Dockerfile +++ b/watchdog/Dockerfile @@ -96,7 +96,7 @@ RUN chmod +x /usr/local/bin/sequencer-watchdog /usr/local/bin/cartesi-machine \ " \"cartesi_machine_version\": \"${CARTESI_MACHINE_VERSION}\"" \ "}" > /opt/watchdog/RELEASE.json -ENV WATCHDOG_LUA_DEPS=/opt/watchdog/lib \ +ENV CARTESI_WATCHDOG_LUA_DEPS=/opt/watchdog/lib \ LUA_PATH="/opt/watchdog/lua/?.lua;/opt/watchdog/lua/?/init.lua;/usr/local/share/lua/5.4/?.lua;/usr/local/share/lua/5.4/?/init.lua;;" \ LUA_CPATH="/opt/watchdog/lib/?.so;/usr/local/lib/lua/5.4/?.so;;" \ LD_LIBRARY_PATH="/usr/local/lib" \ diff --git a/watchdog/README.md b/watchdog/README.md index 36f7075..c77569c 100644 --- a/watchdog/README.md +++ b/watchdog/README.md @@ -15,7 +15,7 @@ docker pull ghcr.io/cartesi/sequencer-watchdog:vX just doctor # lua + cartesi + lcurl + machine_cartesi load probe just watchdog-lua-deps # .deps/lua/lcurl.so (needs libcurl + liblua5.4-dev) just test-watchdog # unit tests (mocked HTTP; no lcurl required) -just devnet-for-watchdog # local Anvil + sequencer-devnet (prints WATCHDOG_* env) +just devnet-for-watchdog # local Anvil + sequencer-devnet (prints CARTESI_WATCHDOG_* env) ``` Watchdog-local recipes also live in [`justfile`](justfile) (`just -f watchdog/justfile `). diff --git a/watchdog/config.lua b/watchdog/config.lua index 76c694d..f5404ea 100644 --- a/watchdog/config.lua +++ b/watchdog/config.lua @@ -59,7 +59,7 @@ end function config.load_state_dir(env) env = normalize_env(env) - return required("WATCHDOG_STATE_DIR", env) + return required("CARTESI_WATCHDOG_STATE_DIR", env) end function config.load_init(env) @@ -69,22 +69,22 @@ function config.load_init(env) -- a canonical CM re-derivation. One cycle per process; infra schedules it. return { version = config.VERSION, - sequencer_url = required("WATCHDOG_SEQUENCER_URL", env), - input_box_address = required("WATCHDOG_INPUTBOX_ADDRESS", env), - app_address = required("WATCHDOG_APP_ADDRESS", env), - input_added_topic = env.WATCHDOG_INPUT_ADDED_TOPIC, - state_dir = required("WATCHDOG_STATE_DIR", env), - cm_snapshot_dir = required("WATCHDOG_CM_SNAPSHOT_DIR", env), + sequencer_url = required("CARTESI_WATCHDOG_SEQUENCER_URL", env), + input_box_address = required("CARTESI_WATCHDOG_CONTRACTS_INPUT_BOX_ADDRESS", env), + app_address = required("CARTESI_WATCHDOG_APP_ADDRESS", env), + input_added_topic = env.CARTESI_WATCHDOG_INPUT_ADDED_TOPIC, + state_dir = required("CARTESI_WATCHDOG_STATE_DIR", env), + cm_snapshot_dir = required("CARTESI_WATCHDOG_CM_SNAPSHOT_DIR", env), cm_snapshot_safe_block = optional_required_number( - "WATCHDOG_CM_SNAPSHOT_DIR", - "WATCHDOG_CM_SNAPSHOT_SAFE_BLOCK", + "CARTESI_WATCHDOG_CM_SNAPSHOT_DIR", + "CARTESI_WATCHDOG_CM_SNAPSHOT_SAFE_BLOCK", env ), - cm_image_hash = env.WATCHDOG_CM_IMAGE_HASH, - retry_attempts = optional_number("WATCHDOG_RETRY_ATTEMPTS", 3, env), - retry_delay_sec = optional_number("WATCHDOG_RETRY_DELAY_SEC", 5, env), + cm_image_hash = env.CARTESI_WATCHDOG_CM_IMAGE_HASH, + retry_attempts = optional_number("CARTESI_WATCHDOG_RETRY_ATTEMPTS", 3, env), + retry_delay_sec = optional_number("CARTESI_WATCHDOG_RETRY_DELAY_SEC", 5, env), long_block_range_error_codes = split_csv( - env.WATCHDOG_LONG_BLOCK_RANGE_ERROR_CODES or "-32005,-32600,-32602,-32616" + env.CARTESI_WATCHDOG_LONG_BLOCK_RANGE_ERROR_CODES or "-32005,-32600,-32602,-32616" ), } end @@ -131,7 +131,7 @@ function config.from_persisted(state_dir, data, env) version = config.VERSION, state_dir = state_dir, sequencer_url = required_field(data, "sequencer_url"), - l1_rpc_url = required("WATCHDOG_L1_RPC_URL", env), + l1_rpc_url = required("CARTESI_WATCHDOG_BLOCKCHAIN_HTTP_ENDPOINT", env), input_box_address = required_field(data, "input_box_address"), app_address = required_field(data, "app_address"), input_added_topic = data.input_added_topic, diff --git a/watchdog/main.lua b/watchdog/main.lua index a7ecd97..9b079ae 100644 --- a/watchdog/main.lua +++ b/watchdog/main.lua @@ -19,7 +19,7 @@ local EXIT_TRANSIENT = 1 local EXIT_DIVERGENCE = 2 local function prepend_deps_cpath() - local deps = os.getenv("WATCHDOG_LUA_DEPS") + local deps = os.getenv("CARTESI_WATCHDOG_LUA_DEPS") if deps and deps ~= "" then package.cpath = deps .. "/?.so;" .. package.cpath end diff --git a/watchdog/sequencer-watchdog b/watchdog/sequencer-watchdog index 285729c..a92f099 100755 --- a/watchdog/sequencer-watchdog +++ b/watchdog/sequencer-watchdog @@ -2,23 +2,23 @@ # Production CLI wrapper for watchdog subcommands. set -euo pipefail -if [[ "${WATCHDOG_PRINT_RELEASE_INFO:-0}" == "1" ]]; then +if [[ "${CARTESI_WATCHDOG_PRINT_RELEASE_INFO:-0}" == "1" ]]; then cat /opt/watchdog/RELEASE.json || true cartesi-machine --version 2>&1 | sed 's/^/cartesi-machine: /' || true exit 0 fi -lua_root="${WATCHDOG_LUA_ROOT:-/opt/watchdog/lua}" -lua_bin="${WATCHDOG_LUA_BIN:-lua5.4}" +lua_root="${CARTESI_WATCHDOG_LUA_ROOT:-/opt/watchdog/lua}" +lua_bin="${CARTESI_WATCHDOG_LUA_BIN:-lua5.4}" cd "${lua_root}" if [[ "$#" -gt 0 && ( "$1" == "init" || "$1" == "tick" ) ]]; then - : "${WATCHDOG_STATE_DIR:?WATCHDOG_STATE_DIR is required}" - mkdir -p "$WATCHDOG_STATE_DIR" - exec 9>"$WATCHDOG_STATE_DIR/run.lock" + : "${CARTESI_WATCHDOG_STATE_DIR:?CARTESI_WATCHDOG_STATE_DIR is required}" + mkdir -p "$CARTESI_WATCHDOG_STATE_DIR" + exec 9>"$CARTESI_WATCHDOG_STATE_DIR/run.lock" if ! flock -n 9; then - echo "watchdog state is already locked: $WATCHDOG_STATE_DIR/run.lock" >&2 + echo "watchdog state is already locked: $CARTESI_WATCHDOG_STATE_DIR/run.lock" >&2 exit 1 fi fi diff --git a/watchdog/tests/drill_divergence.lua b/watchdog/tests/drill_divergence.lua index b47bc63..ad4b69c 100644 --- a/watchdog/tests/drill_divergence.lua +++ b/watchdog/tests/drill_divergence.lua @@ -9,7 +9,7 @@ package.path = "./?.lua;./?/init.lua;" .. package.path -local deps_lua = os.getenv("WATCHDOG_LUA_DEPS") +local deps_lua = os.getenv("CARTESI_WATCHDOG_LUA_DEPS") if deps_lua and deps_lua ~= "" then package.cpath = deps_lua .. "/?.so;" .. package.cpath end diff --git a/watchdog/tests/e2e.lua b/watchdog/tests/e2e.lua index 8322de7..40c8d08 100644 --- a/watchdog/tests/e2e.lua +++ b/watchdog/tests/e2e.lua @@ -182,11 +182,11 @@ table.insert(scenarios, { name = "compare-runner-with-sequencer", fn = function() local scenario = "compare-runner-with-sequencer" - local sequencer_url = os.getenv("WATCHDOG_E2E_SEQUENCER_URL") + local sequencer_url = os.getenv("CARTESI_WATCHDOG_E2E_SEQUENCER_URL") if not sequencer_url or sequencer_url == "" then return skip( scenario, - "set WATCHDOG_E2E_SEQUENCER_URL to a live sequencer base URL to run this scenario" + "set CARTESI_WATCHDOG_E2E_SEQUENCER_URL to a live sequencer base URL to run this scenario" ) end require_cartesi_machine() @@ -209,10 +209,10 @@ table.insert(scenarios, { state_dir = state_dir, cm_snapshot_dir = MACHINE_IMAGE, cm_snapshot_safe_block = GENESIS_SAFE_BLOCK, - l1_rpc_url = os.getenv("WATCHDOG_E2E_L1_RPC_URL") or "http://127.0.0.1:8545", - input_box_address = os.getenv("WATCHDOG_E2E_INPUTBOX_ADDRESS") + l1_rpc_url = os.getenv("CARTESI_WATCHDOG_E2E_BLOCKCHAIN_HTTP_ENDPOINT") or "http://127.0.0.1:8545", + input_box_address = os.getenv("CARTESI_WATCHDOG_E2E_CONTRACTS_INPUT_BOX_ADDRESS") or "0x0000000000000000000000000000000000000000", - app_address = os.getenv("WATCHDOG_E2E_APP_ADDRESS") + app_address = os.getenv("CARTESI_WATCHDOG_E2E_APP_ADDRESS") or "0x1111111111111111111111111111111111111111", long_block_range_error_codes = { "-32005" }, retry_attempts = 1, diff --git a/watchdog/tests/run.lua b/watchdog/tests/run.lua index d949dcb..c462d8f 100644 --- a/watchdog/tests/run.lua +++ b/watchdog/tests/run.lua @@ -280,13 +280,13 @@ end) test("config loads snapshot directory safe block and optional topic", function() local env = { - WATCHDOG_SEQUENCER_URL = "http://seq", - WATCHDOG_INPUTBOX_ADDRESS = "0x9999999999999999999999999999999999999999", - WATCHDOG_APP_ADDRESS = "0x1111111111111111111111111111111111111111", - WATCHDOG_INPUT_ADDED_TOPIC = "0xtopic", - WATCHDOG_STATE_DIR = "/tmp/watchdog-state", - WATCHDOG_CM_SNAPSHOT_DIR = "/tmp/snapshot", - WATCHDOG_CM_SNAPSHOT_SAFE_BLOCK = "42", + CARTESI_WATCHDOG_SEQUENCER_URL = "http://seq", + CARTESI_WATCHDOG_CONTRACTS_INPUT_BOX_ADDRESS = "0x9999999999999999999999999999999999999999", + CARTESI_WATCHDOG_APP_ADDRESS = "0x1111111111111111111111111111111111111111", + CARTESI_WATCHDOG_INPUT_ADDED_TOPIC = "0xtopic", + CARTESI_WATCHDOG_STATE_DIR = "/tmp/watchdog-state", + CARTESI_WATCHDOG_CM_SNAPSHOT_DIR = "/tmp/snapshot", + CARTESI_WATCHDOG_CM_SNAPSHOT_SAFE_BLOCK = "42", } local cfg = config.load(env) @@ -301,13 +301,13 @@ end) test("config requires a sequencer URL", function() local ok, err = pcall(function() config.load({ - WATCHDOG_INPUTBOX_ADDRESS = "0x9999999999999999999999999999999999999999", - WATCHDOG_APP_ADDRESS = "0x1111111111111111111111111111111111111111", - WATCHDOG_STATE_DIR = "/tmp/watchdog-state", + CARTESI_WATCHDOG_CONTRACTS_INPUT_BOX_ADDRESS = "0x9999999999999999999999999999999999999999", + CARTESI_WATCHDOG_APP_ADDRESS = "0x1111111111111111111111111111111111111111", + CARTESI_WATCHDOG_STATE_DIR = "/tmp/watchdog-state", }) end) assert_eq(ok, false) - assert(tostring(err):find("WATCHDOG_SEQUENCER_URL", 1, true) ~= nil, "sequencer URL is required") + assert(tostring(err):find("CARTESI_WATCHDOG_SEQUENCER_URL", 1, true) ~= nil, "sequencer URL is required") end) test("checkpoint writes manifest-backed head pointer", function() @@ -541,8 +541,8 @@ test("init stores bootstrap snapshot as watchdog head", function() assert_eq(persisted.l1_rpc_url, nil) local tick_cfg = main_mod.load_tick_config({ - WATCHDOG_STATE_DIR = dir, - WATCHDOG_L1_RPC_URL = "http://tick-rpc", + CARTESI_WATCHDOG_STATE_DIR = dir, + CARTESI_WATCHDOG_BLOCKCHAIN_HTTP_ENDPOINT = "http://tick-rpc", }) assert_eq(tick_cfg.state_dir, dir) assert_eq(tick_cfg.sequencer_url, "http://sequencer") @@ -561,11 +561,11 @@ test("tick config requires current RPC URL outside persisted state", function() local ok, load_err = pcall(function() main_mod.load_tick_config({ - WATCHDOG_STATE_DIR = dir, + CARTESI_WATCHDOG_STATE_DIR = dir, }) end) assert_eq(ok, false) - assert(tostring(load_err):find("WATCHDOG_L1_RPC_URL", 1, true) ~= nil, tostring(load_err)) + assert(tostring(load_err):find("CARTESI_WATCHDOG_BLOCKCHAIN_HTTP_ENDPOINT", 1, true) ~= nil, tostring(load_err)) end) test("init refuses an already initialized state directory", function()