diff --git a/.cursor/rules/chain138-tokens-and-pmm.mdc b/.cursor/rules/chain138-tokens-and-pmm.mdc index 2a60c4a5..e067af1c 100644 --- a/.cursor/rules/chain138-tokens-and-pmm.mdc +++ b/.cursor/rules/chain138-tokens-and-pmm.mdc @@ -16,6 +16,8 @@ alwaysApply: true **PMM pools (live funded public):** cUSDT/cUSDC `0xff8d3b8fDF7B112759F076B69f4271D4209C0849` | cUSDT/USDT `0x6fc60DEDc92a2047062294488539992710b99D71` | cUSDC/USDC `0x9f74Be42725f2Aa072a9E0CdCce0E7203C510263` — see `docs/11-references/ADDRESS_MATRIX_AND_STATUS.md` / `PMM_DEX_ROUTING_STATUS.md`. +**Public cW\* mesh (cross-chain):** treat as **execution / corridor capacity** against reference-anchored GRU policy, not shadow FX — `docs/04-configuration/GRU_REFERENCE_PRIMACY_AND_MESH_EXECUTION_MODEL.md`, `cross-chain-pmm-lps/config/peg-bands.json` **`gruPolicyIntegration`**. + **cXAUC / cXAUT (XAU):** `0x290E52a8819A4fbD0714E517225429aA2B70EC6b`, `0x94e408E26c6FD8F4ee00b54dF19082FDA07dC96E` (6 decimals). **1 full token = 1 troy ounce Au** — not USD face value; see `EXPLORER_TOKEN_LIST_CROSSCHECK.md` section 5.1. **RPC (deploy):** `RPC_URL_138=http://192.168.11.211:8545`. **Deployer:** `0x4A666F96fC8764181194447A7dFdb7d471b301C8`. Add-liquidity reads tokens from the integration contract, not env. Do not use non-canonical Blockscout addresses (§2 of EXPLORER_TOKEN_LIST_CROSSCHECK). diff --git a/.cursor/rules/project-doc-and-deployment-refs.mdc b/.cursor/rules/project-doc-and-deployment-refs.mdc index 06fad335..5bd55eff 100644 --- a/.cursor/rules/project-doc-and-deployment-refs.mdc +++ b/.cursor/rules/project-doc-and-deployment-refs.mdc @@ -9,6 +9,7 @@ When answering token/PMM/deployment questions, prefer these docs over inferring **Canonical / verification:** `docs/11-references/EXPLORER_TOKEN_LIST_CROSSCHECK.md` (§5 canonical, §8 on-chain verification) **Token / bridge naming (UTRNF + DBIS `c*` mapping):** `docs/04-configuration/naming-conventions/README.md` (especially `02_DBIS_NAMESPACE_AND_UTRNF_MAPPING.md` for UTRNF `c` vs compliant money) +**GRU FX reference vs public PMM mesh:** `docs/04-configuration/GRU_REFERENCE_PRIMACY_AND_MESH_EXECUTION_MODEL.md` (reference-first policy; mesh = execution layer) **Contract addresses:** `docs/11-references/CONTRACT_ADDRESSES_REFERENCE.md` (includes **Ethereum mainnet optional TRUU PMM** subsection) **Address matrix:** `docs/11-references/ADDRESS_MATRIX_AND_STATUS.md` **Mainnet TRUU PMM (optional volatile rail):** `docs/03-deployment/MAINNET_PMM_TRUU_CWUSD_PEG_AND_BOT_RUNBOOK.md` section 11; `cross-chain-pmm-lps/config/deployment-status.json` `chains."1".pmmPoolsVolatile[]` diff --git a/.env.master.example b/.env.master.example index 29f60dea..bfd72f36 100644 --- a/.env.master.example +++ b/.env.master.example @@ -239,8 +239,11 @@ ETHEREUM_MAINNET_RPC= DODO_PMM_INTEGRATION_MAINNET= # --- Mainnet Aave flash quote-push (cWUSDC/USDC peg / rebalance without wallet USDC) --- # If the deployer wallet already has USDC + cWUSDC: bash scripts/deployment/apply-mainnet-cwusdc-usdc-peg-tranche-from-wallet.sh --dry-run | --apply +# Receiver only: bash scripts/deployment/deploy-mainnet-aave-quote-push-receiver.sh --dry-run | --apply # Deploy: bash scripts/deployment/deploy-mainnet-aave-quote-push-stack.sh --dry-run | --apply +# Treasury manager: bash scripts/deployment/deploy-mainnet-quote-push-treasury-manager.sh --dry-run | --apply # One shot: bash scripts/deployment/run-mainnet-aave-cwusdc-quote-push-once.sh --dry-run | --apply +# Keeper: bash scripts/deployment/run-mainnet-aave-quote-push-keeper.sh --dry-run | --apply # Loop: FLASH_LOOP_COUNT=3 bash scripts/deployment/run-mainnet-aave-cwusdc-quote-push-loop.sh --dry-run | --apply # Forge sources: smom-dbis-138/script/flash/RunMainnetAaveCwusdcUsdcQuotePushOnce.s.sol # Modeling (no chain writes): scripts/deployment/run-mainnet-cwusdc-flash-quote-push-model-sweep.sh @@ -259,6 +262,24 @@ UNWIND_TWO_HOP_POOL_A=0xe944b7Cb012A0820c07f54D51e92f0e1C74168DB UNWIND_TWO_HOP_POOL_B=0x27f3aE7EE71Be3d77bAf17d4435cF8B895DD25D2 UNWIND_TWO_HOP_MID_TOKEN=0xaF5017d0163ecb99d9B5D94e3b4D7b09Af44D8AE UNWIND_MIN_MID_OUT_RAW=1 +# Retained-surplus recycle / treasury manager policy: +# QUOTE_PUSH_RECEIVER_OWNER=0x... +# Live migration shortcut: +# bash scripts/deployment/deploy-mainnet-aave-quote-push-receiver.sh --apply +# AAVE_QUOTE_PUSH_RECEIVER_MAINNET= QUOTE_PUSH_TREASURY_TAKE_RECEIVER_OWNERSHIP=1 bash scripts/deployment/deploy-mainnet-quote-push-treasury-manager.sh --apply +# QUOTE_PUSH_TREASURY_MANAGER_MAINNET=0x... +# QUOTE_PUSH_TREASURY_OWNER=0x... +# QUOTE_PUSH_TREASURY_OPERATOR=0x... +# QUOTE_PUSH_TREASURY_GAS_RECIPIENT=0x... +# QUOTE_PUSH_TREASURY_RECYCLE_RECIPIENT=0x... +# QUOTE_PUSH_RECEIVER_RESERVE_RAW=0 +# QUOTE_PUSH_TREASURY_RESERVE_RAW=0 +# QUOTE_PUSH_TREASURY_TAKE_RECEIVER_OWNERSHIP=1 +# QUOTE_PUSH_KEEPER_SKIP_FLASH=0 +# QUOTE_PUSH_KEEPER_SKIP_RECYCLE=0 +# QUOTE_PUSH_DEPLOYER_GAS_FLOOR_ETH=0.003 +# QUOTE_PUSH_OPERATION_BUFFER_ETH=0.0005 +# QUOTE_PUSH_NATIVE_TOKEN_PRICE=3200 # Discover V3 pools: bash scripts/verify/probe-uniswap-v3-cwusdc-usdc-mainnet.sh # Optional min-out overrides (script derives from pool query + Aave premium when unset): # MIN_OUT_PMM= diff --git a/.github/workflows/validate-config.yml b/.github/workflows/validate-config.yml index 452295dc..0ccca5c4 100644 --- a/.github/workflows/validate-config.yml +++ b/.github/workflows/validate-config.yml @@ -40,6 +40,18 @@ on: - 'scripts/deployment/pmm-soak-export-wallet-grid.py' - '.github/workflows/pmm-soak-grid-smoke.yml' - 'docs/11-references/CHAIN138_GRID_6534_WALLET_FUNDING_PLAN.md' + - 'docs/04-configuration/GRU_REFERENCE_PRIMACY_AND_MESH_EXECUTION_MODEL.md' + - 'docs/04-configuration/GRU_C_STAR_V2_STANDARDS_MATRIX_AND_IMPLEMENTATION_PLAN.md' + - 'scripts/verify/check-gru-reference-primacy-integration.sh' + - 'cross-chain-pmm-lps/config/peg-bands.json' + - 'cross-chain-pmm-lps/docs/04-bot-policy.md' + - 'cross-chain-pmm-lps/docs/05-oracles.md' + - 'docs/00-meta/SUBMODULE_HYGIENE.md' + - 'docs/00-meta/NEXT_STEPS_LIST.md' + - 'docs/00-meta/OPERATOR_READY_CHECKLIST.md' + - 'docs/11-references/GRU_V2_PUBLIC_PROTOCOL_DEPLOYMENT_STATUS.md' + - '.cursor/rules/chain138-tokens-and-pmm.mdc' + - 'scripts/run-completable-tasks-from-anywhere.sh' push: branches: [master, main] paths: @@ -79,6 +91,18 @@ on: - 'scripts/deployment/pmm-soak-export-wallet-grid.py' - '.github/workflows/pmm-soak-grid-smoke.yml' - 'docs/11-references/CHAIN138_GRID_6534_WALLET_FUNDING_PLAN.md' + - 'docs/04-configuration/GRU_REFERENCE_PRIMACY_AND_MESH_EXECUTION_MODEL.md' + - 'docs/04-configuration/GRU_C_STAR_V2_STANDARDS_MATRIX_AND_IMPLEMENTATION_PLAN.md' + - 'scripts/verify/check-gru-reference-primacy-integration.sh' + - 'cross-chain-pmm-lps/config/peg-bands.json' + - 'cross-chain-pmm-lps/docs/04-bot-policy.md' + - 'cross-chain-pmm-lps/docs/05-oracles.md' + - 'docs/00-meta/SUBMODULE_HYGIENE.md' + - 'docs/00-meta/NEXT_STEPS_LIST.md' + - 'docs/00-meta/OPERATOR_READY_CHECKLIST.md' + - 'docs/11-references/GRU_V2_PUBLIC_PROTOCOL_DEPLOYMENT_STATUS.md' + - '.cursor/rules/chain138-tokens-and-pmm.mdc' + - 'scripts/run-completable-tasks-from-anywhere.sh' jobs: validate: @@ -88,6 +112,18 @@ jobs: - name: Checkout uses: actions/checkout@v4 + - uses: pnpm/action-setup@v4 + with: + version: 9 + + - uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'pnpm' + + - name: Install workspace dependencies + run: pnpm install --frozen-lockfile + - name: Config validation run: bash scripts/validation/validate-config-files.sh @@ -134,6 +170,7 @@ jobs: scripts/lib/pmm-soak-chain138-tick.sh scripts/deployment/chain138-pmm-random-soak-swaps.sh scripts/deployment/chain138-pmm-soak-grid-bot.sh + scripts/verify/check-gru-reference-primacy-integration.sh ) shellcheck -x "${shells[@]}" diff --git a/AGENTS.md b/AGENTS.md index 1651a56b..e4f28cce 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -18,6 +18,7 @@ Orchestration for Proxmox VE, Chain 138 (`smom-dbis-138/`), explorers, NPMplus, | **SolaceNet + gateway rails** (dbis_core) | Hub map: `docs/04-configuration/SOLACENET_PUBLIC_HUB.md`. Backlog: `dbis_core/docs/solacenet/REMAINING_TASKS_FULL_LIST.md`. Gap IDs: `dbis_core/docs/solacenet/PROTOCOL_GAPS_CHECKLIST.md`. **Delta audit** (missing wiring, naming drift, CI): `dbis_core/docs/solacenet/AUDIT_GAPS_INCONSISTENCIES_MISSING.md`. Enforce rails runbook: `dbis_core/docs/solacenet/SOLACENET_GATEWAY_RAILS_ENFORCE_RUNBOOK.md`. Tests: `cd dbis_core && npm run test:gateway` (unit + HTTP integration). **Provider seed:** `cd dbis_core && npm run seed:gateway-provider` (needs `DATABASE_URL`). **Smoke (auth):** `bash scripts/verify/check-dbis-core-gateway-rails.sh`. **Outbox worker:** `cd dbis_core && npm run worker:gateway-outbox` (`DATABASE_URL`). CI: `.github/workflows/dbis-core-gateway-ci.yml`. API: `GET/POST /api/v1/gateway/rails*` (optional `SOLACENET_GATEWAY_RAILS_ENFORCE`) — `dbis_core/src/core/gateway/routes/gateway.routes.ts`. | | cXAUC/cXAUT unit | 1 full token = 1 troy oz Au — `docs/11-references/EXPLORER_TOKEN_LIST_CROSSCHECK.md` (section 5.1) | | GRU / UTRNF token naming (`c*` vs collateral prefix) | `docs/04-configuration/naming-conventions/README.md`, `docs/04-configuration/naming-conventions/02_DBIS_NAMESPACE_AND_UTRNF_MAPPING.md` | +| **GRU reference primacy vs public cW\* PMM mesh** (FX policy; mesh = execution, not shadow oracle) | `docs/04-configuration/GRU_REFERENCE_PRIMACY_AND_MESH_EXECUTION_MODEL.md` | | PMM mesh 6s tick | `smom-dbis-138/scripts/reserve/pmm-mesh-6s-automation.sh` — `docs/integration/ORACLE_AND_KEEPER_CHAIN138.md` (PMM mesh automation) | | **PMM soak grid (33×33×6 wallets)** | `docs/11-references/CHAIN138_GRID_6534_WALLET_FUNDING_PLAN.md` — one-shot `scripts/deployment/pmm-soak-complete-operator-bootstrap.sh` (`PMM_SOAK_AUTO_INIT_GRID_MNEMONIC=1` … `--apply-funds --to-linear 19`); full-grid resume `scripts/deployment/pmm-soak-complete-grid-funding-operator.sh` (`PMM_SOAK_START_LEG`, `PMM_SOAK_RESUME_NATIVE_FROM_LINEAR`, `PMM_SOAK_RPC_URL_OVERRIDE`, `PMM_SOAK_FUND_PROGRESS_EVERY` via fund-grid); tranche driver `scripts/deployment/pmm-soak-operator-fund-full-grid-tranches.sh`; export `pmm-soak-export-wallet-grid.py`, fund `pmm-soak-operator-fund-grid.sh`, pools `scripts/lib/pmm-soak-pools.sh`, bots `chain138-pmm-soak-grid-bot.sh` / `chain138-pmm-random-soak-swaps.sh` (`--pool-preset`, `--swap-via`; `scripts/lib/pmm-soak-dotenv-override.sh` preserves caller `PMM_SOAK_POOL_*` / `CHAIN138_PMM_SOAK_SWAP_VIA` over `.env`), smoke `scripts/deployment/pmm-soak-grid-smoke-check.sh`, CI `.github/workflows/pmm-soak-grid-smoke.yml` | | Mainnet cWUSD\* peg, TRUU PMM, bot readiness | `docs/03-deployment/MAINNET_PMM_TRUU_CWUSD_PEG_AND_BOT_RUNBOOK.md` (§11 live inventory) — `scripts/verify/check-mainnet-pmm-peg-bot-readiness.sh`, `scripts/deployment/deploy-mainnet-pmm-cw-truu-pool.sh`, `scripts/deployment/add-mainnet-truu-pmm-topup.sh`, `scripts/deployment/compute-mainnet-truu-liquidity-amounts.sh`, `scripts/deployment/compute-mainnet-truu-pmm-seed-amounts.sh`; `cross-chain-pmm-lps/config/deployment-status.json` `pmmPoolsVolatile`; `docs/11-references/CONTRACT_ADDRESSES_REFERENCE.md` (Mainnet TRUU PMM); `check-full-deployment-status.sh` when `ETHEREUM_MAINNET_RPC` + `DODO_PMM_INTEGRATION_MAINNET` are set | diff --git a/docs/00-meta/NEXT_STEPS_LIST.md b/docs/00-meta/NEXT_STEPS_LIST.md index dfa92ab4..4cff21a9 100644 --- a/docs/00-meta/NEXT_STEPS_LIST.md +++ b/docs/00-meta/NEXT_STEPS_LIST.md @@ -5,6 +5,8 @@ **Refs:** [TODOS_CONSOLIDATED.md](TODOS_CONSOLIDATED.md), [REMAINING_DEPLOYMENTS_FOR_FULL_NETWORK_COVERAGE.md](../03-deployment/REMAINING_DEPLOYMENTS_FOR_FULL_NETWORK_COVERAGE.md), [TASKS_ROUTING_SWAP_CROSSCHAIN.md](TASKS_ROUTING_SWAP_CROSSCHAIN.md). **Full execution (all + optional, suggested order):** [EXECUTION_CHECKLIST_MULTIPLE_ROUTES_AND_LIQUIDITY.md](EXECUTION_CHECKLIST_MULTIPLE_ROUTES_AND_LIQUIDITY.md). +**GRU reference primacy (mesh vs policy):** `bash scripts/verify/check-gru-reference-primacy-integration.sh` — also runs inside `bash scripts/validation/validate-config-files.sh`. Submodule workflow: [SUBMODULE_HYGIENE.md](SUBMODULE_HYGIENE.md) section **cross-chain-pmm-lps**. + **Completion check (current baseline):** Full run including optional: completable ✅, validate-config ✅, PMM pool balances ✅ (Pool 1: 2M/2M), preflight ✅, token-aggregation build ✅, on-chain **67/67** (current canonical `check-contracts-on-chain-138.sh` inventory) ✅, unit tests 457 ✅, deployer-gas dry-run ✅, fund-ccip dry-run ✅, E2E flow dry-run ✅, E2E routing ✅ (**37** public domains **Failed: 0** on 2026-03-06; **44** on 2026-03-29 re-check), operator script --skip-backup ✅ (NPMplus RPC + Blockscout verify). **Live 2026-03-30:** [LIVE_VERIFICATION_LOG_2026-03-30.md](LIVE_VERIFICATION_LOG_2026-03-30.md). **Audit (2026-03-06):** [DOTENV_AND_MARKDOWN_AUDIT_GAPS_AND_RECOMMENDATIONS.md](DOTENV_AND_MARKDOWN_AUDIT_GAPS_AND_RECOMMENDATIONS.md) — required dotenv/markdown info, gaps, and recommendations. B.1/B.2 still blocked (need CRO/WEMIX); B.3 blocked (LINK/gas); A2 env set (CHAIN_138_DODO_PMM_INTEGRATION in smom-dbis-138/.env); A3/C3–C8, Phase C, LINK relay, B4/B5 remain pending or optional. --- diff --git a/docs/00-meta/OPERATOR_READY_CHECKLIST.md b/docs/00-meta/OPERATOR_READY_CHECKLIST.md index 27d017bf..dcc1b043 100644 --- a/docs/00-meta/OPERATOR_READY_CHECKLIST.md +++ b/docs/00-meta/OPERATOR_READY_CHECKLIST.md @@ -9,7 +9,7 @@ **One-command LAN wrapper:** `./scripts/run-full-operator-completion-from-lan.sh --dry-run` prints the full execution order starting with the token-aggregation `/api/v1` repair, then E2E, then a **non-fatal** `check-info-defi-oracle-public.sh`. Add `--fix-e2e-if-needed`, `--install-cron`, `--include-config-ready-chains`, `--include-chain138-next-steps`, and `--include-send-cross-chain --send-amount 0.01` as needed. -**Submodule working trees (no local edits in submodules):** `bash scripts/verify/submodules-clean.sh` — see [SUBMODULE_HYGIENE.md](SUBMODULE_HYGIENE.md). +**Submodule working trees (no local edits in submodules):** `bash scripts/verify/submodules-clean.sh` — see [SUBMODULE_HYGIENE.md](SUBMODULE_HYGIENE.md). **GRU mesh vs policy wiring:** `bash scripts/verify/check-gru-reference-primacy-integration.sh` (also step 1 of completable / `validate-config-files.sh`). **Proxmox SSH (all five hypervisors):** `bash scripts/security/ensure-proxmox-ssh-access.sh` — key-based **BatchMode** check to **192.168.11.10–.14** (ML110 + r630-01..04). Optional `bash scripts/security/ensure-proxmox-ssh-access.sh --fqdn` uses **`*.sankofa.nexus`** (`config/ip-addresses.conf` `PROXMOX_FQDN_*`); skips with a hint if DNS is missing. Optional `--copy` runs **`ssh-copy-id`** per host (interactive). **LAN DNS for FQDNs:** `bash scripts/verify/check-proxmox-mgmt-fqdn.sh` and `bash scripts/verify/check-proxmox-mgmt-fqdn.sh --print-hosts` (emits `/etc/hosts` lines for operator laptops). **NPMplus tunnel:** `ssh -L 8181:192.168.11.167:81 -N root@r630-01.sankofa.nexus` or `root@192.168.11.11`, then `http://127.0.0.1:8181`. diff --git a/docs/00-meta/SUBMODULE_HYGIENE.md b/docs/00-meta/SUBMODULE_HYGIENE.md index f8d29fc2..33113693 100644 --- a/docs/00-meta/SUBMODULE_HYGIENE.md +++ b/docs/00-meta/SUBMODULE_HYGIENE.md @@ -1,6 +1,6 @@ # Submodule and explorer remote hygiene -**Last Updated:** 2026-03-27 +**Last Updated:** 2026-04-12 **Purpose:** Operational notes for the many git submodules under the proxmox parent repo: detached HEAD, remotes, pushes, and non-secret JSON env snapshots. --- @@ -79,6 +79,14 @@ See each submodule’s `config/README.md` for a short in-tree note. --- +## cross-chain-pmm-lps (public cW\* PMM mesh) + +Parent repo policy treats the mesh as **execution against reference-anchored GRU/FX**, not standalone shadow FX — `docs/04-configuration/GRU_REFERENCE_PRIMACY_AND_MESH_EXECUTION_MODEL.md`. + +When you change **`cross-chain-pmm-lps/config/peg-bands.json`**, keep **`gruPolicyIntegration`** (`referencePrimacyDoc`, `meshExecutionRole`); parent CI validates it via `scripts/verify/check-gru-reference-primacy-integration.sh` (invoked from `scripts/validation/validate-config-files.sh`). **Workflow:** commit inside `cross-chain-pmm-lps` → push submodule remote → in parent root `git add cross-chain-pmm-lps` → commit pointer. + +--- + ## Related - **[AGENTS.md](../../AGENTS.md)** — quick pointers including submodule discipline diff --git a/docs/03-deployment/FINAL_UNBLOCK_CHECKLIST_MAINNET_BSC.md b/docs/03-deployment/FINAL_UNBLOCK_CHECKLIST_MAINNET_BSC.md index 1ebfacbc..b46e3fbe 100644 --- a/docs/03-deployment/FINAL_UNBLOCK_CHECKLIST_MAINNET_BSC.md +++ b/docs/03-deployment/FINAL_UNBLOCK_CHECKLIST_MAINNET_BSC.md @@ -83,6 +83,10 @@ The bridge can be technically deliverable at the bootstrap floor while still bei - Live bridge inventory after the bootstrap top-up and replay check: **`0.009 WETH`** - Additional WETH still needed to clear that queued release: **`0.091 WETH`** +The worker is also back on forward-only monitoring (`START_BLOCK=latest`), and the known +oversized historical WETH backlog ids are intentionally parked in `RELAY_SKIP_MESSAGE_IDS` +so restarts do not repopulate stale queue debt. + Use the health checker below to confirm the exact shortfall before topping up: ```bash diff --git a/docs/03-deployment/MAINNET_WETH_RELAY_BACKLOG_POLICY.md b/docs/03-deployment/MAINNET_WETH_RELAY_BACKLOG_POLICY.md new file mode 100644 index 00000000..fa3089ba --- /dev/null +++ b/docs/03-deployment/MAINNET_WETH_RELAY_BACKLOG_POLICY.md @@ -0,0 +1,52 @@ +# Mainnet WETH Relay Backlog Policy + +This note documents the intentional backlog policy for the `mainnet-weth` relay worker. + +## Current policy + +- The worker runs in **forward-only** mode with `START_BLOCK=latest`. +- Historical oversized WETH release messages that are not meant to be replayed on every restart + are explicitly parked in `RELAY_SKIP_MESSAGE_IDS`. +- The worker remains **operational** with: + - `RELAY_SHEDDING=0` + - `RELAY_DELIVERY_ENABLED=1` + - `RELAY_ENFORCE_BRIDGE_TOKEN_BALANCE=1` + +## Why this exists + +The Chain 138 -> Ethereum Mainnet WETH lane had accumulated historical source messages whose +release amounts were larger than the current Mainnet relay bridge float. Replaying them on every +service restart created stale queue debt and made lane health depend on old backlog instead of +current forward traffic. + +Parking those known historical message IDs is safer than repeatedly replaying them when: + +- there is no active intent to fund and deliver those exact historical releases now +- there is no source-side cancel path +- the goal is to keep the worker truthful for current traffic + +## What stays live + +- New source `MessageSent` events are still monitored. +- Current forward traffic still relays normally. +- Underfunded new releases are deferred by the bridge-inventory guard instead of spending gas on a + reverting destination transaction. + +## Operational rule + +If you deliberately want to replay a parked historical WETH release later, do all of the following +in one planned operator pass: + +1. Remove only the specific message ID from `RELAY_SKIP_MESSAGE_IDS`. +2. Set an explicit replay `START_BLOCK` that includes the source message. +3. Restart only `ccip-relay`. +4. Restore `START_BLOCK=latest` after the replay window is complete. + +## Known historical WETH backlog posture + +The current parked IDs live in: + +- [`smom-dbis-138/services/relay/.env.mainnet-weth`](/home/intlc/projects/proxmox/smom-dbis-138/services/relay/.env.mainnet-weth) + +Treat that env list as the enforced machine-readable source, and this document as the human policy +reference explaining why those IDs are intentionally skipped. diff --git a/docs/03-deployment/PHASE_C_CW_AND_EDGE_POOLS_RUNBOOK.md b/docs/03-deployment/PHASE_C_CW_AND_EDGE_POOLS_RUNBOOK.md index d11b8d24..547373eb 100644 --- a/docs/03-deployment/PHASE_C_CW_AND_EDGE_POOLS_RUNBOOK.md +++ b/docs/03-deployment/PHASE_C_CW_AND_EDGE_POOLS_RUNBOOK.md @@ -40,6 +40,8 @@ bash scripts/verify/check-gru-v2-deployment-queue.sh Run deviation watcher and peg-band config from cross-chain-pmm-lps when cW* and edge pools are live. +**Policy:** peg bands and bot behavior must follow **reference-anchored** GRU/FX rules (OMNL rate matrix, agreed oracles, reserve gates) — see [GRU_REFERENCE_PRIMACY_AND_MESH_EXECUTION_MODEL.md](../04-configuration/GRU_REFERENCE_PRIMACY_AND_MESH_EXECUTION_MODEL.md). The mesh **implements** corridors; it does not replace institution-grade reference pricing. + --- ## Quick ref @@ -47,3 +49,4 @@ Run deviation watcher and peg-band config from cross-chain-pmm-lps when cW* and - Pool matrix: cross-chain-pmm-lps/config/pool-matrix.json - Deployment status: cross-chain-pmm-lps/config/deployment-status.json - Recipe: cross-chain-pmm-lps/docs/06-deployment-recipe.md +- Reference primacy + mesh: [GRU_REFERENCE_PRIMACY_AND_MESH_EXECUTION_MODEL.md](../04-configuration/GRU_REFERENCE_PRIMACY_AND_MESH_EXECUTION_MODEL.md) diff --git a/docs/04-configuration/GRU_C_STAR_V2_STANDARDS_MATRIX_AND_IMPLEMENTATION_PLAN.md b/docs/04-configuration/GRU_C_STAR_V2_STANDARDS_MATRIX_AND_IMPLEMENTATION_PLAN.md index f716fbf5..022ef693 100644 --- a/docs/04-configuration/GRU_C_STAR_V2_STANDARDS_MATRIX_AND_IMPLEMENTATION_PLAN.md +++ b/docs/04-configuration/GRU_C_STAR_V2_STANDARDS_MATRIX_AND_IMPLEMENTATION_PLAN.md @@ -4,7 +4,7 @@ **Audience:** Solidity engineers, protocol architects, bridge operators, GRU governance, explorer / token-aggregation maintainers, and auditors. -**Related:** [naming-conventions/README.md](naming-conventions/README.md) (UTRNF reference + DBIS `c*` vs UTRNF `c` mapping: [naming-conventions/02_DBIS_NAMESPACE_AND_UTRNF_MAPPING.md](naming-conventions/02_DBIS_NAMESPACE_AND_UTRNF_MAPPING.md)), [GRU_STANDARDS_PROFILE.md](GRU_STANDARDS_PROFILE.md), [GRU_STORAGE_GOVERNANCE_AND_SUPERVISION_STANDARD.md](GRU_STORAGE_GOVERNANCE_AND_SUPERVISION_STANDARD.md), [GRU_M00_DIAMOND_INSTITUTIONAL_SPEC.md](GRU_M00_DIAMOND_INSTITUTIONAL_SPEC.md), [GRU_M00_DIAMOND_FACET_MAP.md](GRU_M00_DIAMOND_FACET_MAP.md), [GRU_M00_DIAMOND_REVIEW_GAPS_AND_RECOMMENDATIONS.md](GRU_M00_DIAMOND_REVIEW_GAPS_AND_RECOMMENDATIONS.md), [CHAIN138_X402_TOKEN_SUPPORT.md](CHAIN138_X402_TOKEN_SUPPORT.md), [SMART_CONTRACTS_ISO20022_FIN_METHODOLOGY.md](SMART_CONTRACTS_ISO20022_FIN_METHODOLOGY.md), [GRU_TRANSPORT_ACTIVE_JSON.md](GRU_TRANSPORT_ACTIVE_JSON.md), [EXPLORER_TOKENS_GRU_POLICY.md](EXPLORER_TOKENS_GRU_POLICY.md). +**Related:** [naming-conventions/README.md](naming-conventions/README.md) (UTRNF reference + DBIS `c*` vs UTRNF `c` mapping: [naming-conventions/02_DBIS_NAMESPACE_AND_UTRNF_MAPPING.md](naming-conventions/02_DBIS_NAMESPACE_AND_UTRNF_MAPPING.md)), [GRU_STANDARDS_PROFILE.md](GRU_STANDARDS_PROFILE.md), [GRU_REFERENCE_PRIMACY_AND_MESH_EXECUTION_MODEL.md](GRU_REFERENCE_PRIMACY_AND_MESH_EXECUTION_MODEL.md) (reference FX / GRU vs public PMM mesh — integrated constraint), [GRU_STORAGE_GOVERNANCE_AND_SUPERVISION_STANDARD.md](GRU_STORAGE_GOVERNANCE_AND_SUPERVISION_STANDARD.md), [GRU_M00_DIAMOND_INSTITUTIONAL_SPEC.md](GRU_M00_DIAMOND_INSTITUTIONAL_SPEC.md), [GRU_M00_DIAMOND_FACET_MAP.md](GRU_M00_DIAMOND_FACET_MAP.md), [GRU_M00_DIAMOND_REVIEW_GAPS_AND_RECOMMENDATIONS.md](GRU_M00_DIAMOND_REVIEW_GAPS_AND_RECOMMENDATIONS.md), [CHAIN138_X402_TOKEN_SUPPORT.md](CHAIN138_X402_TOKEN_SUPPORT.md), [SMART_CONTRACTS_ISO20022_FIN_METHODOLOGY.md](SMART_CONTRACTS_ISO20022_FIN_METHODOLOGY.md), [GRU_TRANSPORT_ACTIVE_JSON.md](GRU_TRANSPORT_ACTIVE_JSON.md), [EXPLORER_TOKENS_GRU_POLICY.md](EXPLORER_TOKENS_GRU_POLICY.md). --- @@ -24,6 +24,10 @@ The key design rule is: - **Put flash, vault, and bridge-side complexity around the base token.** - **Put compliance, messaging, reserve, and accounting policy above the base token.** +### 1.1 Reference primacy and public mesh (policy integration) + +Public-chain **cW\*** PMM pools and bots ([cross-chain-pmm-lps](../../cross-chain-pmm-lps/)) are **execution and stabilization capacity** around canonical `c*` and agreed FX references — not a parallel shadow FX market. **GRU, XDR (SDR), and ISO FX** must remain anchored to **institution-grade rate sets and reserve methodology** (OMNL FX / triangulation, attestations, governance). See [GRU_REFERENCE_PRIMACY_AND_MESH_EXECUTION_MODEL.md](GRU_REFERENCE_PRIMACY_AND_MESH_EXECUTION_MODEL.md) for the integrated stack, checklist, and doc map. + --- ## 2. Current Repo Mapping diff --git a/docs/04-configuration/GRU_REFERENCE_PRIMACY_AND_MESH_EXECUTION_MODEL.md b/docs/04-configuration/GRU_REFERENCE_PRIMACY_AND_MESH_EXECUTION_MODEL.md new file mode 100644 index 00000000..2e45e8f3 --- /dev/null +++ b/docs/04-configuration/GRU_REFERENCE_PRIMACY_AND_MESH_EXECUTION_MODEL.md @@ -0,0 +1,65 @@ +# GRU reference primacy and mesh execution model + +**Purpose:** Integrate monetary-policy intent into engineering and operations: **reference markets and GRU policy define truth**; the **public cW\* PMM mesh and soak grid are execution and capacity layers**, not independent FX discovery or shadow-banking surfaces. + +**Audience:** Protocol architects, GRU governance, RTGS/OMNL operators, cross-chain PMM owners, explorer/token-aggregation maintainers, auditors. + +**Status:** Active — treat as a **design constraint** alongside [GRU_C_STAR_V2_STANDARDS_MATRIX_AND_IMPLEMENTATION_PLAN.md](GRU_C_STAR_V2_STANDARDS_MATRIX_AND_IMPLEMENTATION_PLAN.md) and [GRU_STANDARDS_PROFILE.md](GRU_STANDARDS_PROFILE.md). + +--- + +## 1. Non-negotiable rule (tail does not wag dog) + +1. **SDR (IMF XDR)** and **GRU** (reserve / valuation unit in the OMNL model) must **trace to institution-grade references**: published basket methodology, agreed FX rate sets, **XAU triangulation** where the GL/FX model requires it, and reserve attestations — see [mifos-omnl-central-bank/FX_AND_VALUATION.md](mifos-omnl-central-bank/FX_AND_VALUATION.md), [mifos-omnl-central-bank/CURRENCY_AND_UNITS.md](mifos-omnl-central-bank/CURRENCY_AND_UNITS.md). +2. **On-chain PMM prices, DEX midquotes, and bot activity** are **implementation signals** (slippage, inventory, latency). They are **not** the oracle of record for GRU or XDR unless explicitly adopted as a **secondary** feed with governance, staleness bounds, and fallbacks. +3. **Base money (`c*`)** remains **e-money-shaped**: par redeemability, segregated reserves, monitoring hooks — [runbooks/MULTI_CHAIN_EXECUTION_ISO20022_EMONEY.md](../runbooks/MULTI_CHAIN_EXECUTION_ISO20022_EMONEY.md). **Capability and mesh layers** (`cW*`, PMM, flash wrappers) must not redefine base liability semantics. + +--- + +## 2. Three GRU layers + mesh (integrated stack) + +This doc **does not replace** [GRU_C_STAR_V2_STANDARDS_MATRIX_AND_IMPLEMENTATION_PLAN.md](GRU_C_STAR_V2_STANDARDS_MATRIX_AND_IMPLEMENTATION_PLAN.md); it **pins** the public mesh into that stack: + +| GRU layer (c\* V2 matrix) | Role | Mesh / public-chain touchpoint | +|---------------------------|------|--------------------------------| +| **Base money** | Canonical `c*`; payment standards; liability clarity | Chain 138 canonical tokens; registry + explorer policy | +| **Capability** | Bridges, `cW*`, x402, vault/flash wrappers | [cross-chain-pmm-lps](../../cross-chain-pmm-lps/) token map, pool-matrix, deployment-status | +| **Policy / governance** | ReserveGate, ComplianceGate, ISO-20022, accounting | M00 facets, institutional JSON, RTGS runbooks | + +**Mesh execution:** [cross-chain-pmm-lps/README.md](../../cross-chain-pmm-lps/README.md) describes the **bot-managed PMM stabilization mesh**. Under this model, that mesh **implements** corridor behavior **against** policy/reference inputs (`peg-bands.json`, oracles, throttling), rather than inventing FX reality. + +--- + +## 3. Integration map (where this must show up) + +| Surface | Required linkage | +|---------|------------------| +| **OMNL / Fineract FX** | Rate matrix, revaluation, GRU/XDR/XAU units — [FX_AND_VALUATION.md](mifos-omnl-central-bank/FX_AND_VALUATION.md) | +| **RTGS / institutional rails** | Settlement messaging, UETR vs on-chain ids — [03-deployment/OMNL_DBIS_CORE_CHAIN138_SMART_VAULT_RTGS_RUNBOOK.md](../03-deployment/OMNL_DBIS_CORE_CHAIN138_SMART_VAULT_RTGS_RUNBOOK.md), [03-deployment/DBIS_RTGS_FX_AND_LIQUIDITY_OPERATING_MODEL.md](../03-deployment/DBIS_RTGS_FX_AND_LIQUIDITY_OPERATING_MODEL.md) | +| **Phase C edge pools** | Deploy/fund pools **after** reference and transport policy are clear — [03-deployment/PHASE_C_CW_AND_EDGE_POOLS_RUNBOOK.md](../03-deployment/PHASE_C_CW_AND_EDGE_POOLS_RUNBOOK.md) | +| **Public protocol truth** | `deployment-status.json` + verifier — [11-references/GRU_V2_PUBLIC_PROTOCOL_DEPLOYMENT_STATUS.md](../11-references/GRU_V2_PUBLIC_PROTOCOL_DEPLOYMENT_STATUS.md) (links this policy doc), `scripts/verify/check-gru-v2-public-protocols.sh` | +| **PMM / DEX status narrative** | Distinguish Chain 138 venues vs public cW\* mesh — [11-references/PMM_DEX_ROUTING_STATUS.md](../11-references/PMM_DEX_ROUTING_STATUS.md) | +| **Liquidity taxonomy** | Reserve vs public stabilization vs price discovery — [11-references/LIQUIDITY_POOLS_MASTER_MAP.md](../11-references/LIQUIDITY_POOLS_MASTER_MAP.md) | +| **Soak grid (6,534 wallets)** | Operational throughput and segmentation; **not** a substitute for reserve policy — [11-references/CHAIN138_GRID_6534_WALLET_FUNDING_PLAN.md](../11-references/CHAIN138_GRID_6534_WALLET_FUNDING_PLAN.md) | +| **Stress and dominance discipline** | External market baselines for simulation — [gru-m1/GRU_M1_REAL_DATA_DOMINANCE_ADDENDUM.md](../gru-m1/GRU_M1_REAL_DATA_DOMINANCE_ADDENDUM.md) | + +--- + +## 4. Implementation checklist (anti–afterthought) + +Use this when adding bots, oracles, new `cW*` rows, or explorer surfaces: + +1. **Name the reference** for each corridor (fixing, triangulation path, basket rule, or attested reserve parity). +2. **Declare on-chain price role** (execution only vs allowed secondary oracle) and **staleness / divergence** behavior. +3. **Wire policy gates** per [GRU_C_STAR_V2_STANDARDS_MATRIX_AND_IMPLEMENTATION_PLAN.md](GRU_C_STAR_V2_STANDARDS_MATRIX_AND_IMPLEMENTATION_PLAN.md) (ReserveGate / compliance / ISO-20022 routing as applicable). +4. **Update machine-readable status** (`cross-chain-pmm-lps/config/deployment-status.json`, [config/gru-transport-active.json](../../config/gru-transport-active.json)) so public truth tables stay aligned. +5. **Keep the peg-bands policy hook**: `cross-chain-pmm-lps/config/peg-bands.json` must retain **`gruPolicyIntegration`** (`referencePrimacyDoc`, `meshExecutionRole`) so mesh config stays explicitly subordinate to this document. CI enforces it when the submodule is present (`scripts/verify/check-gru-reference-primacy-integration.sh` via `validate-config-files.sh`). +6. **Document edge vs mesh**: edge pools scale access; **mesh + reference** define acceptable executable bounds — consistent with [cross-chain-pmm-lps/docs/02-pool-topology.md](../../cross-chain-pmm-lps/docs/02-pool-topology.md) and Phase C. + +--- + +## Related + +- [GRU_STANDARDS_PROFILE.md](GRU_STANDARDS_PROFILE.md), [`config/gru-standards-profile.json`](../../config/gru-standards-profile.json) +- [SMART_CONTRACTS_ISO20022_FIN_METHODOLOGY.md](SMART_CONTRACTS_ISO20022_FIN_METHODOLOGY.md) +- [reserve-provenance-package README](../../config/reserve-provenance-package/README.md) — attestation discipline diff --git a/docs/04-configuration/README.md b/docs/04-configuration/README.md index 9a9319d5..10dacfd7 100644 --- a/docs/04-configuration/README.md +++ b/docs/04-configuration/README.md @@ -67,6 +67,7 @@ This directory contains setup and configuration guides. **Explorer tokens and GRU:** - **[naming-conventions/README.md](naming-conventions/README.md)** — UTRNF token-role grammar, DBIS `c*` / `cW*` vs UTRNF collision matrix, bridge naming, registry JSON fields (Chain 138 + cross-chain); optional schema + examples validated by `scripts/validation/validate-naming-convention-registry-examples.sh` when `check-jsonschema` is installed. - **[EXPLORER_TOKENS_GRU_POLICY.md](EXPLORER_TOKENS_GRU_POLICY.md)** ⭐⭐ - Policy: all c* tokens on [explorer.d-bis.org/tokens](https://explorer.d-bis.org/tokens) must be registered as GRU; token list and registration steps. +- **[GRU_REFERENCE_PRIMACY_AND_MESH_EXECUTION_MODEL.md](GRU_REFERENCE_PRIMACY_AND_MESH_EXECUTION_MODEL.md)** — Reference-first GRU/XDR vs public PMM mesh; integration map and implementation checklist (not shadow FX). - **[C_TO_CW_MAPPER_MAPPING.md](C_TO_CW_MAPPER_MAPPING.md)** ⭐⭐ - c* → cW* mapping for mapper: symbol mapping and per-chain address mapping in `config/token-mapping-multichain.json`. **DEX and aggregators (Chain 138 tokens and routing):** diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/admin_d-bis_org_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/admin_d-bis_org_https_headers.txt new file mode 100644 index 00000000..ba6e1e6b --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/admin_d-bis_org_https_headers.txt @@ -0,0 +1,17 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:53:49 GMT +content-type: text/html +content-length: 795 +vary: Accept-Encoding +last-modified: Thu, 02 Apr 2026 19:27:04 GMT +etag: "69cec308-31b" +x-frame-options: SAMEORIGIN +x-content-type-options: nosniff +x-xss-protection: 0 +accept-ranges: bytes +alt-svc: h3=":443"; ma=86400 +content-security-policy: upgrade-insecure-requests +strict-transport-security: max-age=63072000; includeSubDomains; preload + + +0.073550 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/admin_sankofa_nexus_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/admin_sankofa_nexus_https_headers.txt new file mode 100644 index 00000000..49de12fd --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/admin_sankofa_nexus_https_headers.txt @@ -0,0 +1,20 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:52:35 GMT +content-type: text/html; charset=utf-8 +content-length: 5259 +vary: Accept-Encoding +x-dns-prefetch-control: on +strict-transport-security: max-age=63072000; includeSubDomains; preload +x-frame-options: SAMEORIGIN +x-content-type-options: nosniff +x-xss-protection: 0 +referrer-policy: strict-origin-when-cross-origin +permissions-policy: camera=(), microphone=(), geolocation=() +content-security-policy: default-src 'self'; script-src 'self' 'unsafe-eval' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' https: +vary: RSC, Next-Router-State-Tree, Next-Router-Prefetch, Accept-Encoding +cache-control: s-maxage=31536000, stale-while-revalidate +etag: "oibim89srm41x" +alt-svc: h3=":443"; ma=86400 + + +0.157411 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/all_e2e_results.json b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/all_e2e_results.json new file mode 100644 index 00000000..0fffb9e0 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/all_e2e_results.json @@ -0,0 +1,1616 @@ +[ + { + "domain": "ws.rpc-fireblocks.d-bis.org", + "domain_type": "rpc-ws", + "timestamp": "2026-04-12T06:52:15-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "ws.rpc-fireblocks.d-bis.org", + "issuer": "E8", + "expires": "May 22 21:48:21 2026 GMT" + }, + "websocket": { + "status": "pass", + "http_code": "400", + "full_test": true, + "full_test_output": "result" + } + } + }, + { + "domain": "dbis-admin.d-bis.org", + "domain_type": "web", + "timestamp": "2026-04-12T06:52:23-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "dbis-admin.d-bis.org", + "issuer": "E7", + "expires": "Jun 15 06:47:43 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.137332, + "has_hsts": true, + "has_csp": true, + "has_xfo": true + } + } + }, + { + "domain": "core.d-bis.org", + "domain_type": "web", + "timestamp": "2026-04-12T06:52:26-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "core.d-bis.org", + "issuer": "E7", + "expires": "Jun 28 18:50:01 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.090176, + "has_hsts": true, + "has_csp": true, + "has_xfo": true + } + } + }, + { + "domain": "rpc-alltra-3.d-bis.org", + "domain_type": "rpc-http", + "timestamp": "2026-04-12T06:52:28-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "172.67.220.49", + "expected_ip": "any" + }, + "ssl": { + "status": "pass", + "cn": "d-bis.org", + "issuer": "WE1", + "expires": "May 27 07:40:56 2026 GMT" + }, + "rpc_http": { + "status": "pass", + "chain_id": "0x8a" + } + } + }, + { + "domain": "mifos.d-bis.org", + "domain_type": "web", + "timestamp": "2026-04-12T06:52:30-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "*", + "issuer": "*", + "expires": "May 19 19:15:03 3025 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.077119, + "has_hsts": false, + "has_csp": false, + "has_xfo": false + } + } + }, + { + "domain": "members.d-bis.org", + "domain_type": "web", + "timestamp": "2026-04-12T06:52:32-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "members.d-bis.org", + "issuer": "E8", + "expires": "Jun 30 17:31:28 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.133922, + "has_hsts": true, + "has_csp": true, + "has_xfo": true + } + } + }, + { + "domain": "admin.sankofa.nexus", + "domain_type": "web", + "timestamp": "2026-04-12T06:52:33-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "admin.sankofa.nexus", + "issuer": "E7", + "expires": "Jun 27 19:39:40 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.157411, + "has_hsts": true, + "has_csp": true, + "has_xfo": true + } + } + }, + { + "domain": "dash.sankofa.nexus", + "domain_type": "web", + "timestamp": "2026-04-12T06:52:36-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "dash.sankofa.nexus", + "issuer": "E8", + "expires": "Jun 30 17:27:00 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.218328, + "has_hsts": true, + "has_csp": true, + "has_xfo": true + } + } + }, + { + "domain": "rpc-hybx-2.d-bis.org", + "domain_type": "rpc-http", + "timestamp": "2026-04-12T06:52:38-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "172.67.220.49", + "expected_ip": "any" + }, + "ssl": { + "status": "pass", + "cn": "d-bis.org", + "issuer": "WE1", + "expires": "May 27 07:40:56 2026 GMT" + }, + "rpc_http": { + "status": "pass", + "chain_id": "0x8a" + } + } + }, + { + "domain": "research.d-bis.org", + "domain_type": "web", + "timestamp": "2026-04-12T06:52:40-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "research.d-bis.org", + "issuer": "E7", + "expires": "Jun 30 17:33:28 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.244462, + "has_hsts": true, + "has_csp": true, + "has_xfo": true + } + } + }, + { + "domain": "policy.d-bis.org", + "domain_type": "web", + "timestamp": "2026-04-12T06:52:42-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "policy.d-bis.org", + "issuer": "E7", + "expires": "Jun 30 17:32:38 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.102009, + "has_hsts": true, + "has_csp": true, + "has_xfo": true + } + } + }, + { + "domain": "portal.sankofa.nexus", + "domain_type": "web", + "timestamp": "2026-04-12T06:52:43-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "portal.sankofa.nexus", + "issuer": "E8", + "expires": "Jun 27 19:40:08 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.093692, + "has_hsts": true, + "has_csp": true, + "has_xfo": true + } + } + }, + { + "domain": "cacti-hybx.d-bis.org", + "domain_type": "web", + "timestamp": "2026-04-12T06:52:45-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "104.21.86.131", + "expected_ip": "any" + }, + "ssl": { + "status": "pass", + "cn": "d-bis.org", + "issuer": "WE1", + "expires": "May 27 07:40:56 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.187927, + "has_hsts": true, + "has_csp": false, + "has_xfo": true + } + } + }, + { + "domain": "developers.d-bis.org", + "domain_type": "web", + "timestamp": "2026-04-12T06:52:47-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "developers.d-bis.org", + "issuer": "E7", + "expires": "Jun 30 17:28:44 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.080972, + "has_hsts": true, + "has_csp": true, + "has_xfo": true + } + } + }, + { + "domain": "sankofa.nexus", + "domain_type": "web", + "timestamp": "2026-04-12T06:52:49-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "sankofa.nexus", + "issuer": "E8", + "expires": "Jun 16 06:48:37 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.116520, + "has_hsts": true, + "has_csp": true, + "has_xfo": true + } + } + }, + { + "domain": "rpc-alltra.d-bis.org", + "domain_type": "rpc-http", + "timestamp": "2026-04-12T06:52:50-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "104.21.86.131", + "expected_ip": "any" + }, + "ssl": { + "status": "pass", + "cn": "d-bis.org", + "issuer": "WE1", + "expires": "May 27 07:40:56 2026 GMT" + }, + "rpc_http": { + "status": "pass", + "chain_id": "0x8a" + } + } + }, + { + "domain": "rpc-http-pub.d-bis.org", + "domain_type": "rpc-http", + "timestamp": "2026-04-12T06:52:51-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "rpc-http-pub.d-bis.org", + "issuer": "E8", + "expires": "Jun 16 06:48:10 2026 GMT" + }, + "rpc_http": { + "status": "pass", + "chain_id": "0x8a" + } + } + }, + { + "domain": "info.defi-oracle.io", + "domain_type": "web", + "timestamp": "2026-04-12T06:52:53-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "104.21.91.43", + "expected_ip": "any" + }, + "ssl": { + "status": "pass", + "cn": "info.defi-oracle.io", + "issuer": "Cloudflare TLS Issuing ECC CA 1", + "expires": "Jul 1 22:38:44 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.202597, + "has_hsts": true, + "has_csp": true, + "has_xfo": true + } + } + }, + { + "domain": "rpc.public-0138.defi-oracle.io", + "domain_type": "rpc-http", + "timestamp": "2026-04-12T06:52:56-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "rpc.public-0138.defi-oracle.io", + "issuer": "E8", + "expires": "Jun 26 16:00:12 2026 GMT" + }, + "rpc_http": { + "status": "pass", + "chain_id": "0x8a" + } + } + }, + { + "domain": "studio.sankofa.nexus", + "domain_type": "web", + "timestamp": "2026-04-12T06:52:57-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "studio.sankofa.nexus", + "issuer": "E7", + "expires": "May 31 10:23:29 2026 GMT" + }, + "https": { + "status": "warn", + "http_code": 502, + "response_time_seconds": 0.059656 + } + } + }, + { + "domain": "www.d-bis.org", + "domain_type": "web", + "timestamp": "2026-04-12T06:52:58-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "www.d-bis.org", + "issuer": "E8", + "expires": "Jun 28 18:50:30 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 301, + "response_time_seconds": 0.052194, + "has_hsts": true, + "has_csp": true, + "has_xfo": true + } + } + }, + { + "domain": "dbis-api.d-bis.org", + "domain_type": "api", + "timestamp": "2026-04-12T06:52:59-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "dbis-api.d-bis.org", + "issuer": "E7", + "expires": "Jun 16 06:47:45 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.104624, + "has_hsts": true, + "has_csp": true, + "has_xfo": true + } + } + }, + { + "domain": "interop.d-bis.org", + "domain_type": "web", + "timestamp": "2026-04-12T06:53:01-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "interop.d-bis.org", + "issuer": "E8", + "expires": "Jun 30 17:30:34 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.073623, + "has_hsts": true, + "has_csp": true, + "has_xfo": true + } + } + }, + { + "domain": "docs.d-bis.org", + "domain_type": "web", + "timestamp": "2026-04-12T06:53:02-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "docs.d-bis.org", + "issuer": "E8", + "expires": "Jun 19 20:22:34 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.662922, + "has_hsts": true, + "has_csp": true, + "has_xfo": true + } + } + }, + { + "domain": "identity.d-bis.org", + "domain_type": "web", + "timestamp": "2026-04-12T06:53:04-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "identity.d-bis.org", + "issuer": "E8", + "expires": "Jun 30 17:30:05 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.125819, + "has_hsts": true, + "has_csp": true, + "has_xfo": true + } + } + }, + { + "domain": "rpc-hybx-3.d-bis.org", + "domain_type": "rpc-http", + "timestamp": "2026-04-12T06:53:06-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "172.67.220.49", + "expected_ip": "any" + }, + "ssl": { + "status": "pass", + "cn": "d-bis.org", + "issuer": "WE1", + "expires": "May 27 07:40:56 2026 GMT" + }, + "rpc_http": { + "status": "pass", + "chain_id": "0x8a" + } + } + }, + { + "domain": "rpc.d-bis.org", + "domain_type": "rpc-http", + "timestamp": "2026-04-12T06:53:07-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "rpc.d-bis.org", + "issuer": "E8", + "expires": "Jun 29 16:01:15 2026 GMT" + }, + "rpc_http": { + "status": "pass", + "chain_id": "0x8a" + } + } + }, + { + "domain": "dapp.d-bis.org", + "domain_type": "web", + "timestamp": "2026-04-12T06:53:08-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "dapp.d-bis.org", + "issuer": "E8", + "expires": "May 22 02:38:20 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.046539, + "has_hsts": false, + "has_csp": true, + "has_xfo": false + } + } + }, + { + "domain": "ops.d-bis.org", + "domain_type": "web", + "timestamp": "2026-04-12T06:53:09-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "ops.d-bis.org", + "issuer": "E8", + "expires": "Jun 30 17:32:17 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.071058, + "has_hsts": true, + "has_csp": true, + "has_xfo": true + } + } + }, + { + "domain": "www.sankofa.nexus", + "domain_type": "web", + "timestamp": "2026-04-12T06:53:10-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "www.sankofa.nexus", + "issuer": "E7", + "expires": "Apr 16 20:59:41 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 301, + "response_time_seconds": 0.065033, + "canonical_redirect": true, + "location_header": "location: https://sankofa.nexus/" + } + } + }, + { + "domain": "www.the-order.sankofa.nexus", + "domain_type": "web", + "timestamp": "2026-04-12T06:53:11-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "www.the-order.sankofa.nexus", + "issuer": "E8", + "expires": "Jun 25 04:52:05 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 301, + "response_time_seconds": 0.138665, + "canonical_redirect": true, + "location_header": "location: https://the-order.sankofa.nexus/" + } + } + }, + { + "domain": "keycloak.sankofa.nexus", + "domain_type": "web", + "timestamp": "2026-04-12T06:53:13-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "keycloak.sankofa.nexus", + "issuer": "E8", + "expires": "Jun 25 04:50:58 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 302, + "response_time_seconds": 0.100692, + "has_hsts": true, + "has_csp": true, + "has_xfo": true + } + } + }, + { + "domain": "mim4u.org", + "domain_type": "web", + "timestamp": "2026-04-12T06:53:14-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "mim4u.org", + "issuer": "E8", + "expires": "Jun 16 06:47:53 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.066202, + "has_hsts": true, + "has_csp": true, + "has_xfo": true + } + } + }, + { + "domain": "data.d-bis.org", + "domain_type": "api", + "timestamp": "2026-04-12T06:53:15-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "data.d-bis.org", + "issuer": "E8", + "expires": "Jun 30 17:27:36 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.077742, + "has_hsts": true, + "has_csp": true, + "has_xfo": true + } + } + }, + { + "domain": "sandbox.d-bis.org", + "domain_type": "web", + "timestamp": "2026-04-12T06:53:17-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "sandbox.d-bis.org", + "issuer": "E8", + "expires": "Jun 30 17:19:17 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.088363, + "has_hsts": true, + "has_csp": true, + "has_xfo": true + } + } + }, + { + "domain": "ws.rpc.d-bis.org", + "domain_type": "rpc-ws", + "timestamp": "2026-04-12T06:53:18-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "ws.rpc.d-bis.org", + "issuer": "E8", + "expires": "Jun 29 16:00:38 2026 GMT" + }, + "websocket": { + "status": "pass", + "http_code": "400", + "full_test": true, + "full_test_output": "result" + } + } + }, + { + "domain": "phoenix.sankofa.nexus", + "domain_type": "web", + "timestamp": "2026-04-12T06:53:26-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "phoenix.sankofa.nexus", + "issuer": "E7", + "expires": "Jun 16 06:47:58 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.086112, + "has_hsts": true, + "has_csp": true, + "has_xfo": true + } + } + }, + { + "domain": "www.mim4u.org", + "domain_type": "web", + "timestamp": "2026-04-12T06:53:27-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "www.mim4u.org", + "issuer": "E8", + "expires": "Jun 15 06:47:54 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.060509, + "has_hsts": true, + "has_csp": true, + "has_xfo": true + } + } + }, + { + "domain": "wss.defi-oracle.io", + "domain_type": "rpc-ws", + "timestamp": "2026-04-12T06:53:29-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "wss.defi-oracle.io", + "issuer": "E8", + "expires": "Jun 29 16:00:55 2026 GMT" + }, + "websocket": { + "status": "pass", + "http_code": "400", + "full_test": true, + "full_test_output": "result" + } + } + }, + { + "domain": "the-order.sankofa.nexus", + "domain_type": "web", + "timestamp": "2026-04-12T06:53:36-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "the-order.sankofa.nexus", + "issuer": "E8", + "expires": "Jun 16 06:48:53 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.122532, + "has_hsts": true, + "has_csp": true, + "has_xfo": true + } + } + }, + { + "domain": "rpc2.d-bis.org", + "domain_type": "rpc-http", + "timestamp": "2026-04-12T06:53:38-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "rpc2.d-bis.org", + "issuer": "E7", + "expires": "Jun 30 16:00:41 2026 GMT" + }, + "rpc_http": { + "status": "pass", + "chain_id": "0x8a" + } + } + }, + { + "domain": "rpc-ws-pub.d-bis.org", + "domain_type": "rpc-ws", + "timestamp": "2026-04-12T06:53:39-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "rpc-ws-pub.d-bis.org", + "issuer": "E7", + "expires": "Jun 16 06:48:27 2026 GMT" + }, + "websocket": { + "status": "pass", + "http_code": "400", + "full_test": true, + "full_test_output": "result" + } + } + }, + { + "domain": "dev.d-bis.org", + "domain_type": "web", + "timestamp": "2026-04-12T06:53:46-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.40", + "expected_ip": "76.53.10.40" + }, + "ssl": { + "status": "pass", + "cn": "subject=", + "issuer": "YE2", + "expires": "Apr 16 19:29:58 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.102886, + "has_hsts": false, + "has_csp": false, + "has_xfo": true + } + } + }, + { + "domain": "admin.d-bis.org", + "domain_type": "web", + "timestamp": "2026-04-12T06:53:48-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "admin.d-bis.org", + "issuer": "E7", + "expires": "Jun 28 18:49:41 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.073550, + "has_hsts": true, + "has_csp": true, + "has_xfo": true + } + } + }, + { + "domain": "status.d-bis.org", + "domain_type": "web", + "timestamp": "2026-04-12T06:53:50-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "status.d-bis.org", + "issuer": "E8", + "expires": "Jun 30 17:16:11 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.080954, + "has_hsts": true, + "has_csp": true, + "has_xfo": true + } + } + }, + { + "domain": "rpc-alltra-2.d-bis.org", + "domain_type": "rpc-http", + "timestamp": "2026-04-12T06:53:51-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "172.67.220.49", + "expected_ip": "any" + }, + "ssl": { + "status": "pass", + "cn": "d-bis.org", + "issuer": "WE1", + "expires": "May 27 07:40:56 2026 GMT" + }, + "rpc_http": { + "status": "pass", + "chain_id": "0x8a" + } + } + }, + { + "domain": "rpc-http-prv.d-bis.org", + "domain_type": "rpc-http", + "timestamp": "2026-04-12T06:53:53-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "rpc-http-prv.d-bis.org", + "issuer": "E7", + "expires": "Jun 25 16:00:12 2026 GMT" + }, + "rpc_http": { + "status": "pass", + "chain_id": "0x8a" + } + } + }, + { + "domain": "www.phoenix.sankofa.nexus", + "domain_type": "web", + "timestamp": "2026-04-12T06:53:54-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "www.phoenix.sankofa.nexus", + "issuer": "E8", + "expires": "Jun 15 06:48:02 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 301, + "response_time_seconds": 0.115175, + "canonical_redirect": true, + "location_header": "location: https://phoenix.sankofa.nexus/health" + } + } + }, + { + "domain": "gitea.d-bis.org", + "domain_type": "web", + "timestamp": "2026-04-12T06:53:57-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.40", + "expected_ip": "76.53.10.40" + }, + "ssl": { + "status": "pass", + "cn": "subject=", + "issuer": "YE2", + "expires": "Apr 16 22:29:59 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.133719, + "has_hsts": false, + "has_csp": false, + "has_xfo": true + } + } + }, + { + "domain": "secure.mim4u.org", + "domain_type": "web", + "timestamp": "2026-04-12T06:53:58-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "secure.mim4u.org", + "issuer": "E8", + "expires": "Jun 16 06:48:46 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.174413, + "has_hsts": true, + "has_csp": true, + "has_xfo": true + } + } + }, + { + "domain": "rpc-fireblocks.d-bis.org", + "domain_type": "rpc-http", + "timestamp": "2026-04-12T06:54:00-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "rpc-fireblocks.d-bis.org", + "issuer": "E8", + "expires": "May 22 21:47:15 2026 GMT" + }, + "rpc_http": { + "status": "pass", + "chain_id": "0x8a" + } + } + }, + { + "domain": "explorer.d-bis.org", + "domain_type": "web", + "timestamp": "2026-04-12T06:54:01-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "explorer.d-bis.org", + "issuer": "E8", + "expires": "Jul 8 03:31:39 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.797344, + "has_hsts": true, + "has_csp": true, + "has_xfo": true + }, + "blockscout_api": { + "status": "pass", + "http_code": 200 + }, + "explorer_command_center": { + "status": "pass", + "http_code": 200 + }, + "mission_control_stream": { + "status": "pass", + "http_code": 200 + }, + "mission_control_trace": { + "status": "pass", + "http_code": 200 + }, + "mission_control_liquidity": { + "status": "pass", + "http_code": 200 + } + } + }, + { + "domain": "training.mim4u.org", + "domain_type": "web", + "timestamp": "2026-04-12T06:54:31-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "training.mim4u.org", + "issuer": "E7", + "expires": "Jun 16 06:49:02 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.078750, + "has_hsts": true, + "has_csp": true, + "has_xfo": true + } + } + }, + { + "domain": "blockscout.defi-oracle.io", + "domain_type": "web", + "timestamp": "2026-04-12T06:54:32-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "blockscout.defi-oracle.io", + "issuer": "E7", + "expires": "Jun 8 13:56:19 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.765541, + "has_hsts": true, + "has_csp": true, + "has_xfo": true + }, + "blockscout_api": { + "status": "pass", + "http_code": 200 + } + } + }, + { + "domain": "dbis-api-2.d-bis.org", + "domain_type": "api", + "timestamp": "2026-04-12T06:54:35-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "dbis-api-2.d-bis.org", + "issuer": "E8", + "expires": "Apr 16 20:56:22 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.182304, + "has_hsts": true, + "has_csp": true, + "has_xfo": true + } + } + }, + { + "domain": "d-bis.org", + "domain_type": "web", + "timestamp": "2026-04-12T06:54:37-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "d-bis.org", + "issuer": "E7", + "expires": "Jun 28 18:50:15 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.142925, + "has_hsts": true, + "has_csp": true, + "has_xfo": true + } + } + }, + { + "domain": "rpc-core.d-bis.org", + "domain_type": "rpc-http", + "timestamp": "2026-04-12T06:54:39-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "rpc-core.d-bis.org", + "issuer": "E8", + "expires": "Jun 30 17:33:58 2026 GMT" + }, + "rpc_http": { + "status": "pass", + "chain_id": "0x8a" + } + } + }, + { + "domain": "secure.d-bis.org", + "domain_type": "web", + "timestamp": "2026-04-12T06:54:41-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "secure.d-bis.org", + "issuer": "E7", + "expires": "Apr 16 20:58:28 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.100453, + "has_hsts": true, + "has_csp": true, + "has_xfo": true + } + } + }, + { + "domain": "rpc-hybx.d-bis.org", + "domain_type": "rpc-http", + "timestamp": "2026-04-12T06:54:42-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "172.67.220.49", + "expected_ip": "any" + }, + "ssl": { + "status": "pass", + "cn": "d-bis.org", + "issuer": "WE1", + "expires": "May 27 07:40:56 2026 GMT" + }, + "rpc_http": { + "status": "pass", + "chain_id": "0x8a" + } + } + }, + { + "domain": "codespaces.d-bis.org", + "domain_type": "web", + "timestamp": "2026-04-12T06:54:44-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.40", + "expected_ip": "76.53.10.40" + }, + "ssl": { + "status": "pass", + "cn": "subject=", + "issuer": "YE2", + "expires": "Apr 16 13:29:58 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.097073, + "has_hsts": false, + "has_csp": false, + "has_xfo": true + } + } + }, + { + "domain": "rpc.defi-oracle.io", + "domain_type": "rpc-http", + "timestamp": "2026-04-12T06:54:45-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "rpc.defi-oracle.io", + "issuer": "E7", + "expires": "Jun 30 18:44:51 2026 GMT" + }, + "rpc_http": { + "status": "pass", + "chain_id": "0x8a" + } + } + }, + { + "domain": "rpc-ws-prv.d-bis.org", + "domain_type": "rpc-ws", + "timestamp": "2026-04-12T06:54:46-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "rpc-ws-prv.d-bis.org", + "issuer": "E7", + "expires": "Jun 16 06:48:19 2026 GMT" + }, + "websocket": { + "status": "pass", + "http_code": "400", + "full_test": true, + "full_test_output": "result" + } + } + }, + { + "domain": "ws.rpc2.d-bis.org", + "domain_type": "rpc-ws", + "timestamp": "2026-04-12T06:54:55-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "76.53.10.36", + "expected_ip": "76.53.10.36" + }, + "ssl": { + "status": "pass", + "cn": "ws.rpc2.d-bis.org", + "issuer": "E8", + "expires": "Jun 28 16:00:21 2026 GMT" + }, + "websocket": { + "status": "pass", + "http_code": "400", + "full_test": true, + "full_test_output": "result" + } + } + }, + { + "domain": "cacti-alltra.d-bis.org", + "domain_type": "web", + "timestamp": "2026-04-12T06:55:02-07:00", + "tests": { + "dns": { + "status": "pass", + "resolved_ip": "172.67.220.49", + "expected_ip": "any" + }, + "ssl": { + "status": "pass", + "cn": "d-bis.org", + "issuer": "WE1", + "expires": "May 27 07:40:56 2026 GMT" + }, + "https": { + "status": "pass", + "http_code": 200, + "response_time_seconds": 0.172515, + "has_hsts": true, + "has_csp": false, + "has_xfo": true + } + } + } +] diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/blockscout_defi-oracle_io_blockscout_api.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/blockscout_defi-oracle_io_blockscout_api.txt new file mode 100644 index 00000000..aa8dcec4 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/blockscout_defi-oracle_io_blockscout_api.txt @@ -0,0 +1 @@ +{"total_blocks":3931243,"total_transactions":54606,"total_addresses":6793,"latest_block":3931242,"average_block_time":2000,"gas_prices":{"average":0.000001},"network_utilization_percentage":0,"transactions_today":6972,"freshness":{"chain_head":{"block_number":3931243,"timestamp":"2026-04-12T13:54:35Z","age_seconds":0,"source":"reported","confidence":"high","provenance":"rpc","completeness":"complete"},"latest_indexed_block":{"block_number":3931242,"timestamp":"2026-04-12T13:54:33Z","age_seconds":2,"source":"reported","confidence":"high","provenance":"explorer_index","completeness":"complete"},"latest_indexed_transaction":{"block_number":3926698,"timestamp":"2026-04-12T11:23:05Z","age_seconds":9090,"hash":"0x36b74570686b3b384b23167a26985c7a83628f8609a7e928525526cdf28e7759","source":"reported","confidence":"high","provenance":"tx_index","completeness":"partial"},"latest_non_empty_block":{"block_number":3926698,"timestamp":"2026-04-12T11:23:05Z","age_seconds":9090,"distance_from_head":4545,"source":"reported","confidence":"high","provenance":"tx_index","completeness":"partial"}},"completeness":{"transactions_feed":"partial","blocks_feed":"complete","gas_metrics":"complete","utilization_metrics":"complete"},"sampling":{"stats_generated_at":"2026-04-12T13:54:35Z","rpc_probe_at":"2026-04-12T13:54:35Z","stats_window_seconds":300}} diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/blockscout_defi-oracle_io_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/blockscout_defi-oracle_io_https_headers.txt new file mode 100644 index 00000000..37582524 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/blockscout_defi-oracle_io_https_headers.txt @@ -0,0 +1,18 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:54:33 GMT +content-type: text/html; charset=utf-8 +content-length: 112221 +vary: Accept-Encoding +etag: "yjac89wqx52ek2" +vary: Accept-Encoding +cache-control: no-store, no-cache, must-revalidate +referrer-policy: strict-origin-when-cross-origin +content-security-policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.jsdelivr.net https://unpkg.com https://cdnjs.cloudflare.com; style-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com; img-src 'self' data: https:; font-src 'self' https://cdnjs.cloudflare.com; connect-src 'self' https://blockscout.defi-oracle.io wss://blockscout.defi-oracle.io https://explorer.d-bis.org wss://explorer.d-bis.org https://rpc-http-pub.d-bis.org wss://rpc-ws-pub.d-bis.org http://192.168.11.221:8545 ws://192.168.11.221:8546; +alt-svc: h3=":443"; ma=86400 +x-xss-protection: 0 +x-content-type-options: nosniff +x-frame-options: SAMEORIGIN +strict-transport-security: max-age=63072000; includeSubDomains; preload + + +0.765541 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/cacti-alltra_d-bis_org_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/cacti-alltra_d-bis_org_https_headers.txt new file mode 100644 index 00000000..0bbb643e --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/cacti-alltra_d-bis_org_https_headers.txt @@ -0,0 +1,20 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:55:04 GMT +content-type: text/html +alt-svc: h3=":443"; ma=86400 +nel: {"report_to":"cf-nel","success_fraction":0.0,"max_age":604800} +report-to: {"group":"cf-nel","max_age":604800,"endpoints":[{"url":"https://a.nel.cloudflare.com/report/v4?s=WOdS1RKIRF7sF6i9m%2F4XO9Nw4lnrLQZS6yqtus4vbWSEkaEa3z1BuJEDizBROmndenZGRrRc2%2BmCv8F3nfk3p8jOrCFbpEaKpC3JUxORE0e4IbaQOrg%2Bwq2EPwyKcwPT4A2lBp6IRNDk"}]} +last-modified: Thu, 02 Apr 2026 19:42:29 GMT +referrer-policy: strict-origin-when-cross-origin +vary: Accept-Encoding +x-content-type-options: nosniff +x-dns-prefetch-control: off +x-frame-options: SAMEORIGIN +x-permitted-cross-domain-policies: none +cf-cache-status: DYNAMIC +strict-transport-security: max-age=31536000; includeSubDomains +server: cloudflare +cf-ray: 9eb2b9fe29b923d1-LAX + + +0.172515 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/cacti-hybx_d-bis_org_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/cacti-hybx_d-bis_org_https_headers.txt new file mode 100644 index 00000000..eea4e2b2 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/cacti-hybx_d-bis_org_https_headers.txt @@ -0,0 +1,20 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:52:46 GMT +content-type: text/html +alt-svc: h3=":443"; ma=86400 +nel: {"report_to":"cf-nel","success_fraction":0.0,"max_age":604800} +report-to: {"group":"cf-nel","max_age":604800,"endpoints":[{"url":"https://a.nel.cloudflare.com/report/v4?s=td3t73bBpDAu6fXd6gQe%2Bi%2B3kcMfb8UCQ5%2BKRk79vPvoshoYjDez%2BBdb2L8s0s%2BPDeL0K8HZ69DKXB1SqAJTaAC9CfK1rVf6Jbk3suwvPBZZVJXjE8JXqA2fctBYhrFa3fEdLeMGPA%3D%3D"}]} +last-modified: Thu, 02 Apr 2026 19:42:29 GMT +referrer-policy: strict-origin-when-cross-origin +vary: Accept-Encoding +x-content-type-options: nosniff +x-dns-prefetch-control: off +x-frame-options: SAMEORIGIN +x-permitted-cross-domain-policies: none +cf-cache-status: DYNAMIC +strict-transport-security: max-age=31536000; includeSubDomains +server: cloudflare +cf-ray: 9eb2b6a55d31792b-LAX + + +0.187927 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/codespaces_d-bis_org_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/codespaces_d-bis_org_https_headers.txt new file mode 100644 index 00000000..9c66440e --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/codespaces_d-bis_org_https_headers.txt @@ -0,0 +1,10 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:54:45 GMT +x-dns-prefetch-control: off +x-content-type-options: nosniff +x-permitted-cross-domain-policies: none +referrer-policy: strict-origin-when-cross-origin +x-frame-options: SAMEORIGIN + + +0.097073 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/core_d-bis_org_https_body.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/core_d-bis_org_https_body.txt new file mode 100644 index 00000000..c98a6e26 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/core_d-bis_org_https_body.txt @@ -0,0 +1 @@ +{"service":"dbis-core-banking-system","status":"healthy","version":"1.0.0","docs":"/api-docs","health":"/health"} \ No newline at end of file diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/core_d-bis_org_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/core_d-bis_org_https_headers.txt new file mode 100644 index 00000000..f6219fed --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/core_d-bis_org_https_headers.txt @@ -0,0 +1,20 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:52:27 GMT +content-type: application/json; charset=utf-8 +content-length: 113 +vary: Accept-Encoding +content-security-policy: default-src 'self';base-uri 'self';font-src 'self' https: data:;form-action 'self';frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests +cross-origin-opener-policy: same-origin +cross-origin-resource-policy: same-origin +origin-agent-cluster: ?1 +referrer-policy: no-referrer +strict-transport-security: max-age=63072000; includeSubDomains; preload +x-content-type-options: nosniff +x-dns-prefetch-control: off +x-download-options: noopen +x-frame-options: SAMEORIGIN +x-permitted-cross-domain-policies: none +x-xss-protection: 0 +x-trace-id: 1516f235e7610f08af0caa7937fa145e +x-span-id: 2d294d36490cb8e2 +x-parent-span-id: diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/d-bis_org_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/d-bis_org_https_headers.txt new file mode 100644 index 00000000..3e6774bf --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/d-bis_org_https_headers.txt @@ -0,0 +1,18 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:54:39 GMT +content-type: text/html; charset=utf-8 +content-length: 22505 +vary: Accept-Encoding +x-frame-options: SAMEORIGIN +x-content-type-options: nosniff +referrer-policy: strict-origin-when-cross-origin +content-security-policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self' +vary: RSC, Next-Router-State-Tree, Next-Router-Prefetch, Accept-Encoding +cache-control: s-maxage=31536000, stale-while-revalidate +etag: "fqzlq2o9ljhd0" +alt-svc: h3=":443"; ma=86400 +x-xss-protection: 0 +strict-transport-security: max-age=63072000; includeSubDomains; preload + + +0.142925 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/dapp_d-bis_org_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/dapp_d-bis_org_https_headers.txt new file mode 100644 index 00000000..ecca65a0 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/dapp_d-bis_org_https_headers.txt @@ -0,0 +1,12 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:53:08 GMT +content-type: text/html +content-length: 470 +vary: Accept-Encoding +last-modified: Sun, 22 Feb 2026 04:25:15 GMT +etag: "699a852b-1d6" +content-security-policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https:; connect-src 'self' https: wss: http://192.168.11.221:8545 ws://192.168.11.221:8546 https://rpc-http-pub.d-bis.org wss://rpc-ws-pub.d-bis.org; frame-src 'self' https:; frame-ancestors 'self'; +accept-ranges: bytes + + +0.046539 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/dash_sankofa_nexus_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/dash_sankofa_nexus_https_headers.txt new file mode 100644 index 00000000..206f8b32 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/dash_sankofa_nexus_https_headers.txt @@ -0,0 +1,20 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:52:37 GMT +content-type: text/html; charset=utf-8 +content-length: 5259 +vary: Accept-Encoding +x-dns-prefetch-control: on +strict-transport-security: max-age=63072000; includeSubDomains; preload +x-frame-options: SAMEORIGIN +x-content-type-options: nosniff +x-xss-protection: 0 +referrer-policy: strict-origin-when-cross-origin +permissions-policy: camera=(), microphone=(), geolocation=() +content-security-policy: default-src 'self'; script-src 'self' 'unsafe-eval' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' https: +vary: RSC, Next-Router-State-Tree, Next-Router-Prefetch, Accept-Encoding +cache-control: s-maxage=31536000, stale-while-revalidate +etag: "oibim89srm41x" +alt-svc: h3=":443"; ma=86400 + + +0.218328 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/data_d-bis_org_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/data_d-bis_org_https_headers.txt new file mode 100644 index 00000000..770d25f3 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/data_d-bis_org_https_headers.txt @@ -0,0 +1,20 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:53:16 GMT +content-type: application/json; charset=utf-8 +content-length: 100 +vary: Accept-Encoding +content-security-policy: default-src 'self';base-uri 'self';font-src 'self' https: data:;form-action 'self';frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests +cross-origin-opener-policy: same-origin +cross-origin-resource-policy: same-origin +origin-agent-cluster: ?1 +referrer-policy: no-referrer +strict-transport-security: max-age=63072000; includeSubDomains; preload +x-content-type-options: nosniff +x-dns-prefetch-control: off +x-download-options: noopen +x-frame-options: SAMEORIGIN +x-permitted-cross-domain-policies: none +x-xss-protection: 0 +x-trace-id: 891d7dfc9213b8828d8543b79546d381 +x-span-id: d02a195b28e76898 +x-parent-span-id: diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/dbis-admin_d-bis_org_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/dbis-admin_d-bis_org_https_headers.txt new file mode 100644 index 00000000..3e0481ba --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/dbis-admin_d-bis_org_https_headers.txt @@ -0,0 +1,18 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:52:25 GMT +content-type: text/html +content-length: 795 +vary: Accept-Encoding +last-modified: Thu, 02 Apr 2026 19:27:04 GMT +etag: "69cec308-31b" +x-frame-options: SAMEORIGIN +x-content-type-options: nosniff +x-xss-protection: 0 +accept-ranges: bytes +alt-svc: h3=":443"; ma=86400 +content-security-policy: upgrade-insecure-requests +strict-transport-security: max-age=63072000; includeSubDomains; preload +referrer-policy: strict-origin-when-cross-origin + + +0.137332 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/dbis-api-2_d-bis_org_https_body.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/dbis-api-2_d-bis_org_https_body.txt new file mode 100644 index 00000000..c98a6e26 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/dbis-api-2_d-bis_org_https_body.txt @@ -0,0 +1 @@ +{"service":"dbis-core-banking-system","status":"healthy","version":"1.0.0","docs":"/api-docs","health":"/health"} \ No newline at end of file diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/dbis-api-2_d-bis_org_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/dbis-api-2_d-bis_org_https_headers.txt new file mode 100644 index 00000000..64efea39 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/dbis-api-2_d-bis_org_https_headers.txt @@ -0,0 +1,20 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:54:37 GMT +content-type: application/json; charset=utf-8 +content-length: 113 +vary: Accept-Encoding +content-security-policy: default-src 'self';base-uri 'self';font-src 'self' https: data:;form-action 'self';frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests +cross-origin-opener-policy: same-origin +cross-origin-resource-policy: same-origin +origin-agent-cluster: ?1 +referrer-policy: no-referrer +strict-transport-security: max-age=63072000; includeSubDomains; preload +x-content-type-options: nosniff +x-dns-prefetch-control: off +x-download-options: noopen +x-frame-options: SAMEORIGIN +x-permitted-cross-domain-policies: none +x-xss-protection: 0 +x-trace-id: 34f1d83ae98d71e6cb39434767adf0b0 +x-span-id: 63cbb37a45435a17 +x-parent-span-id: diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/dbis-api_d-bis_org_https_body.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/dbis-api_d-bis_org_https_body.txt new file mode 100644 index 00000000..c98a6e26 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/dbis-api_d-bis_org_https_body.txt @@ -0,0 +1 @@ +{"service":"dbis-core-banking-system","status":"healthy","version":"1.0.0","docs":"/api-docs","health":"/health"} \ No newline at end of file diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/dbis-api_d-bis_org_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/dbis-api_d-bis_org_https_headers.txt new file mode 100644 index 00000000..ed36c461 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/dbis-api_d-bis_org_https_headers.txt @@ -0,0 +1,20 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:53:00 GMT +content-type: application/json; charset=utf-8 +content-length: 113 +vary: Accept-Encoding +content-security-policy: default-src 'self';base-uri 'self';font-src 'self' https: data:;form-action 'self';frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests +cross-origin-opener-policy: same-origin +cross-origin-resource-policy: same-origin +origin-agent-cluster: ?1 +referrer-policy: no-referrer +strict-transport-security: max-age=63072000; includeSubDomains; preload +x-content-type-options: nosniff +x-dns-prefetch-control: off +x-download-options: noopen +x-frame-options: SAMEORIGIN +x-permitted-cross-domain-policies: none +x-xss-protection: 0 +x-trace-id: 8111b21bac5a939b4d8399b5c8677d28 +x-span-id: 0df48de426498a0b +x-parent-span-id: diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/dev_d-bis_org_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/dev_d-bis_org_https_headers.txt new file mode 100644 index 00000000..64a61b8e --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/dev_d-bis_org_https_headers.txt @@ -0,0 +1,10 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:53:47 GMT +x-dns-prefetch-control: off +x-content-type-options: nosniff +x-permitted-cross-domain-policies: none +referrer-policy: strict-origin-when-cross-origin +x-frame-options: SAMEORIGIN + + +0.102886 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/developers_d-bis_org_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/developers_d-bis_org_https_headers.txt new file mode 100644 index 00000000..9594fb20 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/developers_d-bis_org_https_headers.txt @@ -0,0 +1,18 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:52:48 GMT +content-type: text/html; charset=utf-8 +content-length: 22505 +vary: Accept-Encoding +x-frame-options: SAMEORIGIN +x-content-type-options: nosniff +referrer-policy: strict-origin-when-cross-origin +content-security-policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self' +vary: RSC, Next-Router-State-Tree, Next-Router-Prefetch, Accept-Encoding +cache-control: s-maxage=31536000, stale-while-revalidate +etag: "fqzlq2o9ljhd0" +alt-svc: h3=":443"; ma=86400 +x-xss-protection: 0 +strict-transport-security: max-age=63072000; includeSubDomains; preload + + +0.080972 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/docs_d-bis_org_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/docs_d-bis_org_https_headers.txt new file mode 100644 index 00000000..b71fe7dd --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/docs_d-bis_org_https_headers.txt @@ -0,0 +1,18 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:53:04 GMT +content-type: text/html; charset=utf-8 +content-length: 111771 +vary: Accept-Encoding +etag: "20xkccs7qj2e7k" +vary: Accept-Encoding +cache-control: no-store, no-cache, must-revalidate +referrer-policy: strict-origin-when-cross-origin +content-security-policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.jsdelivr.net https://unpkg.com https://cdnjs.cloudflare.com; style-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com; img-src 'self' data: https:; font-src 'self' https://cdnjs.cloudflare.com; connect-src 'self' https://blockscout.defi-oracle.io wss://blockscout.defi-oracle.io https://explorer.d-bis.org wss://explorer.d-bis.org https://rpc-http-pub.d-bis.org wss://rpc-ws-pub.d-bis.org http://192.168.11.221:8545 ws://192.168.11.221:8546; +alt-svc: h3=":443"; ma=86400 +x-xss-protection: 0 +x-content-type-options: nosniff +x-frame-options: SAMEORIGIN +strict-transport-security: max-age=63072000; includeSubDomains; preload + + +0.662922 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/explorer_d-bis_org_blockscout_api.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/explorer_d-bis_org_blockscout_api.txt new file mode 100644 index 00000000..87586282 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/explorer_d-bis_org_blockscout_api.txt @@ -0,0 +1 @@ +{"total_blocks":3931228,"total_transactions":54606,"total_addresses":6793,"latest_block":3931227,"average_block_time":2000,"gas_prices":{"average":0.000001},"network_utilization_percentage":0,"transactions_today":6972,"freshness":{"chain_head":{"block_number":3931227,"timestamp":"2026-04-12T13:54:03Z","age_seconds":1,"source":"reported","confidence":"high","provenance":"rpc","completeness":"complete"},"latest_indexed_block":{"block_number":3931227,"timestamp":"2026-04-12T13:54:03Z","age_seconds":1,"source":"reported","confidence":"high","provenance":"explorer_index","completeness":"complete"},"latest_indexed_transaction":{"block_number":3926698,"timestamp":"2026-04-12T11:23:05Z","age_seconds":9059,"hash":"0x36b74570686b3b384b23167a26985c7a83628f8609a7e928525526cdf28e7759","source":"reported","confidence":"high","provenance":"tx_index","completeness":"partial"},"latest_non_empty_block":{"block_number":3926698,"timestamp":"2026-04-12T11:23:05Z","age_seconds":9059,"distance_from_head":4529,"source":"reported","confidence":"high","provenance":"tx_index","completeness":"partial"}},"completeness":{"transactions_feed":"partial","blocks_feed":"complete","gas_metrics":"complete","utilization_metrics":"complete"},"sampling":{"stats_generated_at":"2026-04-12T13:54:04Z","rpc_probe_at":"2026-04-12T13:54:03Z","stats_window_seconds":300}} diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/explorer_d-bis_org_command_center_body.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/explorer_d-bis_org_command_center_body.txt new file mode 100644 index 00000000..9f1375cb --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/explorer_d-bis_org_command_center_body.txt @@ -0,0 +1,748 @@ + + + + + + Chain 138 — Visual Command Center + + + + + + +
+

Chain 138 — deployment and liquidity topology

+

Operator-style view of the architecture in docs/02-architecture/SMOM_DBIS_138_FULL_DEPLOYMENT_FLOW_MAP.md. Diagrams are informational only; contract addresses live in explorer config and repo references. The main explorer remains the canonical live operational surface. Deep links: ?tab=mission-control or numeric ?tab=08 (slug per tab).

+
+ +
+ Loading local diagram assets. If the local Mermaid bundle is unavailable, the page will try a trusted CDN fallback automatically. +
+ +
+ If diagram rendering is unavailable, use the main explorer operational surfaces directly: + Operations Hub, + Bridge Monitoring, + Routes, + System, + and Operator. +
+ +
+
+ + + + + + + + + +
+ Back to Operations +
+ + +
+

Hub, leaf endings, CCIP destinations, Alltra, the dedicated Avalanche cW corridor, the public cW mesh, and pending programs. Mainnet cW mint corridors and the optional TRUU rail are summarized under the Ethereum anchor.

+
+flowchart TB + subgraph LEAF_INGRESS["Leaves — access to 138"] + WU[Wallets · MetaMask Snaps · Ledger · Chainlist · SDKs · ethers.js] + OPS[Operators · Foundry scripts · relay · systemd · deploy hooks] + RPCPUB[Public RPC FQDNs · thirdweb mirrors] + FB[Fireblocks Web3 RPC] + end + + subgraph LEAF_EDGE["Leaves — services that index or front 138"] + EXP[Explorer · Blockscout · token-aggregation] + INFO[info.defi-oracle.io] + DAPP[dapp.d-bis.org bridge UI] + DBIS[dbis-api Core hosts] + X402[x402 payment API] + MCP[MCP PMM controller] + end + + subgraph HUB["CHAIN 138 — origin hub"] + C138["Besu EVM · tokens core · DODO PMM V2/V3 · RouterV2 · UniV3 / Balancer / Curve / 1inch pilots · CCIP bridges + router · AlltraAdapter · BridgeVault · ISO channels · mirror reserve vault settlement · Lockbox · Truth / Tron / Solana adapters"] + end + + subgraph CCIP_ETH["Ethereum 1 — CCIP anchor"] + ETH1["WETH9 / WETH10 bridges · CCIPRelayRouter · RelayBridge · Logger · optional trustless stack"] + LEAF_ETH["Leaf — Mainnet native DEX venues · Li.Fi touchpoints on other chains · first-wave cW DODO pools · optional TRUU PMM rail"] + end + + subgraph CCIP_L2["Other live CCIP EVM destinations"] + L2CLU["OP 10 · Base 8453 · Arb 42161 · Polygon 137 · BSC 56 · Avax 43114 · Gnosis 100 · Celo 42220 · Cronos 25"] + LEAF_L2["Leaf — per-chain native DEX · cW token transport · partial edge pools"] + end + + subgraph ALLTRA["ALL Mainnet 651940"] + A651["AlltraAdapter peer · AUSDT · WETH · WALL · HYDX · DEX env placeholders"] + LEAF_651["Leaf — ALL native venues when configured"] + end + + subgraph SPECIAL["Dedicated corridor from 138"] + AVAXCW["138 cUSDT to Avax cWUSDT mint path"] + LEAF_AVAX["Leaf — recipient on 43114"] + end + + subgraph CW_MESH["Public cW GRU mesh"] + CW["Cross-public-EVM token matrix · pool design · Mainnet DODO concentration"] + end + + subgraph PENDING["Pending separate scaffold"] + WEMIX[Wemix 1111 CCIP pending] + XDC[XDC Zero parallel program] + SCAFF[Etherlink Tezos OP L2 design] + PNON[Truth pointer · Tron adapter · Solana partial] + end + + WU --> RPCPUB + RPCPUB --> C138 + WU --> C138 + OPS --> C138 + EXP --> C138 + INFO --> C138 + DAPP --> C138 + DBIS --> C138 + X402 --> C138 + MCP --> C138 + FB --> C138 + + C138 <--> ETH1 + C138 <--> L2CLU + C138 <--> A651 + C138 --> AVAXCW + AVAXCW --> LEAF_AVAX + + ETH1 <--> L2CLU + ETH1 --> LEAF_ETH + L2CLU --> LEAF_L2 + A651 --> LEAF_651 + + CW -.->|pool and peg design| LEAF_ETH + CW -.->|token mesh| L2CLU + + C138 -.-> WEMIX + C138 -.-> XDC + C138 -.-> SCAFF + C138 -.-> PNON +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/explorer_d-bis_org_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/explorer_d-bis_org_https_headers.txt new file mode 100644 index 00000000..bd9001da --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/explorer_d-bis_org_https_headers.txt @@ -0,0 +1,19 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:54:03 GMT +content-type: text/html; charset=utf-8 +content-length: 111925 +vary: Accept-Encoding +etag: "y82jwqcv5g2ebu" +vary: Accept-Encoding +cache-control: no-store, no-cache, must-revalidate +referrer-policy: strict-origin-when-cross-origin +content-security-policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.jsdelivr.net https://unpkg.com https://cdnjs.cloudflare.com; style-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com; img-src 'self' data: https:; font-src 'self' https://cdnjs.cloudflare.com; connect-src 'self' https://blockscout.defi-oracle.io wss://blockscout.defi-oracle.io https://explorer.d-bis.org wss://explorer.d-bis.org https://rpc-http-pub.d-bis.org wss://rpc-ws-pub.d-bis.org http://192.168.11.221:8545 ws://192.168.11.221:8546; +alt-svc: h3=":443"; ma=86400 +x-xss-protection: 0 +x-content-type-options: nosniff +x-frame-options: SAMEORIGIN +strict-transport-security: max-age=63072000; includeSubDomains; preload +referrer-policy: strict-origin-when-cross-origin + + +0.797344 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/explorer_d-bis_org_mission_control_liquidity.json b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/explorer_d-bis_org_mission_control_liquidity.json new file mode 100644 index 00000000..5a92b459 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/explorer_d-bis_org_mission_control_liquidity.json @@ -0,0 +1 @@ +{"pools":[{"address":"0x9e89bae009adf128782e19e8341996c596ac40dc","dex":"dodo","token0":{"address":"0x93e66202a11b1772e55407b32b44e5cd8eda7f22","symbol":"cUSDT","name":"Tether USD (Compliant)","source":"db"},"token1":{"address":"0xf22258f57794cc8e06237084b353ab30fffa640b","symbol":"cUSDC","name":"USD Coin (Compliant)","source":"db"},"reserves":{"token0":"983891197998","token1":"1016108797998"},"tvl":1999999.995996,"volume24h":0,"feeTier":null},{"address":"0x866cb44b59303d8dc5f4f9e3e7a8e8b0bf238d66","dex":"dodo","token0":{"address":"0x93e66202a11b1772e55407b32b44e5cd8eda7f22","symbol":"cUSDT","name":"Tether USD (Compliant)","source":"db"},"token1":{"address":"0x004b63a7b5b0e06f6bb6adb4a5f9f590bf3182d1","symbol":"USDT","name":"Tether USD (Chain 138)","source":"db"},"reserves":{"token0":"999872497998","token1":"1000127497998"},"tvl":1999999.995996,"volume24h":0,"feeTier":null}]} \ No newline at end of file diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/explorer_d-bis_org_mission_control_stream_body.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/explorer_d-bis_org_mission_control_stream_body.txt new file mode 100644 index 00000000..1f212940 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/explorer_d-bis_org_mission_control_stream_body.txt @@ -0,0 +1,10 @@ +: mission-control stream + +event: ping +data: {} + +event: mission-control +data: {"data":{"ccip_relay":{"url_probe":{"body":{"destination":{"chain_id":1,"chain_name":"Ethereum Mainnet","chain_selector":"5009297550715157269","delivery_mode":"router","relay_bridge":"0x2bF74583206A49Be07E0E8A94197C12987AbD7B5","relay_bridge_allowlist":["0x2bf74583206a49be07e0e8a94197c12987abd7b5"],"relay_bridge_default":"0x2bF74583206A49Be07E0E8A94197C12987AbD7B5","relay_router":"0x416564Ab73Ad5710855E98dC7bC7Bff7387285BA"},"last_error":null,"last_relay_attempt":{"at":"2026-04-12T09:02:02.190Z","destination_chain_selector":"5009297550715157269","message_id":"0x007a53665f3d69a6e26e0a5bca121395399833658137efe8922ce4830f4fcb63","target_bridge":"0x2bF74583206A49Be07E0E8A94197C12987AbD7B5","token_count":0},"last_relay_success":{"at":"2026-04-12T09:02:02.188Z","destination_chain_selector":"5009297550715157269","message_id":"0x007a53665f3d69a6e26e0a5bca121395399833658137efe8922ce4830f4fcb63","target_bridge":"0x2bF74583206A49Be07E0E8A94197C12987AbD7B5","tx_hash":"0x29422259e81835f80b72d4ca16fa3256ec25461749363d827a3aa5a94a9c7d8e"},"last_seen_message":{"at":"2026-04-12T09:02:55.312Z","block_number":"0x3bda1a","destination_chain_selector":"5009297550715157269","message_id":"0x007a53665f3d69a6e26e0a5bca121395399833658137efe8922ce4830f4fcb63","sender":"0x152eD3e9912161b76BDFd368D0C84B7C31C10dE7","transaction_hash":"0x020002288e64febf18da555466e54ec8c80d287b57615079f805f45d51a699fd"},"last_source_poll":{"at":"2026-04-12T13:54:00.815Z","from_block":3931190,"logs_fetched":0,"ok":true,"to_block":3931223},"monitoring":{"confirmation_blocks":1,"delivery_enabled":true,"effective_source_poll_interval_ms":5000,"finality_delay_blocks":2,"poll_interval_ms":5000,"replay_window_blocks":32,"shedding":false,"start_block":"2706088"},"ok":true,"queue":{"failed":0,"processed":42,"size":0},"scope":{"destination_bridge_allowlist":["0x2bf74583206a49be07e0e8a94197c12987abd7b5"],"destination_bridge_default":"0x2bF74583206A49Be07E0E8A94197C12987AbD7B5","source_bridge":"0x152eD3e9912161b76BDFd368D0C84B7C31C10dE7"},"service":{"name":"ccip-relay","pid":487580,"profile":"mainnet-cw","relayer_address":"0x4A666F96fC8764181194447A7dFdb7d471b301C8","running":true,"started_at":"2026-04-08T09:54:08.316Z","uptime_sec":359996},"source":{"bridge_address":"0x152ed3e9912161b76bdfd368d0c84b7c31c10de7","bridge_filter":"0x152eD3e9912161b76BDFd368D0C84B7C31C10dE7","chain_id":138,"chain_name":"Chain 138","chain_selector":"138","router_address":"0x42DAb7b888Dd382bD5Adcf9E038dBF1fD03b4817"},"status":"operational"},"ok":true,"status":200}},"ccip_relays":{"avax":{"url_probe":{"body":{"destination":{"chain_id":43114,"chain_name":"Avalanche","chain_selector":"6433500567565415381","delivery_mode":"router","relay_bridge":"0x3f8C409C6072a2B6a4Ff17071927bA70F80c725F","relay_bridge_allowlist":["0x3f8c409c6072a2b6a4ff17071927ba70f80c725f"],"relay_bridge_default":"0x3f8C409C6072a2B6a4Ff17071927bA70F80c725F","relay_router":"0x2a0023Ad5ce1Ac6072B454575996DfFb1BB11b16"},"last_error":null,"last_relay_attempt":null,"last_relay_success":null,"last_seen_message":null,"last_source_poll":{"at":"2026-04-12T13:54:02.981Z","from_block":3931191,"logs_fetched":0,"ok":true,"to_block":3931224},"monitoring":{"confirmation_blocks":1,"delivery_enabled":true,"effective_source_poll_interval_ms":5000,"finality_delay_blocks":2,"poll_interval_ms":5000,"replay_window_blocks":32,"shedding":false,"start_block":"latest"},"ok":true,"queue":{"failed":0,"processed":0,"size":0},"scope":{"destination_bridge_allowlist":["0x3f8c409c6072a2b6a4ff17071927ba70f80c725f"],"destination_bridge_default":"0x3f8C409C6072a2B6a4Ff17071927bA70F80c725F","source_bridge":"0xcacfd227A040002e49e2e01626363071324f820a"},"service":{"name":"ccip-relay","pid":2978621,"profile":"avax","relayer_address":"0x4A666F96fC8764181194447A7dFdb7d471b301C8","running":true,"started_at":"2026-04-11T05:16:09.211Z","uptime_sec":117475},"source":{"bridge_address":"0xcacfd227A040002e49e2e01626363071324f820a","bridge_filter":"0xcacfd227A040002e49e2e01626363071324f820a","chain_id":138,"chain_name":"Chain 138","chain_selector":"138","router_address":"0x42DAb7b888Dd382bD5Adcf9E038dBF1fD03b4817"},"status":"operational"},"ok":true,"status":200}},"avax_cw":{"url_probe":{"body":{"destination":{"chain_id":43114,"chain_name":"Avalanche","chain_selector":"6433500567565415381","delivery_mode":"router","relay_bridge":"0x635002c5fb227160cd2eac926d1baa61847f3c75","relay_bridge_allowlist":["0x635002c5fb227160cd2eac926d1baa61847f3c75"],"relay_bridge_default":"0x635002c5Fb227160Cd2eAC926d1BaA61847f3C75","relay_router":"0xc9158759a7e3621f6bb191bf5d77605d6e25b410"},"last_error":null,"last_relay_attempt":{"at":"2026-04-07T04:28:06.895Z","destination_chain_selector":"6433500567565415381","message_id":"0x8aa12010aece5f29396fbe84ed4f18554661f8a77238895c433367276110dc8f","target_bridge":"0x635002c5Fb227160Cd2eAC926d1BaA61847f3C75","token_count":0},"last_relay_success":null,"last_seen_message":{"at":"2026-04-07T04:28:06.558Z","block_number":"0x340dc9","destination_chain_selector":"6433500567565415381","message_id":"0x8aa12010aece5f29396fbe84ed4f18554661f8a77238895c433367276110dc8f","sender":"0x152eD3e9912161b76BDFd368D0C84B7C31C10dE7","transaction_hash":"0xb6b821d3a04739c0f548fe1e30f4f162392c12a06930757bacdb940dc87f05b5"},"last_source_poll":{"at":"2026-04-12T13:54:02.341Z","from_block":3931191,"logs_fetched":0,"ok":true,"to_block":3931224},"monitoring":{"confirmation_blocks":1,"delivery_enabled":true,"effective_source_poll_interval_ms":5000,"finality_delay_blocks":2,"poll_interval_ms":5000,"replay_window_blocks":32,"shedding":false,"start_block":"3411398"},"ok":true,"queue":{"failed":0,"processed":1,"size":0},"scope":{"destination_bridge_allowlist":["0x635002c5fb227160cd2eac926d1baa61847f3c75"],"destination_bridge_default":"0x635002c5Fb227160Cd2eAC926d1BaA61847f3C75","source_bridge":"0x152eD3e9912161b76BDFd368D0C84B7C31C10dE7"},"service":{"name":"ccip-relay","pid":3051,"profile":"avax-cw","relayer_address":"0x4A666F96fC8764181194447A7dFdb7d471b301C8","running":true,"started_at":"2026-04-07T04:26:48.652Z","uptime_sec":466036},"source":{"bridge_address":"0x152ed3e9912161b76bdfd368d0c84b7c31c10de7","bridge_filter":"0x152eD3e9912161b76BDFd368D0C84B7C31C10dE7","chain_id":138,"chain_name":"Chain 138","chain_selector":"138","router_address":"0x42dab7b888dd382bd5adcf9e038dbf1fd03b4817"},"status":"operational"},"ok":true,"status":200}},"avax_to_138":{"url_probe":{"body":{"destination":{"chain_id":138,"chain_name":"Chain 138","chain_selector":"138","delivery_mode":"router","relay_bridge":"0x152ed3e9912161b76bdfd368d0c84b7c31c10de7","relay_bridge_allowlist":["0x152ed3e9912161b76bdfd368d0c84b7c31c10de7"],"relay_bridge_default":"0x152eD3e9912161b76BDFd368D0C84B7C31C10dE7","relay_router":"0xe75d26bc558a28442f30750c6d97bffb46f39abc"},"last_error":null,"last_relay_attempt":null,"last_relay_success":null,"last_seen_message":null,"last_source_poll":{"at":"2026-04-12T13:54:01.170Z","from_block":82757846,"logs_fetched":0,"ok":true,"to_block":82757883},"monitoring":{"confirmation_blocks":1,"delivery_enabled":true,"effective_source_poll_interval_ms":5000,"finality_delay_blocks":2,"poll_interval_ms":5000,"replay_window_blocks":32,"shedding":false,"start_block":"latest"},"ok":true,"queue":{"failed":0,"processed":0,"size":0},"scope":{"destination_bridge_allowlist":["0x152ed3e9912161b76bdfd368d0c84b7c31c10de7"],"destination_bridge_default":"0x152eD3e9912161b76BDFd368D0C84B7C31C10dE7","source_bridge":"0x635002c5Fb227160Cd2eAC926d1BaA61847f3C75"},"service":{"name":"ccip-relay","pid":2978619,"profile":"avax-to-138","relayer_address":"0x4A666F96fC8764181194447A7dFdb7d471b301C8","running":true,"started_at":"2026-04-11T05:16:09.004Z","uptime_sec":117476},"source":{"bridge_address":"0x635002c5fb227160cd2eac926d1baa61847f3c75","bridge_filter":"0x635002c5Fb227160Cd2eAC926d1BaA61847f3C75","chain_id":43114,"chain_name":"Avalanche","chain_selector":"6433500567565415381","router_address":"0x1773125b280d296354f4f4b958a7cfc4e5975b60"},"status":"operational"},"ok":true,"status":200}},"bsc":{"url_probe":{"body":{"destination":{"chain_id":56,"chain_name":"BSC","chain_selector":"11344663589394136015","delivery_mode":"router","relay_bridge":"0x886C6A4ABC064dbf74E7caEc460b7eeC31F1b78C","relay_bridge_allowlist":["0x886c6a4abc064dbf74e7caec460b7eec31f1b78c"],"relay_bridge_default":"0x886C6A4ABC064dbf74E7caEc460b7eeC31F1b78C","relay_router":"0x4d9Bc6c74ba65E37c4139F0aEC9fc5Ddff28Dcc4"},"last_error":null,"last_relay_attempt":null,"last_relay_success":null,"last_seen_message":null,"last_source_poll":{"at":"2026-04-12T13:54:03.472Z","from_block":3931191,"logs_fetched":0,"ok":true,"to_block":3931225},"monitoring":{"confirmation_blocks":1,"delivery_enabled":true,"effective_source_poll_interval_ms":5000,"finality_delay_blocks":2,"poll_interval_ms":5000,"replay_window_blocks":32,"shedding":false,"start_block":"latest"},"ok":true,"queue":{"failed":0,"processed":0,"size":0},"scope":{"destination_bridge_allowlist":["0x886c6a4abc064dbf74e7caec460b7eec31f1b78c"],"destination_bridge_default":"0x886C6A4ABC064dbf74E7caEc460b7eeC31F1b78C","source_bridge":"0xcacfd227A040002e49e2e01626363071324f820a"},"service":{"name":"ccip-relay","pid":2978685,"profile":"bsc","relayer_address":"0x4A666F96fC8764181194447A7dFdb7d471b301C8","running":true,"started_at":"2026-04-11T05:16:10.262Z","uptime_sec":117474},"source":{"bridge_address":"0xcacfd227A040002e49e2e01626363071324f820a","bridge_filter":"0xcacfd227A040002e49e2e01626363071324f820a","chain_id":138,"chain_name":"Chain 138","chain_selector":"138","router_address":"0x42DAb7b888Dd382bD5Adcf9E038dBF1fD03b4817"},"status":"operational"},"ok":true,"status":200}},"mainnet_cw":{"url_probe":{"body":{"destination":{"chain_id":1,"chain_name":"Ethereum Mainnet","chain_selector":"5009297550715157269","delivery_mode":"router","relay_bridge":"0x2bF74583206A49Be07E0E8A94197C12987AbD7B5","relay_bridge_allowlist":["0x2bf74583206a49be07e0e8a94197c12987abd7b5"],"relay_bridge_default":"0x2bF74583206A49Be07E0E8A94197C12987AbD7B5","relay_router":"0x416564Ab73Ad5710855E98dC7bC7Bff7387285BA"},"last_error":null,"last_relay_attempt":{"at":"2026-04-12T09:02:02.190Z","destination_chain_selector":"5009297550715157269","message_id":"0x007a53665f3d69a6e26e0a5bca121395399833658137efe8922ce4830f4fcb63","target_bridge":"0x2bF74583206A49Be07E0E8A94197C12987AbD7B5","token_count":0},"last_relay_success":{"at":"2026-04-12T09:02:02.188Z","destination_chain_selector":"5009297550715157269","message_id":"0x007a53665f3d69a6e26e0a5bca121395399833658137efe8922ce4830f4fcb63","target_bridge":"0x2bF74583206A49Be07E0E8A94197C12987AbD7B5","tx_hash":"0x29422259e81835f80b72d4ca16fa3256ec25461749363d827a3aa5a94a9c7d8e"},"last_seen_message":{"at":"2026-04-12T09:02:55.312Z","block_number":"0x3bda1a","destination_chain_selector":"5009297550715157269","message_id":"0x007a53665f3d69a6e26e0a5bca121395399833658137efe8922ce4830f4fcb63","sender":"0x152eD3e9912161b76BDFd368D0C84B7C31C10dE7","transaction_hash":"0x020002288e64febf18da555466e54ec8c80d287b57615079f805f45d51a699fd"},"last_source_poll":{"at":"2026-04-12T13:54:00.815Z","from_block":3931190,"logs_fetched":0,"ok":true,"to_block":3931223},"monitoring":{"confirmation_blocks":1,"delivery_enabled":true,"effective_source_poll_interval_ms":5000,"finality_delay_blocks":2,"poll_interval_ms":5000,"replay_window_blocks":32,"shedding":false,"start_block":"2706088"},"ok":true,"queue":{"failed":0,"processed":42,"size":0},"scope":{"destination_bridge_allowlist":["0x2bf74583206a49be07e0e8a94197c12987abd7b5"],"destination_bridge_default":"0x2bF74583206A49Be07E0E8A94197C12987AbD7B5","source_bridge":"0x152eD3e9912161b76BDFd368D0C84B7C31C10dE7"},"service":{"name":"ccip-relay","pid":487580,"profile":"mainnet-cw","relayer_address":"0x4A666F96fC8764181194447A7dFdb7d471b301C8","running":true,"started_at":"2026-04-08T09:54:08.316Z","uptime_sec":359996},"source":{"bridge_address":"0x152ed3e9912161b76bdfd368d0c84b7c31c10de7","bridge_filter":"0x152eD3e9912161b76BDFd368D0C84B7C31C10dE7","chain_id":138,"chain_name":"Chain 138","chain_selector":"138","router_address":"0x42DAb7b888Dd382bD5Adcf9E038dBF1fD03b4817"},"status":"operational"},"ok":true,"status":200}},"mainnet_weth":{"url_probe":{"body":{"destination":{"chain_id":1,"chain_name":"Ethereum Mainnet","chain_selector":"5009297550715157269","delivery_mode":"router","relay_bridge":"0xF9A32F37099c582D28b4dE7Fca6eaC1e5259f939","relay_bridge_allowlist":["0xf9a32f37099c582d28b4de7fca6eac1e5259f939"],"relay_bridge_default":"0xF9A32F37099c582D28b4dE7Fca6eaC1e5259f939","relay_router":"0x416564Ab73Ad5710855E98dC7bC7Bff7387285BA"},"last_error":null,"last_relay_attempt":{"at":"2026-04-12T13:54:03.249Z","destination_chain_selector":"5009297550715157269","message_id":"0x3ab53a9e78c4cc00e3efd8a8c92518356a35f144e79f22d53b44c8a5a4dca777","target_bridge":"0xF9A32F37099c582D28b4dE7Fca6eaC1e5259f939","token_count":1},"last_relay_success":{"at":"2026-04-12T13:54:03.239Z","destination_chain_selector":"5009297550715157269","message_id":"0x80dc3aafa88e5702516c1af5bb4d30e0435892117dd94a1bef2dd65761229682","target_bridge":"0xF9A32F37099c582D28b4dE7Fca6eaC1e5259f939","tx_hash":"0x7d2c423443a033d4d3a58b0eac781a4b1a0c462e0056f5b80efc69f217347a21"},"last_seen_message":{"at":"2026-04-12T13:53:43.244Z","block_number":"0x3beaaa","destination_chain_selector":"5009297550715157269","message_id":"0xf5f7a4407bac6890b3085b11e70d2054300ec28572fcf618da0c2b294fa2b1ce","sender":"0xcacfd227A040002e49e2e01626363071324f820a","transaction_hash":"0x36b74570686b3b384b23167a26985c7a83628f8609a7e928525526cdf28e7759"},"last_source_poll":{"at":"2026-04-12T13:54:03.612Z","from_block":3931191,"logs_fetched":0,"ok":true,"to_block":3931225},"monitoring":{"confirmation_blocks":1,"delivery_enabled":true,"effective_source_poll_interval_ms":5000,"finality_delay_blocks":2,"poll_interval_ms":5000,"replay_window_blocks":32,"shedding":false,"start_block":"2706088"},"ok":true,"queue":{"failed":0,"processed":2,"size":4},"scope":{"destination_bridge_allowlist":["0xf9a32f37099c582d28b4de7fca6eac1e5259f939"],"destination_bridge_default":"0xF9A32F37099c582D28b4dE7Fca6eaC1e5259f939","source_bridge":"0xcacfd227A040002e49e2e01626363071324f820a"},"service":{"name":"ccip-relay","pid":3634796,"profile":"mainnet-weth","relayer_address":"0x4A666F96fC8764181194447A7dFdb7d471b301C8","running":true,"started_at":"2026-04-12T13:53:37.256Z","uptime_sec":27},"source":{"bridge_address":"0xcacfd227A040002e49e2e01626363071324f820a","bridge_filter":"0xcacfd227A040002e49e2e01626363071324f820a","chain_id":138,"chain_name":"Chain 138","chain_selector":"138","router_address":"0x42DAb7b888Dd382bD5Adcf9E038dBF1fD03b4817"},"status":"operational"},"ok":true,"status":200}}},"chains":{"138":{"block_number":"3931227","endpoint":"https://rpc-http-pub.d-bis.org","head_age_sec":2.015021919,"last_sync":"2026-04-12T13:54:05Z","latency_ms":4,"name":"Defi Oracle Meta Mainnet","probe_error":"","status":"operational"}},"checked_at":"2026-04-12T13:54:05Z","freshness":{"chain_head":{"block_number":3931227,"timestamp":"2026-04-12T13:54:03Z","age_seconds":2,"source":"reported","confidence":"high","provenance":"rpc","completeness":"complete"},"latest_indexed_block":{"block_number":3931227,"timestamp":"2026-04-12T13:54:03Z","age_seconds":2,"source":"reported","confidence":"high","provenance":"explorer_index","completeness":"complete"},"latest_indexed_transaction":{"block_number":3926698,"timestamp":"2026-04-12T11:23:05Z","age_seconds":9060,"hash":"0x36b74570686b3b384b23167a26985c7a83628f8609a7e928525526cdf28e7759","source":"reported","confidence":"high","provenance":"tx_index","completeness":"partial"},"latest_non_empty_block":{"block_number":3926698,"timestamp":"2026-04-12T11:23:05Z","age_seconds":9060,"distance_from_head":4529,"source":"reported","confidence":"high","provenance":"tx_index","completeness":"partial"}},"mode":{"age_seconds":0,"confidence":"high","kind":"snapshot","provenance":"mission_control_feed","reason":"live_homepage_stream_not_attached","scope":"relay_monitoring_homepage_card_only","source":"reported","updated_at":"2026-04-12T13:54:05Z"},"rpc_probe":[{"blockNumber":"0x3bfc5b","blockNumberDec":"3931227","chainKey":"138","endpoint":"https://rpc-http-pub.d-bis.org","error":"","headAgeSeconds":2.015021919,"latencyMs":4,"name":"chain-138","ok":true}],"sampling":{"stats_generated_at":"2026-04-12T13:54:05Z","rpc_probe_at":"2026-04-12T13:54:03Z","stats_window_seconds":300},"status":"operational","subsystems":{"bridge_relay_monitoring":{"age_seconds":0,"completeness":"complete","confidence":"high","provenance":"mission_control_feed","source":"reported","status":"operational","updated_at":"2026-04-12T13:54:05Z"},"rpc_head":{"age_seconds":2,"completeness":"complete","confidence":"high","provenance":"rpc","source":"reported","status":"operational","updated_at":"2026-04-12T13:54:03Z"},"stats_summary":{"age_seconds":0,"completeness":"complete","confidence":"medium","provenance":"composite","source":"reported","status":"operational","updated_at":"2026-04-12T13:54:05Z"},"tx_index":{"age_seconds":9060,"completeness":"partial","confidence":"high","provenance":"tx_index","source":"reported","status":"partial","updated_at":"2026-04-12T11:23:05Z"}}}} + +event: mission-control +data: {"data":{"ccip_relay":{"url_probe":{"body":{"destination":{"chain_id":1,"chain_name":"Ethereum Mainnet","chain_selector":"5009297550715157269","delivery_mode":"router","relay_bridge":"0x2bF74583206A49Be07E0E8A94197C12987AbD7B5","relay_bridge_allowlist":["0x2bf74583206a49be07e0e8a94197c12987abd7b5"],"relay_bridge_default":"0x2bF74583206A49Be07E0E8A94197C12987AbD7B5","relay_router":"0x416564Ab73Ad5710855E98dC7bC7Bff7387285BA"},"last_error":null,"last_relay_attempt":{"at":"2026-04-12T09:02:02.190Z","destination_chain_selector":"5009297550715157269","message_id":"0x007a53665f3d69a6e26e0a5bca121395399833658137efe8922ce4830f4fcb63","target_bridge":"0x2bF74583206A49Be07E0E8A94197C12987AbD7B5","token_count":0},"last_relay_success":{"at":"2026-04-12T09:02:02.188Z","destination_chain_selector":"5009297550715157269","message_id":"0x007a53665f3d69a6e26e0a5bca121395399833658137efe8922ce4830f4fcb63","target_bridge":"0x2bF74583206A49Be07E0E8A94197C12987AbD7B5","tx_hash":"0x29422259e81835f80b72d4ca16fa3256ec25461749363d827a3aa5a94a9c7d8e"},"last_seen_message":{"at":"2026-04-12T09:02:55.312Z","block_number":"0x3bda1a","destination_chain_selector":"5009297550715157269","message_id":"0x007a53665f3d69a6e26e0a5bca121395399833658137efe8922ce4830f4fcb63","sender":"0x152eD3e9912161b76BDFd368D0C84B7C31C10dE7","transaction_hash":"0x020002288e64febf18da555466e54ec8c80d287b57615079f805f45d51a699fd"},"last_source_poll":{"at":"2026-04-12T13:54:21.227Z","from_block":3931200,"logs_fetched":0,"ok":true,"to_block":3931234},"monitoring":{"confirmation_blocks":1,"delivery_enabled":true,"effective_source_poll_interval_ms":5000,"finality_delay_blocks":2,"poll_interval_ms":5000,"replay_window_blocks":32,"shedding":false,"start_block":"2706088"},"ok":true,"queue":{"failed":0,"processed":42,"size":0},"scope":{"destination_bridge_allowlist":["0x2bf74583206a49be07e0e8a94197c12987abd7b \ No newline at end of file diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/explorer_d-bis_org_mission_control_stream_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/explorer_d-bis_org_mission_control_stream_headers.txt new file mode 100644 index 00000000..206bcbcb --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/explorer_d-bis_org_mission_control_stream_headers.txt @@ -0,0 +1,22 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:54:05 GMT +content-type: text/event-stream +access-control-allow-headers: Authorization, Content-Type, X-API-Key +access-control-allow-methods: GET, POST, OPTIONS +access-control-allow-origin: * +cache-control: no-cache +content-security-policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.jsdelivr.net https://unpkg.com https://cdnjs.cloudflare.com; style-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com; font-src 'self' https://cdnjs.cloudflare.com; img-src 'self' data: https:; connect-src 'self' https://blockscout.defi-oracle.io https://explorer.d-bis.org https://rpc-http-pub.d-bis.org wss://rpc-ws-pub.d-bis.org http://192.168.11.221:8545 ws://192.168.11.221:8546; +permissions-policy: geolocation=(), microphone=(), camera=() +referrer-policy: strict-origin-when-cross-origin +strict-transport-security: max-age=63072000; includeSubDomains; preload +x-content-type-options: nosniff +x-explorer-name: SolaceScan +x-explorer-version: 1.0.0 +x-frame-options: SAMEORIGIN +x-xss-protection: 0 +access-control-allow-origin: * +access-control-allow-methods: GET, POST, OPTIONS +access-control-allow-headers: Content-Type, Authorization +alt-svc: h3=":443"; ma=86400 +referrer-policy: strict-origin-when-cross-origin + diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/explorer_d-bis_org_mission_control_trace.json b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/explorer_d-bis_org_mission_control_trace.json new file mode 100644 index 00000000..d6289553 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/explorer_d-bis_org_mission_control_trace.json @@ -0,0 +1 @@ +{"data":{"blockscout_url":"https://explorer.d-bis.org/tx/0x2f31d4f9a97be754b800f4af1a9eedf3b107d353bfa1a19e81417497a76c05c2","from":"0x4a666f96fc8764181194447a7dfdb7d471b301c8","from_registry":"DEPLOYER_ADMIN_138","source":"blockscout","to":"0x152ed3e9912161b76bdfd368d0c84b7c31c10de7","to_registry":"CW_L1_BRIDGE_CHAIN138","tx_hash":"0x2f31d4f9a97be754b800f4af1a9eedf3b107d353bfa1a19e81417497a76c05c2"}} diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/gitea_d-bis_org_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/gitea_d-bis_org_https_headers.txt new file mode 100644 index 00000000..4f795bfe --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/gitea_d-bis_org_https_headers.txt @@ -0,0 +1,10 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:53:58 GMT +x-dns-prefetch-control: off +x-content-type-options: nosniff +x-permitted-cross-domain-policies: none +referrer-policy: strict-origin-when-cross-origin +x-frame-options: SAMEORIGIN + + +0.133719 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/identity_d-bis_org_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/identity_d-bis_org_https_headers.txt new file mode 100644 index 00000000..ee22c4e3 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/identity_d-bis_org_https_headers.txt @@ -0,0 +1,18 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:53:05 GMT +content-type: text/html; charset=utf-8 +content-length: 22505 +vary: Accept-Encoding +x-frame-options: SAMEORIGIN +x-content-type-options: nosniff +referrer-policy: strict-origin-when-cross-origin +content-security-policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self' +vary: RSC, Next-Router-State-Tree, Next-Router-Prefetch, Accept-Encoding +cache-control: s-maxage=31536000, stale-while-revalidate +etag: "fqzlq2o9ljhd0" +alt-svc: h3=":443"; ma=86400 +x-xss-protection: 0 +strict-transport-security: max-age=63072000; includeSubDomains; preload + + +0.125819 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/info_defi-oracle_io_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/info_defi-oracle_io_https_headers.txt new file mode 100644 index 00000000..d3e3600b --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/info_defi-oracle_io_https_headers.txt @@ -0,0 +1,19 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:52:55 GMT +content-type: text/html +vary: Accept-Encoding +last-modified: Sun, 05 Apr 2026 23:21:29 GMT +report-to: {"group":"cf-nel","max_age":604800,"endpoints":[{"url":"https://a.nel.cloudflare.com/report/v4?s=t1GChXKNyx8%2F4A3x1KGUZ%2FtD7GHCO0T8KWson2zuNPsMmPmQXDt12sJ1EyfxRDaHlNf4Z%2Ft2fD1lX4wP%2Btgvoc1H0sOKlyapwFFITT2kUBUBtTYVuLtJSt5pshunelTpkFBTKDIR"}]} +alt-svc: h3=":443"; ma=86400 +x-xss-protection: 0 +x-content-type-options: nosniff +x-frame-options: SAMEORIGIN +content-security-policy: upgrade-insecure-requests +strict-transport-security: max-age=63072000; includeSubDomains; preload +nel: {"report_to":"cf-nel","success_fraction":0.0,"max_age":604800} +cf-cache-status: DYNAMIC +server: cloudflare +cf-ray: 9eb2b6d9ac57489a-LAX + + +0.202597 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/info_defi_oracle_io_token_aggregation_networks.json b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/info_defi_oracle_io_token_aggregation_networks.json new file mode 100644 index 00000000..dc177aba --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/info_defi_oracle_io_token_aggregation_networks.json @@ -0,0 +1 @@ +{"source":"built-in","version":"1.0.0","networks":[{"chainId":"0x8a","chainIdDecimal":138,"chainName":"DeFi Oracle Meta Mainnet","rpcUrls":["https://rpc-http-pub.d-bis.org","https://rpc.d-bis.org","https://rpc2.d-bis.org","https://rpc.defi-oracle.io"],"nativeCurrency":{"name":"Ether","symbol":"ETH","decimals":18},"blockExplorerUrls":["https://explorer.d-bis.org"],"iconUrls":["https://explorer.d-bis.org/favicon.ico","https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"],"oracles":[{"name":"ETH/USD","address":"0x3304b747e565a97ec8ac220b0b6a1f6ffdb837e6","decimals":8}]},{"chainId":"0x1","chainIdDecimal":1,"chainName":"Ethereum Mainnet","rpcUrls":["https://eth.llamarpc.com","https://rpc.ankr.com/eth","https://ethereum.publicnode.com","https://1rpc.io/eth"],"nativeCurrency":{"name":"Ether","symbol":"ETH","decimals":18},"blockExplorerUrls":["https://etherscan.io"],"iconUrls":["https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"],"oracles":[{"name":"ETH/USD","address":"0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419","decimals":8}]},{"chainId":"0x9f2c4","chainIdDecimal":651940,"chainName":"ALL Mainnet","rpcUrls":["https://mainnet-rpc.alltra.global"],"nativeCurrency":{"name":"Ether","symbol":"ETH","decimals":18},"blockExplorerUrls":["https://alltra.global"],"iconUrls":["https://alltra.global/favicon.ico","https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"],"oracles":[]},{"chainId":"0x38","chainIdDecimal":56,"chainName":"BNB Smart Chain","rpcUrls":["https://bsc-dataseed.binance.org","https://bsc-dataseed1.defibit.io"],"nativeCurrency":{"name":"BNB","symbol":"BNB","decimals":18},"blockExplorerUrls":["https://bscscan.com"],"iconUrls":["https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/smartchain/info/logo.png"],"oracles":[]},{"chainId":"0x89","chainIdDecimal":137,"chainName":"Polygon","rpcUrls":["https://polygon-rpc.com","https://rpc.ankr.com/polygon"],"nativeCurrency":{"name":"MATIC","symbol":"MATIC","decimals":18},"blockExplorerUrls":["https://polygonscan.com"],"iconUrls":["https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/polygon/info/logo.png"],"oracles":[]},{"chainId":"0x64","chainIdDecimal":100,"chainName":"Gnosis Chain","rpcUrls":["https://rpc.gnosischain.com","https://rpc.ankr.com/gnosis"],"nativeCurrency":{"name":"xDAI","symbol":"xDAI","decimals":18},"blockExplorerUrls":["https://gnosisscan.io"],"iconUrls":["https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/xdai/info/logo.png"],"oracles":[]},{"chainId":"0xa","chainIdDecimal":10,"chainName":"Optimism","rpcUrls":["https://mainnet.optimism.io","https://optimism.llamarpc.com"],"nativeCurrency":{"name":"Ether","symbol":"ETH","decimals":18},"blockExplorerUrls":["https://optimistic.etherscan.io"],"iconUrls":["https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/optimism/info/logo.png"],"oracles":[]},{"chainId":"0xa4b1","chainIdDecimal":42161,"chainName":"Arbitrum One","rpcUrls":["https://arb1.arbitrum.io/rpc","https://arbitrum.llamarpc.com"],"nativeCurrency":{"name":"Ether","symbol":"ETH","decimals":18},"blockExplorerUrls":["https://arbiscan.io"],"iconUrls":["https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/arbitrum/info/logo.png"],"oracles":[]},{"chainId":"0x2105","chainIdDecimal":8453,"chainName":"Base","rpcUrls":["https://mainnet.base.org","https://base.llamarpc.com"],"nativeCurrency":{"name":"Ether","symbol":"ETH","decimals":18},"blockExplorerUrls":["https://basescan.org"],"iconUrls":["https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/base/info/logo.png"],"oracles":[]},{"chainId":"0xa86a","chainIdDecimal":43114,"chainName":"Avalanche C-Chain","rpcUrls":["https://api.avax.network/ext/bc/C/rpc","https://avalanche-c-chain-rpc.publicnode.com"],"nativeCurrency":{"name":"AVAX","symbol":"AVAX","decimals":18},"blockExplorerUrls":["https://snowtrace.io"],"iconUrls":["https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/avalanchec/info/logo.png"],"oracles":[]},{"chainId":"0x19","chainIdDecimal":25,"chainName":"Cronos","rpcUrls":["https://evm.cronos.org","https://cronos-rpc.publicnode.com"],"nativeCurrency":{"name":"CRO","symbol":"CRO","decimals":18},"blockExplorerUrls":["https://cronoscan.com"],"iconUrls":["https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/cronos/info/logo.png"],"oracles":[]},{"chainId":"0xa4ec","chainIdDecimal":42220,"chainName":"Celo","rpcUrls":["https://forno.celo.org","https://celo-rpc.publicnode.com"],"nativeCurrency":{"name":"CELO","symbol":"CELO","decimals":18},"blockExplorerUrls":["https://celoscan.io"],"iconUrls":["https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/celo/info/logo.png"],"oracles":[]},{"chainId":"0x457","chainIdDecimal":1111,"chainName":"Wemix","rpcUrls":["https://api.wemix.com","https://wemix-rpc.publicnode.com"],"nativeCurrency":{"name":"WEMIX","symbol":"WEMIX","decimals":18},"blockExplorerUrls":["https://scan.wemix.com"],"iconUrls":["https://scan.wemix.com/favicon.ico"],"oracles":[]}]} \ No newline at end of file diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/interop_d-bis_org_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/interop_d-bis_org_https_headers.txt new file mode 100644 index 00000000..94797acd --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/interop_d-bis_org_https_headers.txt @@ -0,0 +1,18 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:53:02 GMT +content-type: text/html; charset=utf-8 +content-length: 22505 +vary: Accept-Encoding +x-frame-options: SAMEORIGIN +x-content-type-options: nosniff +referrer-policy: strict-origin-when-cross-origin +content-security-policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self' +vary: RSC, Next-Router-State-Tree, Next-Router-Prefetch, Accept-Encoding +cache-control: s-maxage=31536000, stale-while-revalidate +etag: "fqzlq2o9ljhd0" +alt-svc: h3=":443"; ma=86400 +x-xss-protection: 0 +strict-transport-security: max-age=63072000; includeSubDomains; preload + + +0.073623 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/keycloak_sankofa_nexus_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/keycloak_sankofa_nexus_https_headers.txt new file mode 100644 index 00000000..2caa09b6 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/keycloak_sankofa_nexus_https_headers.txt @@ -0,0 +1,13 @@ +HTTP/2 302 +date: Sun, 12 Apr 2026 13:53:14 GMT +location: https://keycloak.sankofa.nexus/admin/ +referrer-policy: no-referrer +strict-transport-security: max-age=63072000; includeSubDomains; preload +x-content-type-options: nosniff +x-xss-protection: 0 +alt-svc: h3=":443"; ma=86400 +x-frame-options: SAMEORIGIN +content-security-policy: upgrade-insecure-requests + + +0.100692 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/members_d-bis_org_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/members_d-bis_org_https_headers.txt new file mode 100644 index 00000000..1b2d7465 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/members_d-bis_org_https_headers.txt @@ -0,0 +1,18 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:52:33 GMT +content-type: text/html; charset=utf-8 +content-length: 22505 +vary: Accept-Encoding +x-frame-options: SAMEORIGIN +x-content-type-options: nosniff +referrer-policy: strict-origin-when-cross-origin +content-security-policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self' +vary: RSC, Next-Router-State-Tree, Next-Router-Prefetch, Accept-Encoding +cache-control: s-maxage=31536000, stale-while-revalidate +etag: "fqzlq2o9ljhd0" +alt-svc: h3=":443"; ma=86400 +x-xss-protection: 0 +strict-transport-security: max-age=63072000; includeSubDomains; preload + + +0.133922 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/mifos_d-bis_org_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/mifos_d-bis_org_https_headers.txt new file mode 100644 index 00000000..70263b0f --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/mifos_d-bis_org_https_headers.txt @@ -0,0 +1,12 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:52:31 GMT +content-type: text/html +content-length: 2147 +last-modified: Wed, 07 May 2025 12:00:31 GMT +vary: Accept-Encoding +etag: "681b4b5f-863" +alt-svc: h3=":443"; ma=86400 +accept-ranges: bytes + + +0.077119 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/mim4u_org_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/mim4u_org_https_headers.txt new file mode 100644 index 00000000..0289e4f0 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/mim4u_org_https_headers.txt @@ -0,0 +1,18 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:53:15 GMT +content-type: text/html +content-length: 2710 +vary: Accept-Encoding +last-modified: Tue, 31 Mar 2026 05:21:47 GMT +etag: "69cb59eb-a96" +accept-ranges: bytes +alt-svc: h3=":443"; ma=86400 +x-xss-protection: 0 +x-content-type-options: nosniff +x-frame-options: SAMEORIGIN +content-security-policy: upgrade-insecure-requests +strict-transport-security: max-age=63072000; includeSubDomains; preload +referrer-policy: strict-origin-when-cross-origin + + +0.066202 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/ops_d-bis_org_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/ops_d-bis_org_https_headers.txt new file mode 100644 index 00000000..bfa485a6 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/ops_d-bis_org_https_headers.txt @@ -0,0 +1,18 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:53:09 GMT +content-type: text/html; charset=utf-8 +content-length: 22505 +vary: Accept-Encoding +x-frame-options: SAMEORIGIN +x-content-type-options: nosniff +referrer-policy: strict-origin-when-cross-origin +content-security-policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self' +vary: RSC, Next-Router-State-Tree, Next-Router-Prefetch, Accept-Encoding +cache-control: s-maxage=31536000, stale-while-revalidate +etag: "fqzlq2o9ljhd0" +alt-svc: h3=":443"; ma=86400 +x-xss-protection: 0 +strict-transport-security: max-age=63072000; includeSubDomains; preload + + +0.071058 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/phoenix_sankofa_nexus_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/phoenix_sankofa_nexus_https_headers.txt new file mode 100644 index 00000000..928f8330 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/phoenix_sankofa_nexus_https_headers.txt @@ -0,0 +1,20 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:53:27 GMT +content-type: application/json; charset=utf-8 +content-length: 54 +vary: Accept-Encoding +x-content-type-options: nosniff +x-frame-options: SAMEORIGIN +x-xss-protection: 0 +strict-transport-security: max-age=63072000; includeSubDomains; preload +content-security-policy: default-src 'self'; script-src 'self' 'nonce-rYV5C64EM5GTfpLAvUrJ1Q=='; style-src 'self' 'nonce-rYV5C64EM5GTfpLAvUrJ1Q=='; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'; upgrade-insecure-requests +referrer-policy: strict-origin-when-cross-origin +permissions-policy: geolocation=(), microphone=(), camera=(), payment=(), usb=(), magnetometer=(), gyroscope=(), accelerometer=() +x-permitted-cross-domain-policies: none +cross-origin-embedder-policy: require-corp +cross-origin-opener-policy: same-origin +cross-origin-resource-policy: same-origin +alt-svc: h3=":443"; ma=86400 + + +0.086112 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/policy_d-bis_org_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/policy_d-bis_org_https_headers.txt new file mode 100644 index 00000000..65720967 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/policy_d-bis_org_https_headers.txt @@ -0,0 +1,18 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:52:43 GMT +content-type: text/html; charset=utf-8 +content-length: 22505 +vary: Accept-Encoding +x-frame-options: SAMEORIGIN +x-content-type-options: nosniff +referrer-policy: strict-origin-when-cross-origin +content-security-policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self' +vary: RSC, Next-Router-State-Tree, Next-Router-Prefetch, Accept-Encoding +cache-control: s-maxage=31536000, stale-while-revalidate +etag: "fqzlq2o9ljhd0" +alt-svc: h3=":443"; ma=86400 +x-xss-protection: 0 +strict-transport-security: max-age=63072000; includeSubDomains; preload + + +0.102009 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/portal_sankofa_nexus_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/portal_sankofa_nexus_https_headers.txt new file mode 100644 index 00000000..f2ea42a8 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/portal_sankofa_nexus_https_headers.txt @@ -0,0 +1,20 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:52:44 GMT +content-type: text/html; charset=utf-8 +content-length: 5259 +vary: Accept-Encoding +x-dns-prefetch-control: on +strict-transport-security: max-age=63072000; includeSubDomains; preload +x-frame-options: SAMEORIGIN +x-content-type-options: nosniff +x-xss-protection: 0 +referrer-policy: strict-origin-when-cross-origin +permissions-policy: camera=(), microphone=(), geolocation=() +content-security-policy: default-src 'self'; script-src 'self' 'unsafe-eval' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' https: +vary: RSC, Next-Router-State-Tree, Next-Router-Prefetch, Accept-Encoding +cache-control: s-maxage=31536000, stale-while-revalidate +etag: "oibim89srm41x" +alt-svc: h3=":443"; ma=86400 + + +0.093692 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/research_d-bis_org_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/research_d-bis_org_https_headers.txt new file mode 100644 index 00000000..4dcfaa49 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/research_d-bis_org_https_headers.txt @@ -0,0 +1,18 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:52:41 GMT +content-type: text/html; charset=utf-8 +content-length: 22505 +vary: Accept-Encoding +x-frame-options: SAMEORIGIN +x-content-type-options: nosniff +referrer-policy: strict-origin-when-cross-origin +content-security-policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self' +vary: RSC, Next-Router-State-Tree, Next-Router-Prefetch, Accept-Encoding +cache-control: s-maxage=31536000, stale-while-revalidate +etag: "fqzlq2o9ljhd0" +alt-svc: h3=":443"; ma=86400 +x-xss-protection: 0 +strict-transport-security: max-age=63072000; includeSubDomains; preload + + +0.244462 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc-alltra-2_d-bis_org_rpc_response.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc-alltra-2_d-bis_org_rpc_response.txt new file mode 100644 index 00000000..1283cc70 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc-alltra-2_d-bis_org_rpc_response.txt @@ -0,0 +1 @@ +{"jsonrpc":"2.0","id":1,"result":"0x8a"} \ No newline at end of file diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc-alltra-3_d-bis_org_rpc_response.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc-alltra-3_d-bis_org_rpc_response.txt new file mode 100644 index 00000000..1283cc70 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc-alltra-3_d-bis_org_rpc_response.txt @@ -0,0 +1 @@ +{"jsonrpc":"2.0","id":1,"result":"0x8a"} \ No newline at end of file diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc-alltra_d-bis_org_rpc_response.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc-alltra_d-bis_org_rpc_response.txt new file mode 100644 index 00000000..1283cc70 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc-alltra_d-bis_org_rpc_response.txt @@ -0,0 +1 @@ +{"jsonrpc":"2.0","id":1,"result":"0x8a"} \ No newline at end of file diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc-core_d-bis_org_rpc_response.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc-core_d-bis_org_rpc_response.txt new file mode 100644 index 00000000..1283cc70 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc-core_d-bis_org_rpc_response.txt @@ -0,0 +1 @@ +{"jsonrpc":"2.0","id":1,"result":"0x8a"} \ No newline at end of file diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc-fireblocks_d-bis_org_rpc_response.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc-fireblocks_d-bis_org_rpc_response.txt new file mode 100644 index 00000000..1283cc70 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc-fireblocks_d-bis_org_rpc_response.txt @@ -0,0 +1 @@ +{"jsonrpc":"2.0","id":1,"result":"0x8a"} \ No newline at end of file diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc-http-prv_d-bis_org_rpc_response.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc-http-prv_d-bis_org_rpc_response.txt new file mode 100644 index 00000000..1283cc70 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc-http-prv_d-bis_org_rpc_response.txt @@ -0,0 +1 @@ +{"jsonrpc":"2.0","id":1,"result":"0x8a"} \ No newline at end of file diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc-http-pub_d-bis_org_rpc_response.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc-http-pub_d-bis_org_rpc_response.txt new file mode 100644 index 00000000..1283cc70 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc-http-pub_d-bis_org_rpc_response.txt @@ -0,0 +1 @@ +{"jsonrpc":"2.0","id":1,"result":"0x8a"} \ No newline at end of file diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc-hybx-2_d-bis_org_rpc_response.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc-hybx-2_d-bis_org_rpc_response.txt new file mode 100644 index 00000000..1283cc70 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc-hybx-2_d-bis_org_rpc_response.txt @@ -0,0 +1 @@ +{"jsonrpc":"2.0","id":1,"result":"0x8a"} \ No newline at end of file diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc-hybx-3_d-bis_org_rpc_response.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc-hybx-3_d-bis_org_rpc_response.txt new file mode 100644 index 00000000..1283cc70 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc-hybx-3_d-bis_org_rpc_response.txt @@ -0,0 +1 @@ +{"jsonrpc":"2.0","id":1,"result":"0x8a"} \ No newline at end of file diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc-hybx_d-bis_org_rpc_response.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc-hybx_d-bis_org_rpc_response.txt new file mode 100644 index 00000000..1283cc70 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc-hybx_d-bis_org_rpc_response.txt @@ -0,0 +1 @@ +{"jsonrpc":"2.0","id":1,"result":"0x8a"} \ No newline at end of file diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc2_d-bis_org_rpc_response.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc2_d-bis_org_rpc_response.txt new file mode 100644 index 00000000..1283cc70 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc2_d-bis_org_rpc_response.txt @@ -0,0 +1 @@ +{"jsonrpc":"2.0","id":1,"result":"0x8a"} \ No newline at end of file diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc_d-bis_org_rpc_response.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc_d-bis_org_rpc_response.txt new file mode 100644 index 00000000..1283cc70 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc_d-bis_org_rpc_response.txt @@ -0,0 +1 @@ +{"jsonrpc":"2.0","id":1,"result":"0x8a"} \ No newline at end of file diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc_defi-oracle_io_rpc_response.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc_defi-oracle_io_rpc_response.txt new file mode 100644 index 00000000..1283cc70 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc_defi-oracle_io_rpc_response.txt @@ -0,0 +1 @@ +{"jsonrpc":"2.0","id":1,"result":"0x8a"} \ No newline at end of file diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc_public-0138_defi-oracle_io_rpc_response.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc_public-0138_defi-oracle_io_rpc_response.txt new file mode 100644 index 00000000..1283cc70 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/rpc_public-0138_defi-oracle_io_rpc_response.txt @@ -0,0 +1 @@ +{"jsonrpc":"2.0","id":1,"result":"0x8a"} \ No newline at end of file diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/sandbox_d-bis_org_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/sandbox_d-bis_org_https_headers.txt new file mode 100644 index 00000000..46e42edf --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/sandbox_d-bis_org_https_headers.txt @@ -0,0 +1,18 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:53:18 GMT +content-type: text/html; charset=utf-8 +content-length: 22505 +vary: Accept-Encoding +x-frame-options: SAMEORIGIN +x-content-type-options: nosniff +referrer-policy: strict-origin-when-cross-origin +content-security-policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self' +vary: RSC, Next-Router-State-Tree, Next-Router-Prefetch, Accept-Encoding +cache-control: s-maxage=31536000, stale-while-revalidate +etag: "fqzlq2o9ljhd0" +alt-svc: h3=":443"; ma=86400 +x-xss-protection: 0 +strict-transport-security: max-age=63072000; includeSubDomains; preload + + +0.088363 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/sankofa_nexus_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/sankofa_nexus_https_headers.txt new file mode 100644 index 00000000..c846b9a2 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/sankofa_nexus_https_headers.txt @@ -0,0 +1,19 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:52:49 GMT +content-type: text/html; charset=utf-8 +vary: Accept-Encoding +x-content-type-options: nosniff +x-dns-prefetch-control: on +strict-transport-security: max-age=63072000; includeSubDomains; preload +x-frame-options: SAMEORIGIN +referrer-policy: strict-origin-when-cross-origin +permissions-policy: camera=(), microphone=(), geolocation=() +content-security-policy: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' https: ws: wss: +vary: RSC, Next-Router-State-Tree, Next-Router-Prefetch, Accept-Encoding +link: ; rel=preload; as="font"; crossorigin=""; type="font/woff2" +cache-control: private, no-cache, no-store, max-age=0, must-revalidate +alt-svc: h3=":443"; ma=86400 +x-xss-protection: 0 + + +0.116520 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/secure_d-bis_org_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/secure_d-bis_org_https_headers.txt new file mode 100644 index 00000000..c7fd8364 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/secure_d-bis_org_https_headers.txt @@ -0,0 +1,18 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:54:42 GMT +content-type: text/html +content-length: 795 +vary: Accept-Encoding +last-modified: Thu, 02 Apr 2026 19:27:04 GMT +etag: "69cec308-31b" +x-frame-options: SAMEORIGIN +x-content-type-options: nosniff +x-xss-protection: 0 +accept-ranges: bytes +alt-svc: h3=":443"; ma=86400 +content-security-policy: upgrade-insecure-requests +strict-transport-security: max-age=63072000; includeSubDomains; preload +referrer-policy: strict-origin-when-cross-origin + + +0.100453 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/secure_mim4u_org_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/secure_mim4u_org_https_headers.txt new file mode 100644 index 00000000..8cd0663e --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/secure_mim4u_org_https_headers.txt @@ -0,0 +1,18 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:53:59 GMT +content-type: text/html +content-length: 2710 +vary: Accept-Encoding +last-modified: Tue, 31 Mar 2026 05:21:47 GMT +etag: "69cb59eb-a96" +accept-ranges: bytes +alt-svc: h3=":443"; ma=86400 +x-xss-protection: 0 +x-content-type-options: nosniff +x-frame-options: SAMEORIGIN +content-security-policy: upgrade-insecure-requests +strict-transport-security: max-age=63072000; includeSubDomains; preload +referrer-policy: strict-origin-when-cross-origin + + +0.174413 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/status_d-bis_org_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/status_d-bis_org_https_headers.txt new file mode 100644 index 00000000..4eb0fd98 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/status_d-bis_org_https_headers.txt @@ -0,0 +1,18 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:53:50 GMT +content-type: text/html; charset=utf-8 +content-length: 22505 +vary: Accept-Encoding +x-frame-options: SAMEORIGIN +x-content-type-options: nosniff +referrer-policy: strict-origin-when-cross-origin +content-security-policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self' +vary: RSC, Next-Router-State-Tree, Next-Router-Prefetch, Accept-Encoding +cache-control: s-maxage=31536000, stale-while-revalidate +etag: "fqzlq2o9ljhd0" +alt-svc: h3=":443"; ma=86400 +x-xss-protection: 0 +strict-transport-security: max-age=63072000; includeSubDomains; preload + + +0.080954 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/studio_sankofa_nexus_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/studio_sankofa_nexus_https_headers.txt new file mode 100644 index 00000000..a218eef0 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/studio_sankofa_nexus_https_headers.txt @@ -0,0 +1,13 @@ +HTTP/2 502 +date: Sun, 12 Apr 2026 13:52:58 GMT +content-type: text/html +content-length: 122 +alt-svc: h3=":443"; ma=86400 +x-xss-protection: 0 +x-content-type-options: nosniff +x-frame-options: SAMEORIGIN +content-security-policy: upgrade-insecure-requests +strict-transport-security: max-age=63072000; includeSubDomains; preload + + +0.059656 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/the-order_sankofa_nexus_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/the-order_sankofa_nexus_https_headers.txt new file mode 100644 index 00000000..41afd84a --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/the-order_sankofa_nexus_https_headers.txt @@ -0,0 +1,20 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:53:37 GMT +content-type: text/html; charset=utf-8 +content-length: 5259 +vary: Accept-Encoding +x-dns-prefetch-control: on +strict-transport-security: max-age=63072000; includeSubDomains; preload +x-frame-options: SAMEORIGIN +x-content-type-options: nosniff +x-xss-protection: 0 +referrer-policy: strict-origin-when-cross-origin +permissions-policy: camera=(), microphone=(), geolocation=() +content-security-policy: default-src 'self'; script-src 'self' 'unsafe-eval' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self' https: +vary: RSC, Next-Router-State-Tree, Next-Router-Prefetch, Accept-Encoding +cache-control: s-maxage=31536000, stale-while-revalidate +etag: "oibim89srm41x" +alt-svc: h3=":443"; ma=86400 + + +0.122532 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/training_mim4u_org_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/training_mim4u_org_https_headers.txt new file mode 100644 index 00000000..eb3863f7 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/training_mim4u_org_https_headers.txt @@ -0,0 +1,18 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:54:31 GMT +content-type: text/html +content-length: 2710 +vary: Accept-Encoding +last-modified: Tue, 31 Mar 2026 05:21:47 GMT +etag: "69cb59eb-a96" +accept-ranges: bytes +alt-svc: h3=":443"; ma=86400 +x-xss-protection: 0 +x-content-type-options: nosniff +x-frame-options: SAMEORIGIN +content-security-policy: upgrade-insecure-requests +strict-transport-security: max-age=63072000; includeSubDomains; preload +referrer-policy: strict-origin-when-cross-origin + + +0.078750 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/verification_report.md b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/verification_report.md new file mode 100644 index 00000000..19c38b6a --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/verification_report.md @@ -0,0 +1,628 @@ +# End-to-End Routing Verification Report + +**Date**: 2026-04-12T06:55:05-07:00 +**Public IP**: 76.53.10.36 +**Profile**: all +**Verifier**: intlc + +## All endpoints (64) + +| Domain | Type | URL | +|--------|------|-----| +| admin.d-bis.org | web | https://admin.d-bis.org | +| admin.sankofa.nexus | web | https://admin.sankofa.nexus | +| blockscout.defi-oracle.io | web | https://blockscout.defi-oracle.io | +| cacti-alltra.d-bis.org | web | https://cacti-alltra.d-bis.org | +| cacti-hybx.d-bis.org | web | https://cacti-hybx.d-bis.org | +| codespaces.d-bis.org | web | https://codespaces.d-bis.org | +| core.d-bis.org | web | https://core.d-bis.org | +| d-bis.org | web | https://d-bis.org | +| dapp.d-bis.org | web | https://dapp.d-bis.org | +| dash.sankofa.nexus | web | https://dash.sankofa.nexus | +| data.d-bis.org | api | https://data.d-bis.org | +| dbis-admin.d-bis.org | web | https://dbis-admin.d-bis.org | +| dbis-api-2.d-bis.org | api | https://dbis-api-2.d-bis.org | +| dbis-api.d-bis.org | api | https://dbis-api.d-bis.org | +| dev.d-bis.org | web | https://dev.d-bis.org | +| developers.d-bis.org | web | https://developers.d-bis.org | +| docs.d-bis.org | web | https://docs.d-bis.org | +| explorer.d-bis.org | web | https://explorer.d-bis.org | +| gitea.d-bis.org | web | https://gitea.d-bis.org | +| identity.d-bis.org | web | https://identity.d-bis.org | +| info.defi-oracle.io | web | https://info.defi-oracle.io | +| interop.d-bis.org | web | https://interop.d-bis.org | +| keycloak.sankofa.nexus | web | https://keycloak.sankofa.nexus | +| members.d-bis.org | web | https://members.d-bis.org | +| mifos.d-bis.org | web | https://mifos.d-bis.org | +| mim4u.org | web | https://mim4u.org | +| ops.d-bis.org | web | https://ops.d-bis.org | +| phoenix.sankofa.nexus | web | https://phoenix.sankofa.nexus | +| policy.d-bis.org | web | https://policy.d-bis.org | +| portal.sankofa.nexus | web | https://portal.sankofa.nexus | +| research.d-bis.org | web | https://research.d-bis.org | +| rpc-alltra-2.d-bis.org | rpc-http | https://rpc-alltra-2.d-bis.org | +| rpc-alltra-3.d-bis.org | rpc-http | https://rpc-alltra-3.d-bis.org | +| rpc-alltra.d-bis.org | rpc-http | https://rpc-alltra.d-bis.org | +| rpc-core.d-bis.org | rpc-http | https://rpc-core.d-bis.org | +| rpc-fireblocks.d-bis.org | rpc-http | https://rpc-fireblocks.d-bis.org | +| rpc-http-prv.d-bis.org | rpc-http | https://rpc-http-prv.d-bis.org | +| rpc-http-pub.d-bis.org | rpc-http | https://rpc-http-pub.d-bis.org | +| rpc-hybx-2.d-bis.org | rpc-http | https://rpc-hybx-2.d-bis.org | +| rpc-hybx-3.d-bis.org | rpc-http | https://rpc-hybx-3.d-bis.org | +| rpc-hybx.d-bis.org | rpc-http | https://rpc-hybx.d-bis.org | +| rpc-ws-prv.d-bis.org | rpc-ws | https://rpc-ws-prv.d-bis.org | +| rpc-ws-pub.d-bis.org | rpc-ws | https://rpc-ws-pub.d-bis.org | +| rpc.d-bis.org | rpc-http | https://rpc.d-bis.org | +| rpc.defi-oracle.io | rpc-http | https://rpc.defi-oracle.io | +| rpc.public-0138.defi-oracle.io | rpc-http | https://rpc.public-0138.defi-oracle.io | +| rpc2.d-bis.org | rpc-http | https://rpc2.d-bis.org | +| sandbox.d-bis.org | web | https://sandbox.d-bis.org | +| sankofa.nexus | web | https://sankofa.nexus | +| secure.d-bis.org | web | https://secure.d-bis.org | +| secure.mim4u.org | web | https://secure.mim4u.org | +| status.d-bis.org | web | https://status.d-bis.org | +| studio.sankofa.nexus | web | https://studio.sankofa.nexus | +| the-order.sankofa.nexus | web | https://the-order.sankofa.nexus | +| training.mim4u.org | web | https://training.mim4u.org | +| ws.rpc-fireblocks.d-bis.org | rpc-ws | https://ws.rpc-fireblocks.d-bis.org | +| ws.rpc.d-bis.org | rpc-ws | https://ws.rpc.d-bis.org | +| ws.rpc2.d-bis.org | rpc-ws | https://ws.rpc2.d-bis.org | +| wss.defi-oracle.io | rpc-ws | https://wss.defi-oracle.io | +| www.d-bis.org | web | https://www.d-bis.org | +| www.mim4u.org | web | https://www.mim4u.org | +| www.phoenix.sankofa.nexus | web | https://www.phoenix.sankofa.nexus | +| www.sankofa.nexus | web | https://www.sankofa.nexus | +| www.the-order.sankofa.nexus | web | https://www.the-order.sankofa.nexus | + +## Summary + +- **Total domains tested**: 64 +- **DNS tests passed**: 64 +- **HTTPS tests passed**: 43 +- **Explorer surface failures**: 0 +- **Failed tests**: 0 +- **Skipped / optional (not configured or unreachable)**: 0 +- **Average response time**: 0.15596259090909093s + +## Results overview + +| Domain | Type | DNS | SSL | HTTPS | Root | RPC | Explorer+ | +|--------|------|-----|-----|-------|------|-----|-----------| +| ws.rpc-fireblocks.d-bis.org | rpc-ws | pass | pass | - | - | - | - | +| dbis-admin.d-bis.org | web | pass | pass | pass | - | - | - | +| core.d-bis.org | web | pass | pass | pass | - | - | - | +| rpc-alltra-3.d-bis.org | rpc-http | pass | pass | - | - | pass | - | +| mifos.d-bis.org | web | pass | pass | pass | - | - | - | +| members.d-bis.org | web | pass | pass | pass | - | - | - | +| admin.sankofa.nexus | web | pass | pass | pass | - | - | - | +| dash.sankofa.nexus | web | pass | pass | pass | - | - | - | +| rpc-hybx-2.d-bis.org | rpc-http | pass | pass | - | - | pass | - | +| research.d-bis.org | web | pass | pass | pass | - | - | - | +| policy.d-bis.org | web | pass | pass | pass | - | - | - | +| portal.sankofa.nexus | web | pass | pass | pass | - | - | - | +| cacti-hybx.d-bis.org | web | pass | pass | pass | - | - | - | +| developers.d-bis.org | web | pass | pass | pass | - | - | - | +| sankofa.nexus | web | pass | pass | pass | - | - | - | +| rpc-alltra.d-bis.org | rpc-http | pass | pass | - | - | pass | - | +| rpc-http-pub.d-bis.org | rpc-http | pass | pass | - | - | pass | - | +| info.defi-oracle.io | web | pass | pass | pass | - | - | - | +| rpc.public-0138.defi-oracle.io | rpc-http | pass | pass | - | - | pass | - | +| studio.sankofa.nexus | web | pass | pass | warn | - | - | - | +| www.d-bis.org | web | pass | pass | pass | - | - | - | +| dbis-api.d-bis.org | api | pass | pass | pass | - | - | - | +| interop.d-bis.org | web | pass | pass | pass | - | - | - | +| docs.d-bis.org | web | pass | pass | pass | - | - | - | +| identity.d-bis.org | web | pass | pass | pass | - | - | - | +| rpc-hybx-3.d-bis.org | rpc-http | pass | pass | - | - | pass | - | +| rpc.d-bis.org | rpc-http | pass | pass | - | - | pass | - | +| dapp.d-bis.org | web | pass | pass | pass | - | - | - | +| ops.d-bis.org | web | pass | pass | pass | - | - | - | +| www.sankofa.nexus | web | pass | pass | pass | - | - | - | +| www.the-order.sankofa.nexus | web | pass | pass | pass | - | - | - | +| keycloak.sankofa.nexus | web | pass | pass | pass | - | - | - | +| mim4u.org | web | pass | pass | pass | - | - | - | +| data.d-bis.org | api | pass | pass | pass | - | - | - | +| sandbox.d-bis.org | web | pass | pass | pass | - | - | - | +| ws.rpc.d-bis.org | rpc-ws | pass | pass | - | - | - | - | +| phoenix.sankofa.nexus | web | pass | pass | pass | - | - | - | +| www.mim4u.org | web | pass | pass | pass | - | - | - | +| wss.defi-oracle.io | rpc-ws | pass | pass | - | - | - | - | +| the-order.sankofa.nexus | web | pass | pass | pass | - | - | - | +| rpc2.d-bis.org | rpc-http | pass | pass | - | - | pass | - | +| rpc-ws-pub.d-bis.org | rpc-ws | pass | pass | - | - | - | - | +| dev.d-bis.org | web | pass | pass | pass | - | - | - | +| admin.d-bis.org | web | pass | pass | pass | - | - | - | +| status.d-bis.org | web | pass | pass | pass | - | - | - | +| rpc-alltra-2.d-bis.org | rpc-http | pass | pass | - | - | pass | - | +| rpc-http-prv.d-bis.org | rpc-http | pass | pass | - | - | pass | - | +| www.phoenix.sankofa.nexus | web | pass | pass | pass | - | - | - | +| gitea.d-bis.org | web | pass | pass | pass | - | - | - | +| secure.mim4u.org | web | pass | pass | pass | - | - | - | +| rpc-fireblocks.d-bis.org | rpc-http | pass | pass | - | - | pass | - | +| explorer.d-bis.org | web | pass | pass | pass | - | - | - | +| training.mim4u.org | web | pass | pass | pass | - | - | - | +| blockscout.defi-oracle.io | web | pass | pass | pass | - | - | - | +| dbis-api-2.d-bis.org | api | pass | pass | pass | - | - | - | +| d-bis.org | web | pass | pass | pass | - | - | - | +| rpc-core.d-bis.org | rpc-http | pass | pass | - | - | pass | - | +| secure.d-bis.org | web | pass | pass | pass | - | - | - | +| rpc-hybx.d-bis.org | rpc-http | pass | pass | - | - | pass | - | +| codespaces.d-bis.org | web | pass | pass | pass | - | - | - | +| rpc.defi-oracle.io | rpc-http | pass | pass | - | - | pass | - | +| rpc-ws-prv.d-bis.org | rpc-ws | pass | pass | - | - | - | - | +| ws.rpc2.d-bis.org | rpc-ws | pass | pass | - | - | - | - | +| cacti-alltra.d-bis.org | web | pass | pass | pass | - | - | - | + +## Test Results by Domain (detail) + + +### ws.rpc-fireblocks.d-bis.org +- Type: rpc-ws +- DNS: pass +- SSL: pass +- Details: See `all_e2e_results.json` + +### dbis-admin.d-bis.org +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### core.d-bis.org +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### rpc-alltra-3.d-bis.org +- Type: rpc-http +- DNS: pass +- SSL: pass +- RPC: pass +- Details: See `all_e2e_results.json` + +### mifos.d-bis.org +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### members.d-bis.org +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### admin.sankofa.nexus +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### dash.sankofa.nexus +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### rpc-hybx-2.d-bis.org +- Type: rpc-http +- DNS: pass +- SSL: pass +- RPC: pass +- Details: See `all_e2e_results.json` + +### research.d-bis.org +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### policy.d-bis.org +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### portal.sankofa.nexus +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### cacti-hybx.d-bis.org +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### developers.d-bis.org +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### sankofa.nexus +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### rpc-alltra.d-bis.org +- Type: rpc-http +- DNS: pass +- SSL: pass +- RPC: pass +- Details: See `all_e2e_results.json` + +### rpc-http-pub.d-bis.org +- Type: rpc-http +- DNS: pass +- SSL: pass +- RPC: pass +- Details: See `all_e2e_results.json` + +### info.defi-oracle.io +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### rpc.public-0138.defi-oracle.io +- Type: rpc-http +- DNS: pass +- SSL: pass +- RPC: pass +- Details: See `all_e2e_results.json` + +### studio.sankofa.nexus +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: warn +- Details: See `all_e2e_results.json` + +### www.d-bis.org +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### dbis-api.d-bis.org +- Type: api +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### interop.d-bis.org +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### docs.d-bis.org +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### identity.d-bis.org +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### rpc-hybx-3.d-bis.org +- Type: rpc-http +- DNS: pass +- SSL: pass +- RPC: pass +- Details: See `all_e2e_results.json` + +### rpc.d-bis.org +- Type: rpc-http +- DNS: pass +- SSL: pass +- RPC: pass +- Details: See `all_e2e_results.json` + +### dapp.d-bis.org +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### ops.d-bis.org +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### www.sankofa.nexus +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### www.the-order.sankofa.nexus +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### keycloak.sankofa.nexus +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### mim4u.org +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### data.d-bis.org +- Type: api +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### sandbox.d-bis.org +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### ws.rpc.d-bis.org +- Type: rpc-ws +- DNS: pass +- SSL: pass +- Details: See `all_e2e_results.json` + +### phoenix.sankofa.nexus +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### www.mim4u.org +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### wss.defi-oracle.io +- Type: rpc-ws +- DNS: pass +- SSL: pass +- Details: See `all_e2e_results.json` + +### the-order.sankofa.nexus +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### rpc2.d-bis.org +- Type: rpc-http +- DNS: pass +- SSL: pass +- RPC: pass +- Details: See `all_e2e_results.json` + +### rpc-ws-pub.d-bis.org +- Type: rpc-ws +- DNS: pass +- SSL: pass +- Details: See `all_e2e_results.json` + +### dev.d-bis.org +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### admin.d-bis.org +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### status.d-bis.org +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### rpc-alltra-2.d-bis.org +- Type: rpc-http +- DNS: pass +- SSL: pass +- RPC: pass +- Details: See `all_e2e_results.json` + +### rpc-http-prv.d-bis.org +- Type: rpc-http +- DNS: pass +- SSL: pass +- RPC: pass +- Details: See `all_e2e_results.json` + +### www.phoenix.sankofa.nexus +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### gitea.d-bis.org +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### secure.mim4u.org +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### rpc-fireblocks.d-bis.org +- Type: rpc-http +- DNS: pass +- SSL: pass +- RPC: pass +- Details: See `all_e2e_results.json` + +### explorer.d-bis.org +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Blockscout API: pass +- Command Center: pass +- Mission Control stream: pass +- Mission Control trace: pass +- Mission Control liquidity: pass +- Details: See `all_e2e_results.json` + +### training.mim4u.org +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### blockscout.defi-oracle.io +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Blockscout API: pass +- Details: See `all_e2e_results.json` + +### dbis-api-2.d-bis.org +- Type: api +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### d-bis.org +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### rpc-core.d-bis.org +- Type: rpc-http +- DNS: pass +- SSL: pass +- RPC: pass +- Details: See `all_e2e_results.json` + +### secure.d-bis.org +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### rpc-hybx.d-bis.org +- Type: rpc-http +- DNS: pass +- SSL: pass +- RPC: pass +- Details: See `all_e2e_results.json` + +### codespaces.d-bis.org +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +### rpc.defi-oracle.io +- Type: rpc-http +- DNS: pass +- SSL: pass +- RPC: pass +- Details: See `all_e2e_results.json` + +### rpc-ws-prv.d-bis.org +- Type: rpc-ws +- DNS: pass +- SSL: pass +- Details: See `all_e2e_results.json` + +### ws.rpc2.d-bis.org +- Type: rpc-ws +- DNS: pass +- SSL: pass +- Details: See `all_e2e_results.json` + +### cacti-alltra.d-bis.org +- Type: web +- DNS: pass +- SSL: pass +- HTTPS: pass +- Details: See `all_e2e_results.json` + +## Files Generated + +- `all_e2e_results.json` - Complete E2E test results +- `*_https_headers.txt` - HTTP response headers per domain +- `*_rpc_response.txt` - RPC response per domain +- `verification_report.md` - This report + +## Notes + +- **Optional domains:** Domains in `E2E_OPTIONAL_WHEN_FAIL` (default: many d-bis.org/sankofa/mim4u/rpc) have any fail treated as skip so the run passes when off-LAN or services unreachable. The canonical explorer `explorer.d-bis.org` is intentionally **not** in that list anymore. Set `E2E_OPTIONAL_WHEN_FAIL=` (empty) for strict mode. +- WebSocket tests require `wscat` tool: `npm install -g wscat` +- OpenSSL fetch uses `timeout` (`E2E_OPENSSL_TIMEOUT` / `E2E_OPENSSL_X509_TIMEOUT`, defaults 15s / 5s) so `openssl s_client` cannot hang indefinitely +- Internal connectivity tests require access to NPMplus container +- Explorer (explorer.d-bis.org): verifies Blockscout API, `/chain138-command-center.html`, and Mission Control stream / trace / liquidity endpoints. Use `SKIP_BLOCKSCOUT_API=1` only when you need to skip the Blockscout API sub-check specifically. + +## Next Steps + +1. Review test results for each domain +2. Investigate any failed tests +3. Test WebSocket connections for RPC WS domains (if wscat available) +4. Test internal connectivity from NPMplus container +5. Update source-of-truth JSON after verification diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/www_d-bis_org_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/www_d-bis_org_https_headers.txt new file mode 100644 index 00000000..14574b57 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/www_d-bis_org_https_headers.txt @@ -0,0 +1,14 @@ +HTTP/2 301 +date: Sun, 12 Apr 2026 13:52:59 GMT +content-type: text/html +content-length: 134 +location: https://d-bis.org/ +alt-svc: h3=":443"; ma=86400 +x-xss-protection: 0 +x-content-type-options: nosniff +x-frame-options: SAMEORIGIN +content-security-policy: upgrade-insecure-requests +strict-transport-security: max-age=63072000; includeSubDomains; preload + + +0.052194 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/www_mim4u_org_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/www_mim4u_org_https_headers.txt new file mode 100644 index 00000000..d3e73ec9 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/www_mim4u_org_https_headers.txt @@ -0,0 +1,18 @@ +HTTP/2 200 +date: Sun, 12 Apr 2026 13:53:28 GMT +content-type: text/html +content-length: 2710 +vary: Accept-Encoding +last-modified: Tue, 31 Mar 2026 05:21:47 GMT +etag: "69cb59eb-a96" +accept-ranges: bytes +alt-svc: h3=":443"; ma=86400 +x-xss-protection: 0 +x-content-type-options: nosniff +x-frame-options: SAMEORIGIN +content-security-policy: upgrade-insecure-requests +strict-transport-security: max-age=63072000; includeSubDomains; preload +referrer-policy: strict-origin-when-cross-origin + + +0.060509 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/www_phoenix_sankofa_nexus_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/www_phoenix_sankofa_nexus_https_headers.txt new file mode 100644 index 00000000..b984566c --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/www_phoenix_sankofa_nexus_https_headers.txt @@ -0,0 +1,14 @@ +HTTP/2 301 +date: Sun, 12 Apr 2026 13:53:56 GMT +content-type: text/html +content-length: 134 +location: https://phoenix.sankofa.nexus/health +alt-svc: h3=":443"; ma=86400 +x-xss-protection: 0 +x-content-type-options: nosniff +x-frame-options: SAMEORIGIN +content-security-policy: upgrade-insecure-requests +strict-transport-security: max-age=63072000; includeSubDomains; preload + + +0.115175 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/www_sankofa_nexus_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/www_sankofa_nexus_https_headers.txt new file mode 100644 index 00000000..753d34b3 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/www_sankofa_nexus_https_headers.txt @@ -0,0 +1,14 @@ +HTTP/2 301 +date: Sun, 12 Apr 2026 13:53:11 GMT +content-type: text/html +content-length: 134 +location: https://sankofa.nexus/ +alt-svc: h3=":443"; ma=86400 +x-xss-protection: 0 +x-content-type-options: nosniff +x-frame-options: SAMEORIGIN +content-security-policy: upgrade-insecure-requests +strict-transport-security: max-age=63072000; includeSubDomains; preload + + +0.065033 diff --git a/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/www_the-order_sankofa_nexus_https_headers.txt b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/www_the-order_sankofa_nexus_https_headers.txt new file mode 100644 index 00000000..7a0b6650 --- /dev/null +++ b/docs/04-configuration/verification-evidence/e2e-verification-20260412_065215/www_the-order_sankofa_nexus_https_headers.txt @@ -0,0 +1,14 @@ +HTTP/2 301 +date: Sun, 12 Apr 2026 13:53:12 GMT +content-type: text/html +content-length: 134 +location: https://the-order.sankofa.nexus/ +alt-svc: h3=":443"; ma=86400 +x-xss-protection: 0 +x-content-type-options: nosniff +x-frame-options: SAMEORIGIN +content-security-policy: upgrade-insecure-requests +strict-transport-security: max-age=63072000; includeSubDomains; preload + + +0.138665 diff --git a/docs/11-references/CHAIN138_GRID_6534_WALLET_FUNDING_PLAN.md b/docs/11-references/CHAIN138_GRID_6534_WALLET_FUNDING_PLAN.md index c7671965..0258d927 100644 --- a/docs/11-references/CHAIN138_GRID_6534_WALLET_FUNDING_PLAN.md +++ b/docs/11-references/CHAIN138_GRID_6534_WALLET_FUNDING_PLAN.md @@ -1,7 +1,7 @@ # Chain 138 — Funding plan for 33×33×6 (6,534) PMM soak grid wallets **Purpose:** Separate the **operator (deployer)** role from the **6,534 grid EOAs**, summarize how to fund native gas and ERC-20 inventory for soak activity, and give **order-of-magnitude budgets** with formulas. -**Companion:** [DEPLOYER_WALLET_FUNDING_PLAN_PMM_POOLS.md](DEPLOYER_WALLET_FUNDING_PLAN_PMM_POOLS.md) (deployer liquidity / reserve split). +**Companion:** [DEPLOYER_WALLET_FUNDING_PLAN_PMM_POOLS.md](DEPLOYER_WALLET_FUNDING_PLAN_PMM_POOLS.md) (deployer liquidity / reserve split). **Policy framing:** the grid is **operational capacity** for PMM execution; GRU/XDR and corridor truth remain **reference-anchored** — [GRU_REFERENCE_PRIMACY_AND_MESH_EXECUTION_MODEL.md](../04-configuration/GRU_REFERENCE_PRIMACY_AND_MESH_EXECUTION_MODEL.md). **Automation:** `scripts/deployment/pmm-soak-operator-fund-grid.sh` (`--native` or ERC-20), `scripts/deployment/pmm-soak-export-wallet-grid.py`, `scripts/deployment/chain138-pmm-soak-grid-bot.sh`, smoke `scripts/deployment/pmm-soak-grid-smoke-check.sh`, **one-shot** `scripts/deployment/pmm-soak-complete-operator-bootstrap.sh` (creates `~/.secure-secrets/chain138-pmm-soak-grid.mnemonic` when `PMM_SOAK_AUTO_INIT_GRID_MNEMONIC=1`, exports 6,534 addresses to `config/pmm-soak-wallet-grid.json`, optional `--apply-funds --to-linear N`), **full-grid resume** `scripts/deployment/pmm-soak-complete-grid-funding-operator.sh` (waits chain + deployer nonce, mirror-USDC mint shortfall, native + four ERC-20 legs in chunks; env `PMM_SOAK_START_LEG`, `PMM_SOAK_RESUME_NATIVE_FROM_LINEAR`, `PMM_SOAK_RPC_URL_OVERRIDE`), and **`scripts/deployment/pmm-soak-operator-fund-full-grid-tranches.sh`** (same legs as tranche loops; same RPC override pattern). **CI:** `.github/workflows/pmm-soak-grid-smoke.yml` runs the smoke script on `CI=true` with public read-only RPC when `RPC_URL_138` is unset. **Pool narrowing:** `scripts/lib/pmm-soak-pools.sh` (`PMM_SOAK_POOL_PRESET`, `PMM_SOAK_POOLS_FILE`). **Swap execution:** `scripts/lib/pmm-soak-chain138-tick.sh` defaults to **`CHAIN138_PMM_SOAK_SWAP_VIA=pool`** (EOA `transfer` into the DVM + `sellBase` / `sellQuote`). On this chain, `DODOPMMIntegration.swapExactIn` reverts inside the pool when the integration contract is `msg.sender`; set `CHAIN138_PMM_SOAK_SWAP_VIA=integration` only if you have confirmed that path on your RPC. diff --git a/docs/11-references/GRU_V2_PUBLIC_PROTOCOL_DEPLOYMENT_STATUS.md b/docs/11-references/GRU_V2_PUBLIC_PROTOCOL_DEPLOYMENT_STATUS.md index 400443a6..bcae9660 100644 --- a/docs/11-references/GRU_V2_PUBLIC_PROTOCOL_DEPLOYMENT_STATUS.md +++ b/docs/11-references/GRU_V2_PUBLIC_PROTOCOL_DEPLOYMENT_STATUS.md @@ -3,6 +3,8 @@ **Last Updated:** 2026-04-04 **Purpose:** Single truthful status surface for the GRU v2 public-network rollout across the public EVM `cW*` token mesh, Wave 1 bridge/transport activation, and the public protocol venues that matter for live `cW*` liquidity. +**Policy:** Public mesh liquidity is **reference-anchored execution capacity**, not an independent FX oracle — see [GRU_REFERENCE_PRIMACY_AND_MESH_EXECUTION_MODEL.md](../04-configuration/GRU_REFERENCE_PRIMACY_AND_MESH_EXECUTION_MODEL.md) and `cross-chain-pmm-lps/config/peg-bands.json` **`gruPolicyIntegration`**. + --- ## Bottom line diff --git a/docs/11-references/LIQUIDITY_POOLS_MASTER_MAP.md b/docs/11-references/LIQUIDITY_POOLS_MASTER_MAP.md index 71573c91..f3737524 100644 --- a/docs/11-references/LIQUIDITY_POOLS_MASTER_MAP.md +++ b/docs/11-references/LIQUIDITY_POOLS_MASTER_MAP.md @@ -167,6 +167,8 @@ Not liquidity pools per se; they support XAU triangulation for private mesh pari ## Public-chain cW* stabilization (edge pools + bot) +**GRU policy:** treat this mesh as **execution capacity** around reference-anchored FX and reserve rules, not standalone shadow FX — [GRU_REFERENCE_PRIMACY_AND_MESH_EXECUTION_MODEL.md](../04-configuration/GRU_REFERENCE_PRIMACY_AND_MESH_EXECUTION_MODEL.md). + M1 tokens on Chain 138 (cUSDT, cUSDC, cAUSDT, cEURC, cEURT, cUSDW) are bridged to public chains as **cW\*** wrappers (cWUSDT, cWUSDC, etc.). The intended public-chain stabilization model uses **single-sided PMM edge pools** (cW* / USDC, cW* / USDT, etc.) plus a **bot-driven stabilization mesh** when those components are deployed. Specs, pool matrix, peg bands, and deployment recipe: **Current repo reality:** `cross-chain-pmm-lps/config/deployment-status.json` records cW token addresses on the supported public EVM chains and now includes the first live Mainnet DODO PMM cW pools: `cWUSDT/USDC`, `cWUSDC/USDC`, `cWUSDT/USDT`, `cWUSDC/USDT`, **`cWUSDT/cWUSDC`** (`0xe944b7Cb012A0820c07f54D51e92f0e1C74168DB`, one vault, both swap directions), and the first six non-USD Wave 1 rows `cWEURC/USDC` (`0x0bC750F9c6DbDcd76B205695A356491b1B9ef098`), `cWGBPC/USDC` (`0x5488042dF882893a3e7074453E2005CaDE4101b0`), `cWAUDC/USDC` (`0x6c1bD4F43c5f330E50B61DE81066dA7C61a9b5b4`), `cWCADC/USDC` (`0xE0F35b5736FDd0a2F4B618621b0A08F8D8A3f92A`), `cWJPYC/USDC` (`0x8A4187dF0A8FE855cC53A4F7B2D8346588Ee9794`), and `cWCHFC/USDC` (`0x776Ca556deD3245984F504F4bef8Eeec55C50190`). The repo still does **not** currently assert any live public cW* `Balancer`, `Curve`, `Uniswap`, or `1inch` venues, and the broader multi-chain cW* mesh remains incomplete. Avalanche still has the proven `cUSDT -> cWUSDT` mint corridor, but not a documented same-chain cW* / stable pool there. diff --git a/docs/11-references/PMM_DEX_ROUTING_STATUS.md b/docs/11-references/PMM_DEX_ROUTING_STATUS.md index 18419759..0cd35ee5 100644 --- a/docs/11-references/PMM_DEX_ROUTING_STATUS.md +++ b/docs/11-references/PMM_DEX_ROUTING_STATUS.md @@ -3,6 +3,8 @@ **Last Updated:** 2026-04-03 **Purpose:** Single reference for DEX/DeFi and PMM liquidity pool routing — what is designed, deployed, and in use. +**GRU / FX policy:** public-chain cW\* PMM activity is **mesh execution** against policy and reference inputs, not a shadow FX oracle — [GRU_REFERENCE_PRIMACY_AND_MESH_EXECUTION_MODEL.md](../04-configuration/GRU_REFERENCE_PRIMACY_AND_MESH_EXECUTION_MODEL.md). + --- ## Executive summary (updated 2026-04-01) diff --git a/scripts/besu/collect-enodes-from-all-besu-nodes.sh b/scripts/besu/collect-enodes-from-all-besu-nodes.sh index cd2018ad..b1065491 100644 --- a/scripts/besu/collect-enodes-from-all-besu-nodes.sh +++ b/scripts/besu/collect-enodes-from-all-besu-nodes.sh @@ -1,8 +1,11 @@ #!/usr/bin/env bash -# Collect enode from each of the 32 Besu nodes and regenerate static-nodes.json and -# permissions-nodes.toml with 32 unique entries (canonical IPs). Fixes duplicate enode (2400/2401). +# Collect enode from each live Besu node and regenerate static-nodes.json and +# permissions-nodes.toml with unique entries (canonical IPs). # -# Usage: bash scripts/besu/collect-enodes-from-all-besu-nodes.sh [--dry-run] [--missing-only] +# Usage: +# bash scripts/besu/collect-enodes-from-all-besu-nodes.sh +# bash scripts/besu/collect-enodes-from-all-besu-nodes.sh --missing-only +# bash scripts/besu/collect-enodes-from-all-besu-nodes.sh --apply --vmid 2301 # --missing-only Only try to collect from VMIDs whose IP is not yet in static-nodes.json (fix failures only). # Output: config/besu-node-lists/static-nodes.json and permissions-nodes.toml (backups as *.bak). @@ -10,29 +13,63 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" -source "${PROJECT_ROOT}/config/ip-addresses.conf" 2>/dev/null || true +source "${PROJECT_ROOT}/scripts/lib/load-project-env.sh" -DRY_RUN=false +DRY_RUN=true MISSING_ONLY=false -for arg in "${@:-}"; do - [[ "$arg" == "--dry-run" ]] && DRY_RUN=true - [[ "$arg" == "--missing-only" ]] && MISSING_ONLY=true +TARGET_VMIDS=() + +usage() { + cat <<'EOF' +Usage: bash scripts/besu/collect-enodes-from-all-besu-nodes.sh [--apply] [--dry-run] [--missing-only] [--vmid ] + +Options: + --dry-run Print intended write actions only (default) + --apply Write regenerated static/perms files + --missing-only Only try VMIDs whose canonical IP is not already present + --vmid Limit collection to one VMID; repeatable +EOF +} + +while [[ $# -gt 0 ]]; do + case "$1" in + --dry-run) + DRY_RUN=true + shift + ;; + --apply) + DRY_RUN=false + shift + ;; + --missing-only) + MISSING_ONLY=true + shift + ;; + --vmid) + [[ $# -ge 2 ]] || { usage >&2; exit 2; } + TARGET_VMIDS+=("$2") + shift 2 + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Unknown argument: $1" >&2 + usage >&2 + exit 2 + ;; + esac done STATIC_FILE="${PROJECT_ROOT}/config/besu-node-lists/static-nodes.json" PERM_FILE="${PROJECT_ROOT}/config/besu-node-lists/permissions-nodes.toml" SSH_OPTS="-o ConnectTimeout=8 -o StrictHostKeyChecking=accept-new" -# All Besu VMIDs in stable order (validators, sentries, RPCs) -BESU_VMIDS=(1000 1001 1002 1003 1004 1500 1501 1502 1503 1504 1505 1506 1507 1508 2101 2102 2103 2201 2301 2303 2304 2305 2306 2400 2401 2402 2403 2500 2501 2502 2503 2504 2505) +# Live Besu VMIDs in stable order (validators, sentries, RPCs) +BESU_VMIDS=(1000 1001 1002 1003 1004 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 2101 2102 2103 2201 2301 2303 2304 2305 2306 2307 2308 2400 2401 2402 2403 2420 2430 2440 2460 2470 2480) -# VMID -> Proxmox host -declare -A HOST_BY_VMID -for v in 1000 1001 1002 1500 1501 1502 2101 2103 2500 2501 2502 2503 2504 2505; do HOST_BY_VMID[$v]="${PROXMOX_R630_01:-192.168.11.11}"; done -for v in 2201 2303 2305 2306 2307 2308 2401; do HOST_BY_VMID[$v]="${PROXMOX_R630_02:-192.168.11.12}"; done -for v in 1003 1004 1503 1504 1505 1506 1507 1508 2102 2301 2304 2400 2402 2403; do HOST_BY_VMID[$v]="${PROXMOX_R630_03:-192.168.11.13}"; done - -# VMID -> canonical IP (all 32) +# VMID -> canonical IP declare -A IP_BY_VMID IP_BY_VMID[1000]=192.168.11.100 IP_BY_VMID[1001]=192.168.11.101 @@ -57,20 +94,33 @@ IP_BY_VMID[2303]=192.168.11.233 IP_BY_VMID[2304]=192.168.11.234 IP_BY_VMID[2305]=192.168.11.235 IP_BY_VMID[2306]=192.168.11.236 +IP_BY_VMID[2307]=192.168.11.237 +IP_BY_VMID[2308]=192.168.11.238 IP_BY_VMID[2400]=192.168.11.240 IP_BY_VMID[2401]=192.168.11.241 IP_BY_VMID[2402]=192.168.11.242 IP_BY_VMID[2403]=192.168.11.243 -IP_BY_VMID[2500]=192.168.11.172 -IP_BY_VMID[2501]=192.168.11.173 -IP_BY_VMID[2502]=192.168.11.174 -IP_BY_VMID[2503]=192.168.11.246 -IP_BY_VMID[2504]=192.168.11.247 -IP_BY_VMID[2505]=192.168.11.248 +IP_BY_VMID[2420]=192.168.11.172 +IP_BY_VMID[2430]=192.168.11.173 +IP_BY_VMID[2440]=192.168.11.174 +IP_BY_VMID[2460]=192.168.11.246 +IP_BY_VMID[2470]=192.168.11.247 +IP_BY_VMID[2480]=192.168.11.248 + +selected_vmid() { + local vmid="$1" + [[ ${#TARGET_VMIDS[@]} -eq 0 ]] && return 0 + local wanted + for wanted in "${TARGET_VMIDS[@]}"; do + [[ "$vmid" == "$wanted" ]] && return 0 + done + return 1 +} get_enode() { local vmid="$1" - local host="${HOST_BY_VMID[$vmid]:-}" + local host + host="$(get_host_for_vmid "$vmid")" local ip="${IP_BY_VMID[$vmid]:-}" [[ -z "$host" || -z "$ip" ]] && return 1 # 1) admin_nodeInfo (RPC) @@ -95,9 +145,9 @@ get_enode() { return 0 fi fi - # 4) For 2501-2505 on r630-01: node may lack Besu binary; export key via helper 2500 (which has Besu) - if [[ "$host" == "${PROXMOX_R630_01:-192.168.11.11}" ]] && [[ "$vmid" =~ ^(2501|2502|2503|2504|2505)$ ]]; then - pubkey=$(ssh $SSH_OPTS "root@$host" "pct exec $vmid -- cat /data/besu/key 2>/dev/null | head -1 > /tmp/key${vmid}.$$ 2>/dev/null && pct push 2500 /tmp/key${vmid}.$$ /tmp/key${vmid} 2>/dev/null && pct exec 2500 -- /opt/besu/bin/besu public-key export --node-private-key-file=/tmp/key${vmid} 2>/dev/null; rm -f /tmp/key${vmid}.$$" 2>/dev/null | grep -oE '0x[0-9a-fA-F]{128}' | head -1 | sed 's/^0x//') + # 4) For edge RPCs without Besu binary, export key via helper 2420 on r630-01. + if [[ "$host" == "${PROXMOX_R630_01:-${PROXMOX_HOST_R630_01:-192.168.11.11}}" ]] && [[ "$vmid" =~ ^(2430|2440|2460|2470|2480)$ ]]; then + pubkey=$(ssh $SSH_OPTS "root@$host" "pct exec $vmid -- cat /data/besu/key 2>/dev/null | head -1 > /tmp/key${vmid}.$$ 2>/dev/null && pct push 2420 /tmp/key${vmid}.$$ /tmp/key${vmid} 2>/dev/null && pct exec 2420 -- /opt/besu/bin/besu public-key export --node-private-key-file=/tmp/key${vmid} 2>/dev/null; rm -f /tmp/key${vmid}.$$" 2>/dev/null | grep -oE '0x[0-9a-fA-F]{128}' | head -1 | sed 's/^0x//') if [[ -n "$pubkey" && ${#pubkey} -eq 128 ]]; then echo "enode://${pubkey}@${ip}:30303" return 0 @@ -125,6 +175,7 @@ done < <(jq -r '.[]' "${STATIC_FILE}.bak" 2>/dev/null) VMIDS_TO_TRY=() if $MISSING_ONLY; then for vmid in "${BESU_VMIDS[@]}"; do + selected_vmid "$vmid" || continue ip="${IP_BY_VMID[$vmid]:-}" [[ -z "$ip" ]] && continue [[ -z "${EXISTING_BY_IP[$ip]:-}" ]] && VMIDS_TO_TRY+=( "$vmid" ) @@ -132,8 +183,11 @@ if $MISSING_ONLY; then echo "Missing-only: collecting from ${#VMIDS_TO_TRY[@]} VMIDs not in current list (${VMIDS_TO_TRY[*]:-none})." [[ ${#VMIDS_TO_TRY[@]} -eq 0 ]] && echo "All 32 IPs already present. Nothing to collect." && exit 0 else - VMIDS_TO_TRY=( "${BESU_VMIDS[@]}" ) - echo "Collecting enodes from ${#BESU_VMIDS[@]} Besu nodes..." + for vmid in "${BESU_VMIDS[@]}"; do + selected_vmid "$vmid" || continue + VMIDS_TO_TRY+=( "$vmid" ) + done + echo "Collecting enodes from ${#VMIDS_TO_TRY[@]} Besu nodes..." fi declare -A COLLECTED_BY_VMID @@ -168,6 +222,7 @@ declare -a MISSING_VMIDS declare -A USED_NODE_ID for vmid in "${BESU_VMIDS[@]}"; do + selected_vmid "$vmid" || continue ip="${IP_BY_VMID[$vmid]:-}" [[ -z "$ip" ]] && continue enode="" diff --git a/scripts/besu/deploy-genesis-and-node-lists-to-rpcs.sh b/scripts/besu/deploy-genesis-and-node-lists-to-rpcs.sh index 3a9b2172..e0db5ee5 100644 --- a/scripts/besu/deploy-genesis-and-node-lists-to-rpcs.sh +++ b/scripts/besu/deploy-genesis-and-node-lists-to-rpcs.sh @@ -1,34 +1,86 @@ #!/usr/bin/env bash -# Deploy canonical genesis.json, static-nodes.json, permissions-nodes.toml to specified VMIDs -# and restart Besu. Usage: VMIDS="2401 2402 2403 2500 2501 2502 2503 2504 2505" bash scripts/besu/deploy-genesis-and-node-lists-to-rpcs.sh +# Deploy canonical genesis.json, static-nodes.json, permissions-nodes.toml to selected RPC VMIDs +# and restart Besu. +# Usage: +# bash scripts/besu/deploy-genesis-and-node-lists-to-rpcs.sh +# bash scripts/besu/deploy-genesis-and-node-lists-to-rpcs.sh --vmid 2401 +# bash scripts/besu/deploy-genesis-and-node-lists-to-rpcs.sh --apply --vmid 2401 set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" -source "${PROJECT_ROOT}/config/ip-addresses.conf" 2>/dev/null || true +source "${PROJECT_ROOT}/scripts/lib/load-project-env.sh" -VMIDS="${VMIDS:-2401 2402 2403 2500 2501 2502 2503 2504 2505}" +DRY_RUN=true +TARGET_VMIDS=() + +usage() { + cat <<'EOF' +Usage: bash scripts/besu/deploy-genesis-and-node-lists-to-rpcs.sh [--apply] [--dry-run] [--vmid ] + +Options: + --dry-run Print intended actions only (default) + --apply Deploy files and restart Besu on selected RPC nodes + --vmid Limit to one VMID; repeatable +EOF +} + +while [[ $# -gt 0 ]]; do + case "$1" in + --dry-run) + DRY_RUN=true + shift + ;; + --apply) + DRY_RUN=false + shift + ;; + --vmid) + [[ $# -ge 2 ]] || { usage >&2; exit 2; } + TARGET_VMIDS+=("$2") + shift 2 + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Unknown argument: $1" >&2 + usage >&2 + exit 2 + ;; + esac +done + +RPC_VMIDS=(2401 2402 2403 2420 2430 2440 2460 2470 2480) GENESIS="${PROJECT_ROOT}/smom-dbis-138-proxmox/config/genesis.json" STATIC="${PROJECT_ROOT}/config/besu-node-lists/static-nodes.json" PERMS="${PROJECT_ROOT}/config/besu-node-lists/permissions-nodes.toml" -declare -A HOST_BY_VMID -for v in 2500 2501 2502 2503 2504 2505; do HOST_BY_VMID[$v]="${PROXMOX_R630_01:-192.168.11.11}"; done -for v in 2401; do HOST_BY_VMID[$v]="${PROXMOX_R630_02:-192.168.11.12}"; done -for v in 2402 2403; do HOST_BY_VMID[$v]="${PROXMOX_ML110:-192.168.11.10}"; done - SSH_OPTS="-o ConnectTimeout=10 -o StrictHostKeyChecking=accept-new" [[ ! -f "$GENESIS" ]] && { echo "ERROR: $GENESIS not found"; exit 1; } [[ ! -f "$STATIC" ]] && { echo "ERROR: $STATIC not found"; exit 1; } [[ ! -f "$PERMS" ]] && { echo "ERROR: $PERMS not found"; exit 1; } -echo "Deploying genesis.json + static-nodes.json + permissions-nodes.toml to: $VMIDS" +selected_vmid() { + local vmid="$1" + [[ ${#TARGET_VMIDS[@]} -eq 0 ]] && return 0 + local wanted + for wanted in "${TARGET_VMIDS[@]}"; do + [[ "$vmid" == "$wanted" ]] && return 0 + done + return 1 +} + +echo "Deploying genesis.json + static-nodes.json + permissions-nodes.toml to selected RPC VMIDs" +if $DRY_RUN; then echo " [dry-run]"; fi echo "" -for vmid in $VMIDS; do - host="${HOST_BY_VMID[$vmid]:-}" +for vmid in "${RPC_VMIDS[@]}"; do + selected_vmid "$vmid" || continue + host="$(get_host_for_vmid "$vmid")" [[ -z "$host" ]] && { echo "VMID $vmid: no host"; continue; } running=$(ssh $SSH_OPTS "root@$host" "pct status $vmid 2>/dev/null | awk '{print \$2}'" 2>/dev/null || echo "") if [[ "$running" != "running" ]]; then @@ -36,6 +88,10 @@ for vmid in $VMIDS; do continue fi echo "--- VMID $vmid @ $host ---" + if $DRY_RUN; then + echo " [dry-run] would deploy files and restart Besu" + continue + fi scp -q $SSH_OPTS "$GENESIS" "$STATIC" "$PERMS" "root@${host}:/tmp/" || { echo " scp failed"; continue; } ssh $SSH_OPTS "root@$host" "pct exec $vmid -- mkdir -p /etc/besu" ssh $SSH_OPTS "root@$host" "pct push $vmid /tmp/genesis.json /etc/besu/genesis.json && pct push $vmid /tmp/static-nodes.json /etc/besu/static-nodes.json && pct push $vmid /tmp/permissions-nodes.toml /etc/besu/permissions-nodes.toml" diff --git a/scripts/besu/generate-node-keys-for-missing-vmids.sh b/scripts/besu/generate-node-keys-for-missing-vmids.sh index 40f2ddd2..d6b912f7 100644 --- a/scripts/besu/generate-node-keys-for-missing-vmids.sh +++ b/scripts/besu/generate-node-keys-for-missing-vmids.sh @@ -1,9 +1,12 @@ #!/usr/bin/env bash -# Generate Besu node key (/data/besu/key) only for VMIDs that are missing from +# Generate Besu node key (/data/besu/key) only for selected VMIDs that are missing from # static-nodes.json (no enode in the list yet). Key file = 64 hex chars (32 bytes). # After running, use: bash scripts/besu/collect-enodes-from-all-besu-nodes.sh --missing-only # -# Usage: bash scripts/besu/generate-node-keys-for-missing-vmids.sh [--dry-run] [--collect] [--force] +# Usage: +# bash scripts/besu/generate-node-keys-for-missing-vmids.sh +# bash scripts/besu/generate-node-keys-for-missing-vmids.sh --vmid 1505 +# bash scripts/besu/generate-node-keys-for-missing-vmids.sh --apply --vmid 1505 --collect # --collect Run collect-enodes-from-all-besu-nodes.sh --missing-only after generating keys. # --force Overwrite existing key file with new 64-hex key (fixes PEM/wrong-format keys). @@ -11,25 +14,65 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" -source "${PROJECT_ROOT}/config/ip-addresses.conf" 2>/dev/null || true +source "${PROJECT_ROOT}/scripts/lib/load-project-env.sh" -DRY_RUN=false +DRY_RUN=true RUN_COLLECT=false FORCE=false -for arg in "${@:-}"; do - [[ "$arg" == "--dry-run" ]] && DRY_RUN=true - [[ "$arg" == "--collect" ]] && RUN_COLLECT=true - [[ "$arg" == "--force" ]] && FORCE=true +TARGET_VMIDS=() + +usage() { + cat <<'EOF' +Usage: bash scripts/besu/generate-node-keys-for-missing-vmids.sh [--apply] [--dry-run] [--collect] [--force] [--vmid ] + +Options: + --dry-run Print intended actions only (default) + --apply Generate node keys on selected VMIDs + --collect Run collect-enodes-from-all-besu-nodes.sh --missing-only after generating keys + --force Overwrite existing key files + --vmid Limit to one VMID; repeatable +EOF +} + +while [[ $# -gt 0 ]]; do + case "$1" in + --dry-run) + DRY_RUN=true + shift + ;; + --apply) + DRY_RUN=false + shift + ;; + --collect) + RUN_COLLECT=true + shift + ;; + --force) + FORCE=true + shift + ;; + --vmid) + [[ $# -ge 2 ]] || { usage >&2; exit 2; } + TARGET_VMIDS+=("$2") + shift 2 + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Unknown argument: $1" >&2 + usage >&2 + exit 2 + ;; + esac done STATIC_FILE="${PROJECT_ROOT}/config/besu-node-lists/static-nodes.json" SSH_OPTS="-o ConnectTimeout=8 -o StrictHostKeyChecking=accept-new" -BESU_VMIDS=(1000 1001 1002 1003 1004 1500 1501 1502 1503 1504 1505 1506 1507 1508 2101 2102 2201 2301 2303 2304 2305 2306 2400 2401 2402 2403 2500 2501 2502 2503 2504 2505) -declare -A HOST_BY_VMID -for v in 1000 1001 1002 1500 1501 1502 2101 2500 2501 2502 2503 2504 2505; do HOST_BY_VMID[$v]="${PROXMOX_R630_01:-192.168.11.11}"; done -for v in 2201 2303 2401; do HOST_BY_VMID[$v]="${PROXMOX_R630_02:-192.168.11.12}"; done -for v in 1003 1004 1503 1504 1505 1506 1507 1508 2102 2301 2304 2305 2306 2400 2402 2403; do HOST_BY_VMID[$v]="${PROXMOX_ML110:-192.168.11.10}"; done +BESU_VMIDS=(1000 1001 1002 1003 1004 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 2101 2102 2103 2201 2301 2303 2304 2305 2306 2307 2308 2400 2401 2402 2403 2420 2430 2440 2460 2470 2480) declare -A IP_BY_VMID IP_BY_VMID[1000]=192.168.11.100 IP_BY_VMID[1001]=192.168.11.101 @@ -45,24 +88,39 @@ IP_BY_VMID[1505]=192.168.11.213 IP_BY_VMID[1506]=192.168.11.214 IP_BY_VMID[1507]=192.168.11.244 IP_BY_VMID[1508]=192.168.11.245 +IP_BY_VMID[1509]=192.168.11.219 +IP_BY_VMID[1510]=192.168.11.220 IP_BY_VMID[2101]=192.168.11.211 IP_BY_VMID[2102]=192.168.11.212 +IP_BY_VMID[2103]=192.168.11.217 IP_BY_VMID[2201]=192.168.11.221 IP_BY_VMID[2301]=192.168.11.232 IP_BY_VMID[2303]=192.168.11.233 IP_BY_VMID[2304]=192.168.11.234 IP_BY_VMID[2305]=192.168.11.235 IP_BY_VMID[2306]=192.168.11.236 +IP_BY_VMID[2307]=192.168.11.237 +IP_BY_VMID[2308]=192.168.11.238 IP_BY_VMID[2400]=192.168.11.240 IP_BY_VMID[2401]=192.168.11.241 IP_BY_VMID[2402]=192.168.11.242 IP_BY_VMID[2403]=192.168.11.243 -IP_BY_VMID[2500]=192.168.11.172 -IP_BY_VMID[2501]=192.168.11.173 -IP_BY_VMID[2502]=192.168.11.174 -IP_BY_VMID[2503]=192.168.11.246 -IP_BY_VMID[2504]=192.168.11.247 -IP_BY_VMID[2505]=192.168.11.248 +IP_BY_VMID[2420]=192.168.11.172 +IP_BY_VMID[2430]=192.168.11.173 +IP_BY_VMID[2440]=192.168.11.174 +IP_BY_VMID[2460]=192.168.11.246 +IP_BY_VMID[2470]=192.168.11.247 +IP_BY_VMID[2480]=192.168.11.248 + +selected_vmid() { + local vmid="$1" + [[ ${#TARGET_VMIDS[@]} -eq 0 ]] && return 0 + local wanted + for wanted in "${TARGET_VMIDS[@]}"; do + [[ "$vmid" == "$wanted" ]] && return 0 + done + return 1 +} # Which VMIDs are missing (IP not in current static-nodes.json) declare -A EXISTING_IP @@ -74,6 +132,7 @@ done < <(jq -r '.[]' "$STATIC_FILE" 2>/dev/null) VMIDS_TO_FIX=() for vmid in "${BESU_VMIDS[@]}"; do + selected_vmid "$vmid" || continue ip="${IP_BY_VMID[$vmid]:-}" [[ -z "$ip" ]] && continue [[ -z "${EXISTING_IP[$ip]:-}" ]] && VMIDS_TO_FIX+=( "$vmid" ) @@ -88,7 +147,7 @@ echo "Generating node keys for ${#VMIDS_TO_FIX[@]} VMIDs (missing from list): ${ echo "" for vmid in "${VMIDS_TO_FIX[@]}"; do - host="${HOST_BY_VMID[$vmid]:-}" + host="$(get_host_for_vmid "$vmid")" ip="${IP_BY_VMID[$vmid]:-}" [[ -z "$host" ]] && echo " $vmid: no host" && continue if $DRY_RUN; then @@ -125,5 +184,9 @@ done echo "" if $RUN_COLLECT && ! $DRY_RUN; then echo "Running collect-enodes-from-all-besu-nodes.sh --missing-only..." - bash "${SCRIPT_DIR}/collect-enodes-from-all-besu-nodes.sh" --missing-only + collect_args=(--apply --missing-only) + for vmid in "${TARGET_VMIDS[@]}"; do + collect_args+=(--vmid "$vmid") + done + bash "${SCRIPT_DIR}/collect-enodes-from-all-besu-nodes.sh" "${collect_args[@]}" fi diff --git a/scripts/besu/install-besu-permanent-on-missing-nodes.sh b/scripts/besu/install-besu-permanent-on-missing-nodes.sh index 063aa42b..53ab14cb 100644 --- a/scripts/besu/install-besu-permanent-on-missing-nodes.sh +++ b/scripts/besu/install-besu-permanent-on-missing-nodes.sh @@ -1,17 +1,58 @@ #!/usr/bin/env bash -# Install Besu permanently on nodes that don't have /opt/besu/bin/besu (1505-1508, 2420-2480). +# Install Besu permanently on selected nodes that don't have /opt/besu/bin/besu (1505-1508, 2420-2480). # Uses install-besu-in-ct-standalone.sh inside each CT; deploys config, genesis, node lists; enables and starts service. # -# Usage: bash scripts/besu/install-besu-permanent-on-missing-nodes.sh [--dry-run] +# Usage: +# bash scripts/besu/install-besu-permanent-on-missing-nodes.sh +# bash scripts/besu/install-besu-permanent-on-missing-nodes.sh --vmid 1505 +# bash scripts/besu/install-besu-permanent-on-missing-nodes.sh --apply --vmid 1505 set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" -source "${PROJECT_ROOT}/config/ip-addresses.conf" 2>/dev/null || true +source "${PROJECT_ROOT}/scripts/lib/load-project-env.sh" -DRY_RUN=false -[[ "${1:-}" == "--dry-run" ]] && DRY_RUN=true +DRY_RUN=true +TARGET_VMIDS=() + +usage() { + cat <<'EOF' +Usage: bash scripts/besu/install-besu-permanent-on-missing-nodes.sh [--apply] [--dry-run] [--vmid ] + +Options: + --dry-run Print intended actions only (default) + --apply Install Besu on selected nodes + --vmid Limit to one VMID; repeatable +EOF +} + +while [[ $# -gt 0 ]]; do + case "$1" in + --dry-run) + DRY_RUN=true + shift + ;; + --apply) + DRY_RUN=false + shift + ;; + --vmid) + [[ $# -ge 2 ]] || { usage >&2; exit 2; } + TARGET_VMIDS+=("$2") + shift 2 + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Unknown argument: $1" >&2 + usage >&2 + exit 2 + ;; + esac +done SSH_OPTS="-o ConnectTimeout=15 -o StrictHostKeyChecking=accept-new" BESU_VERSION="${BESU_VERSION:-23.10.3}" @@ -22,9 +63,6 @@ PERMS_SRC="${PROJECT_ROOT}/config/besu-node-lists/permissions-nodes.toml" # VMIDs that may lack Besu (sentries 1505-1508 on ml110; edge RPC 2420-2480 on r630-01) SENTRY_VMIDS=(1505 1506 1507 1508) RPC_VMIDS=(2420 2430 2440 2460 2470 2480) -declare -A HOST_BY_VMID -for v in 1505 1506 1507 1508; do HOST_BY_VMID[$v]="${PROXMOX_ML110:-192.168.11.10}"; done -for v in 2420 2430 2440 2460 2470 2480; do HOST_BY_VMID[$v]="${PROXMOX_R630_01:-192.168.11.11}"; done declare -A IP_BY_VMID IP_BY_VMID[1505]=192.168.11.213 IP_BY_VMID[1506]=192.168.11.214 @@ -41,8 +79,20 @@ IP_BY_VMID[2480]=192.168.11.248 [[ ! -f "$STATIC_SRC" ]] && { echo "ERROR: $STATIC_SRC not found"; exit 1; } [[ ! -f "$PERMS_SRC" ]] && { echo "ERROR: $PERMS_SRC not found"; exit 1; } +selected_vmid() { + local vmid="$1" + [[ ${#TARGET_VMIDS[@]} -eq 0 ]] && return 0 + local wanted + for wanted in "${TARGET_VMIDS[@]}"; do + [[ "$vmid" == "$wanted" ]] && return 0 + done + return 1 +} + install_sentry() { - local vmid=$1 host=${HOST_BY_VMID[$vmid]} ip=${IP_BY_VMID[$vmid]} + local vmid=$1 host ip + host="$(get_host_for_vmid "$vmid")" + ip=${IP_BY_VMID[$vmid]} echo "--- VMID $vmid (sentry @ $ip) ---" if $DRY_RUN; then echo " [dry-run] would install Besu sentry"; return 0; fi ssh $SSH_OPTS "root@$host" "pct exec $vmid -- rm -rf /opt/besu 2>/dev/null; true" @@ -61,7 +111,9 @@ install_sentry() { } install_rpc() { - local vmid=$1 host=${HOST_BY_VMID[$vmid]} ip=${IP_BY_VMID[$vmid]} + local vmid=$1 host ip + host="$(get_host_for_vmid "$vmid")" + ip=${IP_BY_VMID[$vmid]} echo "--- VMID $vmid (RPC @ $ip) ---" if $DRY_RUN; then echo " [dry-run] would install Besu RPC"; return 0; fi if ! ssh $SSH_OPTS "root@$host" "pct exec $vmid -- bash -c 'touch /tmp/.w && rm -f /tmp/.w'" 2>/dev/null; then @@ -138,7 +190,8 @@ echo "Installing Besu permanently on nodes missing /opt/besu/bin/besu (1505-1508 echo "" for vmid in "${SENTRY_VMIDS[@]}"; do - host="${HOST_BY_VMID[$vmid]:-}" + selected_vmid "$vmid" || continue + host="$(get_host_for_vmid "$vmid")" has_besu=$(ssh $SSH_OPTS "root@$host" "pct exec $vmid -- test -x /opt/besu/bin/besu 2>/dev/null" && echo yes || echo no) if [[ "$has_besu" == yes ]]; then echo "VMID $vmid: Besu already present (skip)" @@ -148,7 +201,8 @@ for vmid in "${SENTRY_VMIDS[@]}"; do done for vmid in "${RPC_VMIDS[@]}"; do - host="${HOST_BY_VMID[$vmid]:-}" + selected_vmid "$vmid" || continue + host="$(get_host_for_vmid "$vmid")" has_besu=$(ssh $SSH_OPTS "root@$host" "pct exec $vmid -- test -x /opt/besu/bin/besu 2>/dev/null" && echo yes || echo no) if [[ "$has_besu" == yes ]]; then echo "VMID $vmid: Besu already present (skip)" @@ -158,6 +212,6 @@ for vmid in "${RPC_VMIDS[@]}"; do done echo "" -echo "Done. Verify: bash scripts/besu/restart-besu-reload-node-lists.sh (optional); then check block production on RPCs." +echo "Done. Verify: bash scripts/besu/restart-besu-reload-node-lists.sh --apply [--vmid ] (optional); then check block production on RPCs." rm -f /tmp/config-sentry.toml /tmp/besu.service /tmp/config.toml 2>/dev/null || true for v in 2420 2430 2440 2460 2470 2480; do rm -f /tmp/config-rpc-${v}.toml 2>/dev/null; done diff --git a/scripts/besu/match-enodes-to-rpcs.sh b/scripts/besu/match-enodes-to-rpcs.sh old mode 100755 new mode 100644 index ddafd272..a4b0b334 --- a/scripts/besu/match-enodes-to-rpcs.sh +++ b/scripts/besu/match-enodes-to-rpcs.sh @@ -1,21 +1,16 @@ #!/usr/bin/env bash +# Match enodes from the current static-nodes allowlist to live RPC nodes. +# +# Usage: +# bash scripts/besu/match-enodes-to-rpcs.sh +# bash scripts/besu/match-enodes-to-rpcs.sh --vmid 2301 + set -euo pipefail -# Load IP configuration -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" -source "${PROJECT_ROOT}/config/ip-addresses.conf" 2>/dev/null || true - - - -# Match Enodes from Allowlist to RPC Nodes - -set -e - SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" +source "${PROJECT_ROOT}/scripts/lib/load-project-env.sh" -# Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' @@ -24,87 +19,128 @@ CYAN='\033[0;36m' NC='\033[0m' log_info() { echo -e "${BLUE}[INFO]${NC} $1"; } -log_success() { echo -e "${GREEN}[✓]${NC} $1"; } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } -log_error() { echo -e "${RED}[ERROR]${NC} $1"; } log_section() { echo -e "\n${CYAN}=== $1 ===${NC}"; } -# RPC node mapping (VMID:IP:Hostname) +TARGET_VMIDS=() + +usage() { + cat <<'EOF' +Usage: bash scripts/besu/match-enodes-to-rpcs.sh [--vmid ] + +Options: + --vmid Limit to one VMID; repeatable +EOF +} + +while [[ $# -gt 0 ]]; do + case "$1" in + --vmid) + [[ $# -ge 2 ]] || { usage >&2; exit 2; } + TARGET_VMIDS+=("$2") + shift 2 + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Unknown argument: $1" >&2 + usage >&2 + exit 2 + ;; + esac +done + +selected_vmid() { + local vmid="$1" + [[ ${#TARGET_VMIDS[@]} -eq 0 ]] && return 0 + local wanted + for wanted in "${TARGET_VMIDS[@]}"; do + [[ "$vmid" == "$wanted" ]] && return 0 + done + return 1 +} + declare -A RPC_NODES=( - ["2101"]="${RPC_CORE_1:-${IP_SERVICE_21:-${IP_SERVICE_21:-${IP_SERVICE_21:-${IP_SERVICE_21:-${IP_SERVICE_21:-192.168.11.21}}}}}1}:besu-rpc-core-1" - ["2201"]="${RPC_PUBLIC_1:-${RPC_PUBLIC_1:-192.168.11.221}}:besu-rpc-public-1" - ["2301"]="${RPC_PRIVATE_1:-${RPC_PRIVATE_1:-192.168.11.232}}:besu-rpc-private-1" - ["2303"]="${RPC_NODE_233:-${RPC_NODE_233:-${RPC_NODE_233:-${RPC_NODE_233:-${RPC_NODE_233:-${RPC_NODE_233:-${RPC_NODE_233:-192.168.11.233}}}}}}}:besu-rpc-ali-0x8a" - ["2304"]="${RPC_NODE_234:-${RPC_NODE_234:-${RPC_NODE_234:-${RPC_NODE_234:-${RPC_NODE_234:-${RPC_NODE_234:-${RPC_NODE_234:-192.168.11.234}}}}}}}:besu-rpc-ali-0x1" - ["2305"]="${RPC_NODE_235:-${RPC_NODE_235:-${RPC_NODE_235:-${RPC_NODE_235:-${RPC_NODE_235:-${RPC_NODE_235:-${RPC_NODE_235:-192.168.11.235}}}}}}}:besu-rpc-luis-0x8a" - ["2306"]="${RPC_NODE_236:-${RPC_NODE_236:-${RPC_NODE_236:-${RPC_NODE_236:-${RPC_NODE_236:-${RPC_NODE_236:-${RPC_NODE_236:-192.168.11.236}}}}}}}:besu-rpc-luis-0x1" - ["2307"]="${IP_RPC_237:-${IP_RPC_237:-${IP_RPC_237:-192.168.11.237}}}:besu-rpc-putu-0x8a" - ["2308"]="${IP_RPC_238:-${IP_RPC_238:-${IP_RPC_238:-192.168.11.238}}}:besu-rpc-putu-0x1" - ["2400"]="${RPC_THIRDWEB_PRIMARY:-${RPC_THIRDWEB_PRIMARY:-192.168.11.240}}:thirdweb-rpc-1" - ["2401"]="${RPC_THIRDWEB_1:-${RPC_THIRDWEB_1:-${RPC_THIRDWEB_1:-${RPC_THIRDWEB_1:-${RPC_THIRDWEB_1:-${RPC_THIRDWEB_1:-${RPC_THIRDWEB_1:-192.168.11.241}}}}}}}:besu-rpc-thirdweb-0x8a-1" - ["2402"]="${RPC_THIRDWEB_2:-${RPC_THIRDWEB_2:-${RPC_THIRDWEB_2:-${RPC_THIRDWEB_2:-${RPC_THIRDWEB_2:-${RPC_THIRDWEB_2:-${RPC_THIRDWEB_2:-192.168.11.242}}}}}}}:besu-rpc-thirdweb-0x8a-2" - ["2403"]="${RPC_THIRDWEB_3:-${RPC_THIRDWEB_3:-${RPC_THIRDWEB_3:-192.168.11.243}}}:besu-rpc-thirdweb-0x8a-3" + ["2101"]="${RPC_CORE_1:-192.168.11.211}:besu-rpc-core-1" + ["2102"]="${RPC_CORE_2:-192.168.11.212}:besu-rpc-core-2" + ["2103"]="${RPC_THIRDWEB_ADMIN_CORE:-192.168.11.217}:besu-rpc-core-thirdweb" + ["2201"]="${RPC_PUBLIC_1:-192.168.11.221}:besu-rpc-public-1" + ["2301"]="${RPC_PRIVATE_1:-192.168.11.232}:besu-rpc-private-1" + ["2303"]="192.168.11.233:besu-rpc-ali-0x8a" + ["2304"]="192.168.11.234:besu-rpc-ali-0x1" + ["2305"]="192.168.11.235:besu-rpc-luis-0x8a" + ["2306"]="192.168.11.236:besu-rpc-luis-0x1" + ["2307"]="192.168.11.237:besu-rpc-putu-0x8a" + ["2308"]="192.168.11.238:besu-rpc-putu-0x1" + ["2400"]="192.168.11.240:thirdweb-rpc-1" + ["2401"]="192.168.11.241:besu-rpc-thirdweb-0x8a-1" + ["2402"]="192.168.11.242:besu-rpc-thirdweb-0x8a-2" + ["2403"]="192.168.11.243:besu-rpc-thirdweb-0x8a-3" + ["2420"]="192.168.11.172:besu-rpc-alltra-1" + ["2430"]="192.168.11.173:besu-rpc-alltra-2" + ["2440"]="192.168.11.174:besu-rpc-alltra-3" + ["2460"]="192.168.11.246:besu-rpc-hybx-1" + ["2470"]="192.168.11.247:besu-rpc-hybx-2" + ["2480"]="192.168.11.248:besu-rpc-hybx-3" ) -# Enodes from allowlist (extract IPs) -declare -A ALLOWLIST_ENODES=( - ["${RPC_CORE_1:-${IP_SERVICE_21:-${IP_SERVICE_21:-${IP_SERVICE_21:-${IP_SERVICE_21:-${IP_SERVICE_21:-192.168.11.21}}}}}1}"]="enode://6cdc892fa09afa2b05c21cc9a1193a86cf0d195ce81b02a270d8bb987f78ca98ad90d907670796c90fc6e4eaf3b4cae6c0c15871e2564de063beceb4bbfc6532@${RPC_CORE_1:-${IP_SERVICE_21:-${IP_SERVICE_21:-${IP_SERVICE_21:-${IP_SERVICE_21:-${IP_SERVICE_21:-192.168.11.21}}}}}1}:30303" - ["${RPC_PUBLIC_1:-${RPC_PUBLIC_1:-192.168.11.221}}"]="enode://07daf3d64079faa3982bc8be7aa86c24ef21eca4565aae4a7fd963c55c728de0639d80663834634edf113b9f047d690232ae23423c64979961db4b6449aa6dfd@${RPC_PUBLIC_1:-${RPC_PUBLIC_1:-192.168.11.221}}:30303" - ["${RPC_PRIVATE_1:-${RPC_PRIVATE_1:-192.168.11.232}}"]="enode://83eb8c172034afd72846740921f748c77780c3cc0cea45604348ba859bc3a47187e24e5fad7f74e5fe353e86fd35ab7c37f02cfbb8299a850a190b40968bd8e2@${RPC_PRIVATE_1:-${RPC_PRIVATE_1:-192.168.11.232}}:30303" - ["${RPC_NODE_233:-${RPC_NODE_233:-${RPC_NODE_233:-${RPC_NODE_233:-${RPC_NODE_233:-${RPC_NODE_233:-${RPC_NODE_233:-192.168.11.233}}}}}}}"]="enode://688f271d94c7995600ae36d25aa2fb92fea0c52e50e86c598be8966515458c1408b67fba76e1f771073e4774a6e399588443da63394ea25d56e6ca36f2288e00@${RPC_NODE_233:-${RPC_NODE_233:-${RPC_NODE_233:-${RPC_NODE_233:-${RPC_NODE_233:-${RPC_NODE_233:-${RPC_NODE_233:-192.168.11.233}}}}}}}:30303" - ["${RPC_NODE_234:-${RPC_NODE_234:-${RPC_NODE_234:-${RPC_NODE_234:-${RPC_NODE_234:-${RPC_NODE_234:-${RPC_NODE_234:-192.168.11.234}}}}}}}"]="enode://4dc4b9f8cffbc53349f6535ab9aa7785cbc0ae92928dcf4ef6f90638ace9fc69ff7d19c49a8bda54f78a000579c557ef25fce3c971c6ab0026b6e70c8e6e5cac@${RPC_NODE_234:-${RPC_NODE_234:-${RPC_NODE_234:-${RPC_NODE_234:-${RPC_NODE_234:-${RPC_NODE_234:-${RPC_NODE_234:-192.168.11.234}}}}}}}:30303" - ["${RPC_NODE_235:-${RPC_NODE_235:-${RPC_NODE_235:-${RPC_NODE_235:-${RPC_NODE_235:-${RPC_NODE_235:-${RPC_NODE_235:-192.168.11.235}}}}}}}"]="enode://2de9fc2be46c2cedce182af65ac1f5fc5ed258d21cdf0ac2687a16618382159dae1f730650e6730cf7fc5dccb6b97bffd20e271e3eb4df5a69f38a8c4cba91b5@${RPC_NODE_235:-${RPC_NODE_235:-${RPC_NODE_235:-${RPC_NODE_235:-${RPC_NODE_235:-${RPC_NODE_235:-${RPC_NODE_235:-192.168.11.235}}}}}}}:30303" - ["${RPC_NODE_236:-${RPC_NODE_236:-${RPC_NODE_236:-${RPC_NODE_236:-${RPC_NODE_236:-${RPC_NODE_236:-${RPC_NODE_236:-192.168.11.236}}}}}}}"]="enode://38bd43b934feaaccb978917c66b0abbf9b62e39bce6064a6d3ec557f61e13b75e293cbb2ab382278adda5ce51f451528c7c37d991255a0c31e9578b85fc1dd5a@${RPC_NODE_236:-${RPC_NODE_236:-${RPC_NODE_236:-${RPC_NODE_236:-${RPC_NODE_236:-${RPC_NODE_236:-${RPC_NODE_236:-192.168.11.236}}}}}}}:30303" - ["${IP_RPC_237:-${IP_RPC_237:-${IP_RPC_237:-192.168.11.237}}}"]="enode://f7edb80de20089cb0b3a28b03e0491fafa1c9eb9a0344dadf343757ee2a44b577a861514fd7747a86f631c9e34519aef25a5f8996f20bc8dd460cd2bdc1bd490@${IP_RPC_237:-${IP_RPC_237:-${IP_RPC_237:-192.168.11.237}}}:30303" - ["${IP_RPC_238:-${IP_RPC_238:-${IP_RPC_238:-192.168.11.238}}}"]="enode://4e2d4e94909813b7145e0e9cd7e56724f64ba91dd7dca0e70bd70742f930450cf57311f2c220cfe24a20e9f668a8e170755d626f84660aa1fbea85f75557eb8d@${IP_RPC_238:-${IP_RPC_238:-${IP_RPC_238:-192.168.11.238}}}:30303" - ["${RPC_THIRDWEB_1:-${RPC_THIRDWEB_1:-${RPC_THIRDWEB_1:-${RPC_THIRDWEB_1:-${RPC_THIRDWEB_1:-${RPC_THIRDWEB_1:-${RPC_THIRDWEB_1:-192.168.11.241}}}}}}}"]="enode://38e138ea5a4b0b244e4484b5c327631b5d3c849dcb188ff3d9ff0a8b6ad7edb738303a1a948888c269aa7555e5ff47d75b7b63dbd579d05580b5442b3fa0ebfc@${RPC_THIRDWEB_1:-${RPC_THIRDWEB_1:-${RPC_THIRDWEB_1:-${RPC_THIRDWEB_1:-${RPC_THIRDWEB_1:-${RPC_THIRDWEB_1:-${RPC_THIRDWEB_1:-192.168.11.241}}}}}}}:30303" -) - -log_section "Matching Enodes to RPC Nodes" +ALLOWLIST_FILE="${PROJECT_ROOT}/config/besu-node-lists/static-nodes.json" +declare -A ALLOWLIST_ENODES +if [[ -f "$ALLOWLIST_FILE" ]]; then + while IFS= read -r enode; do + [[ -z "$enode" ]] && continue + ip=$(echo "$enode" | sed -n 's|enode://[a-fA-F0-9]*@\([0-9.]*\):.*|\1|p') + [[ -n "$ip" ]] && ALLOWLIST_ENODES["$ip"]="$enode" + done < <(jq -r '.[]' "$ALLOWLIST_FILE" 2>/dev/null) +fi +log_section "Matching Enodes To RPC Nodes" echo "" -printf "%-8s %-18s %-40s %-20s\n" "VMID" "IP Address" "Hostname" "Status" -echo "────────────────────────────────────────────────────────────────────────────────────────────────────" +printf "%-8s %-18s %-36s %-12s\n" "VMID" "IP Address" "Hostname" "Status" +echo "--------------------------------------------------------------------------------" MATCHED=0 MISSING=0 -for vmid in "${!RPC_NODES[@]}"; do - IFS=':' read -r ip hostname <<< "${RPC_NODES[$vmid]}" - - if [ -n "${ALLOWLIST_ENODES[$ip]}" ]; then - printf "%-8s %-18s %-40s %-20s\n" "$vmid" "$ip" "$hostname" "✅ MATCHED" - ((MATCHED++)) - else - printf "%-8s %-18s %-40s %-20s\n" "$vmid" "$ip" "$hostname" "❌ MISSING" - ((MISSING++)) - fi +for vmid in $(printf "%s\n" "${!RPC_NODES[@]}" | sort -n); do + selected_vmid "$vmid" || continue + IFS=':' read -r ip hostname <<< "${RPC_NODES[$vmid]}" + if [[ -n "${ALLOWLIST_ENODES[$ip]:-}" ]]; then + printf "%-8s %-18s %-36s %-12s\n" "$vmid" "$ip" "$hostname" "MATCHED" + ((MATCHED++)) || true + else + printf "%-8s %-18s %-36s %-12s\n" "$vmid" "$ip" "$hostname" "MISSING" + ((MISSING++)) || true + fi done +total=$((MATCHED + MISSING)) echo "" log_section "Summary" +log_info "Matched: $MATCHED/$total RPC nodes" +log_info "Missing: $MISSING/$total RPC nodes" -log_info "Matched: $MATCHED/13 RPC nodes" -log_info "Missing: $MISSING/13 RPC nodes" - -if [ $MISSING -gt 0 ]; then - log_warn "Missing enodes:" - for vmid in "${!RPC_NODES[@]}"; do - IFS=':' read -r ip hostname <<< "${RPC_NODES[$vmid]}" - if [ -z "${ALLOWLIST_ENODES[$ip]}" ]; then - log_warn " • $vmid ($ip) - $hostname" - fi - done +if [[ "$MISSING" -gt 0 ]]; then + echo "" + log_warn "Missing enodes:" + for vmid in $(printf "%s\n" "${!RPC_NODES[@]}" | sort -n); do + selected_vmid "$vmid" || continue + IFS=':' read -r ip hostname <<< "${RPC_NODES[$vmid]}" + [[ -n "${ALLOWLIST_ENODES[$ip]:-}" ]] && continue + log_warn " $vmid ($ip) - $hostname" + done fi echo "" -log_section "Complete Enode Mapping" - -for vmid in "${!RPC_NODES[@]}"; do - IFS=':' read -r ip hostname <<< "${RPC_NODES[$vmid]}" - if [ -n "${ALLOWLIST_ENODES[$ip]}" ]; then - echo "VMID $vmid ($hostname) - $ip:" - echo " ${ALLOWLIST_ENODES[$ip]}" - echo "" - fi +log_section "Matched Enodes" +for vmid in $(printf "%s\n" "${!RPC_NODES[@]}" | sort -n); do + selected_vmid "$vmid" || continue + IFS=':' read -r ip hostname <<< "${RPC_NODES[$vmid]}" + enode="${ALLOWLIST_ENODES[$ip]:-}" + [[ -z "$enode" ]] && continue + echo "VMID $vmid ($hostname) - $ip:" + echo " $enode" + echo "" done diff --git a/scripts/check-besu-version-all-nodes.sh b/scripts/check-besu-version-all-nodes.sh index db0bfbc4..ab98c145 100755 --- a/scripts/check-besu-version-all-nodes.sh +++ b/scripts/check-besu-version-all-nodes.sh @@ -1,27 +1,56 @@ #!/usr/bin/env bash -# Confirm Besu version >= 24.1.0 on all nodes (required for EIP-7702 / Cancun) -# Usage: PROXMOX_HOST=${PROXMOX_HOST_ML110:-192.168.11.10} ./scripts/check-besu-version-all-nodes.sh +# Confirm Besu version >= 24.1.0 on selected nodes (required for EIP-7702 / Cancun) +# Usage: +# bash scripts/check-besu-version-all-nodes.sh +# bash scripts/check-besu-version-all-nodes.sh --vmid 2301 set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" - -# Optional: load IP config for PROXMOX_HOST_ML110 etc. -if [ -f "$PROJECT_ROOT/config/ip-addresses.conf" ]; then - # shellcheck source=../config/ip-addresses.conf - source "$PROJECT_ROOT/config/ip-addresses.conf" -fi - -PROXMOX_HOST="${PROXMOX_HOST:-${PROXMOX_HOST_ML110:-192.168.11.10}}" +source "${PROJECT_ROOT}/scripts/lib/load-project-env.sh" MIN_VERSION="24.1.0" +TARGET_VMIDS=() -# All known Besu node VMIDs (validators, sentries, RPC). Override with BESU_VMIDS="2101 2400 2401 2402" for quick check. -if [ -n "${BESU_VMIDS:-}" ]; then - read -ra BESU_VMIDS <<< "$BESU_VMIDS" -else - BESU_VMIDS=(1000 1001 1002 1003 1004 1500 1501 1502 1503 2101 2201 2301 2303 2304 2305 2306 2307 2308 2400 2401 2402 2403) -fi +usage() { + cat <<'EOF' +Usage: bash scripts/check-besu-version-all-nodes.sh [--vmid ] + +Options: + --vmid Limit to one VMID; repeatable +EOF +} + +while [[ $# -gt 0 ]]; do + case "$1" in + --vmid) + [[ $# -ge 2 ]] || { usage >&2; exit 2; } + TARGET_VMIDS+=("$2") + shift 2 + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Unknown argument: $1" >&2 + usage >&2 + exit 2 + ;; + esac +done + +BESU_VMIDS=(1000 1001 1002 1003 1004 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 2101 2102 2103 2201 2301 2303 2304 2305 2306 2307 2308 2400 2401 2402 2403 2420 2430 2440 2460 2470 2480) + +selected_vmid() { + local vmid="$1" + [[ ${#TARGET_VMIDS[@]} -eq 0 ]] && return 0 + local wanted + for wanted in "${TARGET_VMIDS[@]}"; do + [[ "$vmid" == "$wanted" ]] && return 0 + done + return 1 +} RED='\033[0;31m' GREEN='\033[0;32m' @@ -85,7 +114,7 @@ is_running() { } echo "" -log_info "Besu version check (>= ${MIN_VERSION}) on Proxmox host: $PROXMOX_HOST" +log_info "Besu version check (>= ${MIN_VERSION}) on selected nodes" log_info "EIP-7702 / Cancun requires Besu >= 24.1.0" echo "" @@ -96,13 +125,15 @@ declare -a FAILED_VMIDS declare -a FAILED_VERSIONS for vmid in "${BESU_VMIDS[@]}"; do - if ! is_running "$vmid" "$PROXMOX_HOST"; then + selected_vmid "$vmid" || continue + host="$(get_host_for_vmid "$vmid")" + if ! is_running "$vmid" "$host"; then printf " VMID %-5s %-12s %s\n" "$vmid" "—" "(container not running)" ((SKIP++)) || true continue fi - version=$(get_besu_version "$vmid" "$PROXMOX_HOST") + version=$(get_besu_version "$vmid" "$host") if [ -z "$version" ]; then printf " VMID %-5s %-12s " "$vmid" "—" diff --git a/scripts/clear-blockchain-database.sh b/scripts/clear-blockchain-database.sh index 6be35dfb..fbccfad4 100644 --- a/scripts/clear-blockchain-database.sh +++ b/scripts/clear-blockchain-database.sh @@ -1,10 +1,16 @@ #!/usr/bin/env bash -# Clear entire Besu blockchain database (NUCLEAR OPTION) -# This will require full re-sync from genesis -# Usage: ./clear-blockchain-database.sh +# Clear selected Besu blockchain databases (NUCLEAR OPTION) +# This will require full re-sync from genesis. +# Usage: +# ./clear-blockchain-database.sh --vmid 2101 +# ./clear-blockchain-database.sh --apply --vmid 2101 set -euo pipefail +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +source "${PROJECT_ROOT}/scripts/lib/load-project-env.sh" + # Colors RED='\033[0;31m' GREEN='\033[0;32m' @@ -23,6 +29,44 @@ if ! command -v pct &>/dev/null; then exit 1 fi +APPLY=false +TARGET_VMIDS=() + +usage() { + cat <<'EOF' +Usage: ./clear-blockchain-database.sh --vmid [--vmid ...] [--apply] + +Options: + --vmid Required. Limit destructive action to one or more VMIDs. + --apply Perform deletion. Without this flag, the script prints the target VMIDs and exits. +EOF +} + +while [[ $# -gt 0 ]]; do + case "$1" in + --vmid) + [[ $# -ge 2 ]] || { usage >&2; exit 2; } + TARGET_VMIDS+=("$2") + shift 2 + ;; + --apply) + APPLY=true + shift + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Unknown argument: $1" >&2 + usage >&2 + exit 2 + ;; + esac +done + +[[ ${#TARGET_VMIDS[@]} -gt 0 ]] || { log_error "At least one --vmid is required for this destructive script."; usage >&2; exit 2; } + echo "=========================================" echo "Clear Entire Blockchain Database" echo "=========================================" @@ -38,35 +82,39 @@ log_error " 5. Take SIGNIFICANT TIME to re-sync" echo "" log_warn "This is a NUCLEAR OPTION - use only if absolutely necessary" echo "" +declare -A SERVICE_BY_VMID +for vmid in 1000 1001 1002 1003 1004; do SERVICE_BY_VMID[$vmid]="besu-validator.service"; done +for vmid in 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510; do SERVICE_BY_VMID[$vmid]="besu-sentry.service"; done +for vmid in 2101 2102 2103 2201 2301 2303 2304 2305 2306 2307 2308 2400 2401 2402 2403 2420 2430 2440 2460 2470 2480; do SERVICE_BY_VMID[$vmid]="besu-rpc.service"; done + +if ! $APPLY; then + log_warn "Dry-run only. Target VMIDs:" + for vmid in "${TARGET_VMIDS[@]}"; do + log_info " VMID $vmid (host $(get_host_for_vmid "$vmid")) service ${SERVICE_BY_VMID[$vmid]:-unknown}" + done + log_info "Re-run with --apply to proceed." + exit 0 +fi + read -p "Type 'DELETE DATABASE' to confirm: " CONFIRM if [ "$CONFIRM" != "DELETE DATABASE" ]; then log_info "Aborted" exit 0 fi -# All Besu nodes -VALIDATORS=(1000 1001 1002 1003 1004) -RPC_NODES=(2500 2501 2502) - -log_info "Stopping all Besu nodes..." -for vmid in "${VALIDATORS[@]}"; do +log_info "Stopping selected Besu nodes..." +for vmid in "${TARGET_VMIDS[@]}"; do + service="${SERVICE_BY_VMID[$vmid]:-besu.service}" if pct status "$vmid" 2>/dev/null | grep -q "running"; then - log_info "Stopping VMID $vmid (validator)..." - pct exec "$vmid" -- systemctl stop besu-validator.service 2>/dev/null || true - fi -done - -for vmid in "${RPC_NODES[@]}"; do - if pct status "$vmid" 2>/dev/null | grep -q "running"; then - log_info "Stopping VMID $vmid (RPC)..." - pct exec "$vmid" -- systemctl stop besu-rpc.service 2>/dev/null || true + log_info "Stopping VMID $vmid ($service)..." + pct exec "$vmid" -- systemctl stop "$service" 2>/dev/null || pct exec "$vmid" -- systemctl stop besu.service 2>/dev/null || true fi done sleep 5 -log_info "Clearing entire blockchain databases..." -for vmid in "${VALIDATORS[@]}" "${RPC_NODES[@]}"; do +log_info "Clearing selected blockchain databases..." +for vmid in "${TARGET_VMIDS[@]}"; do if pct status "$vmid" 2>/dev/null | grep -q "running"; then log_info "Clearing VMID $vmid..." @@ -84,18 +132,12 @@ for vmid in "${VALIDATORS[@]}" "${RPC_NODES[@]}"; do fi done -log_info "Starting all Besu nodes..." -for vmid in "${VALIDATORS[@]}"; do +log_info "Starting selected Besu nodes..." +for vmid in "${TARGET_VMIDS[@]}"; do + service="${SERVICE_BY_VMID[$vmid]:-besu.service}" if pct status "$vmid" 2>/dev/null | grep -q "running"; then - log_info "Starting VMID $vmid (validator)..." - pct exec "$vmid" -- systemctl start besu-validator.service 2>/dev/null || true - fi -done - -for vmid in "${RPC_NODES[@]}"; do - if pct status "$vmid" 2>/dev/null | grep -q "running"; then - log_info "Starting VMID $vmid (RPC)..." - pct exec "$vmid" -- systemctl start besu-rpc.service 2>/dev/null || true + log_info "Starting VMID $vmid ($service)..." + pct exec "$vmid" -- systemctl start "$service" 2>/dev/null || pct exec "$vmid" -- systemctl start besu.service 2>/dev/null || true fi done @@ -113,4 +155,3 @@ log_info "Next steps:" log_info " 1. Wait for nodes to re-sync (monitor block numbers)" log_info " 2. Once synced, run: ./scripts/configure-ethereum-mainnet-final.sh" log_info "" - diff --git a/scripts/collect-all-enodes.sh b/scripts/collect-all-enodes.sh index 4a1e4f13..e62942f7 100755 --- a/scripts/collect-all-enodes.sh +++ b/scripts/collect-all-enodes.sh @@ -3,14 +3,101 @@ set -euo pipefail -# Load IP configuration SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" -source "${PROJECT_ROOT}/config/ip-addresses.conf" 2>/dev/null || true +source "${PROJECT_ROOT}/scripts/lib/load-project-env.sh" +declare -A NODE_IPS=( + [1505]="192.168.11.213" + [1506]="192.168.11.214" + [1507]="192.168.11.244" + [1508]="192.168.11.245" + [1509]="192.168.11.219" + [1510]="192.168.11.220" + [2101]="${RPC_CORE_1:-192.168.11.211}" + [2102]="192.168.11.212" + [2103]="192.168.11.217" + [2201]="${RPC_PUBLIC_1:-192.168.11.221}" + [2301]="${RPC_PRIVATE_1:-192.168.11.232}" + [2303]="192.168.11.233" + [2304]="192.168.11.234" + [2305]="192.168.11.235" + [2306]="192.168.11.236" + [2307]="192.168.11.237" + [2308]="192.168.11.238" + [2400]="192.168.11.240" + [2401]="${RPC_THIRDWEB_1:-192.168.11.241}" + [2402]="${RPC_THIRDWEB_2:-192.168.11.242}" + [2403]="${RPC_THIRDWEB_3:-192.168.11.243}" + [2420]="192.168.11.172" + [2430]="192.168.11.173" + [2440]="192.168.11.174" + [2460]="192.168.11.246" + [2470]="192.168.11.247" + [2480]="192.168.11.248" +) -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +declare -A NODE_NAMES=( + [1505]="besu-sentry-alltra-1" + [1506]="besu-sentry-alltra-2" + [1507]="besu-sentry-hybx-1" + [1508]="besu-sentry-hybx-2" + [1509]="besu-sentry-thirdweb-1" + [1510]="besu-sentry-thirdweb-2" + [2101]="besu-rpc-core-1" + [2102]="besu-rpc-core-2" + [2103]="besu-rpc-admin-core-3" + [2201]="besu-rpc-public-1" + [2301]="besu-rpc-private-1" + [2303]="besu-rpc-private-3" + [2304]="besu-rpc-private-4" + [2305]="besu-rpc-private-5" + [2306]="besu-rpc-private-6" + [2307]="besu-rpc-private-7" + [2308]="besu-rpc-private-8" + [2400]="besu-rpc-thirdweb-primary" + [2401]="besu-rpc-thirdweb-1" + [2402]="besu-rpc-thirdweb-2" + [2403]="besu-rpc-thirdweb-3" + [2420]="besu-rpc-alltra-1" + [2430]="besu-rpc-alltra-2" + [2440]="besu-rpc-alltra-3" + [2460]="besu-rpc-hybx-1" + [2470]="besu-rpc-hybx-2" + [2480]="besu-rpc-hybx-3" +) + +TARGET_VMIDS=() + +usage() { + cat <<'EOF' +Usage: ./scripts/collect-all-enodes.sh --vmid [--vmid ...] + +Options: + --vmid Required. Collect enodes only for the selected VMIDs. +EOF +} + +while [[ $# -gt 0 ]]; do + case "$1" in + --vmid) + [[ $# -ge 2 ]] || { usage >&2; exit 2; } + TARGET_VMIDS+=("$2") + shift 2 + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Unknown argument: $1" >&2 + usage >&2 + exit 2 + ;; + esac +done + +[[ ${#TARGET_VMIDS[@]} -gt 0 ]] || { usage >&2; exit 2; } BLUE='\033[0;34m' GREEN='\033[0;32m' @@ -23,17 +110,20 @@ collect_enode() { local vmid=$1 local ip=$2 local hostname=$3 + local host + host="$(get_host_for_vmid "$vmid")" log "Collecting enode from $vmid ($hostname)..." - local enode=$(pct exec $vmid -- bash -c ' + local enode + enode=$(ssh -o StrictHostKeyChecking=no root@"$host" "pct exec $vmid -- bash -c ' if [ -f /data/besu/NODE_ID ]; then NODE_ID=$(cat /data/besu/NODE_ID) - echo "enode://${NODE_ID}@'"$ip"':30303" + echo \"enode://${NODE_ID}@'"$ip"':30303\" else - echo "PENDING" + echo PENDING fi - ' 2>/dev/null || echo "ERROR") + '" 2>/dev/null || echo "ERROR") echo "$vmid|$hostname|$ip|$enode" } @@ -45,19 +135,13 @@ echo "" ENODE_DIR=$(mktemp -d) -log "ALLTRA nodes..." -collect_enode 1505 "${IP_SERVICE_21:-${IP_SERVICE_21:-${IP_SERVICE_21:-${IP_SERVICE_21:-${IP_SERVICE_21:-192.168.11.21}}}}}3" "besu-sentry-alltra-1" > "$ENODE_DIR/1505.txt" & -collect_enode 1506 "${IP_SERVICE_21:-${IP_SERVICE_21:-${IP_SERVICE_21:-${IP_SERVICE_21:-${IP_SERVICE_21:-192.168.11.21}}}}}4" "besu-sentry-alltra-2" > "$ENODE_DIR/1506.txt" & -collect_enode 2500 "${IP_SERVICE_172:-${IP_SERVICE_172:-192.168.11.172}}" "besu-rpc-alltra-1" > "$ENODE_DIR/2500.txt" & -collect_enode 2501 "${IP_SERVICE_173:-${IP_SERVICE_173:-192.168.11.173}}" "besu-rpc-alltra-2" > "$ENODE_DIR/2501.txt" & -collect_enode 2502 "${IP_SERVICE_174:-${IP_SERVICE_174:-192.168.11.174}}" "besu-rpc-alltra-3" > "$ENODE_DIR/2502.txt" & - -log "HYBX nodes..." -collect_enode 1507 "${IP_RPC_244:-${IP_RPC_244:-${IP_RPC_244:-192.168.11.244}}}" "besu-sentry-hybx-1" > "$ENODE_DIR/1507.txt" & -collect_enode 1508 "${IP_RPC_245:-${IP_RPC_245:-${IP_RPC_245:-192.168.11.245}}}" "besu-sentry-hybx-2" > "$ENODE_DIR/1508.txt" & -collect_enode 2503 "${IP_RPC_246:-${IP_RPC_246:-${IP_RPC_246:-192.168.11.246}}}" "besu-rpc-hybx-1" > "$ENODE_DIR/2503.txt" & -collect_enode 2504 "${IP_RPC_247:-${IP_RPC_247:-${IP_RPC_247:-192.168.11.247}}}" "besu-rpc-hybx-2" > "$ENODE_DIR/2504.txt" & -collect_enode 2505 "${IP_RPC_248:-${IP_RPC_248:-${IP_RPC_248:-192.168.11.248}}}" "besu-rpc-hybx-3" > "$ENODE_DIR/2505.txt" & +for vmid in "${TARGET_VMIDS[@]}"; do + if [[ -z "${NODE_IPS[$vmid]:-}" || -z "${NODE_NAMES[$vmid]:-}" ]]; then + echo "$vmid|unknown|unknown|UNSUPPORTED_VMID" > "$ENODE_DIR/${vmid}.txt" + continue + fi + collect_enode "$vmid" "${NODE_IPS[$vmid]}" "${NODE_NAMES[$vmid]}" > "$ENODE_DIR/${vmid}.txt" & +done echo "" log "Waiting for collections..." diff --git a/scripts/collect-enodes-via-rpc.sh b/scripts/collect-enodes-via-rpc.sh index d1f54e5f..232334ff 100755 --- a/scripts/collect-enodes-via-rpc.sh +++ b/scripts/collect-enodes-via-rpc.sh @@ -4,24 +4,106 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" -source "$PROJECT_ROOT/config/ip-addresses.conf" +source "$PROJECT_ROOT/scripts/lib/load-project-env.sh" -get_host_for_vmid() { - local vmid=$1 - if [[ "$vmid" =~ ^(1505|1506|1507|1508)$ ]]; then - echo "${PROXMOX_HOST_ML110}" - elif [[ "$vmid" =~ ^(2500|2501|2502|2503|2504|2505)$ ]]; then - echo "${PROXMOX_HOST_R630_01}" - else - echo "${PROXMOX_HOST_R630_01}" - fi +declare -A NODE_IPS=( + [1505]="192.168.11.213" + [1506]="192.168.11.214" + [1507]="192.168.11.244" + [1508]="192.168.11.245" + [1509]="192.168.11.219" + [1510]="192.168.11.220" + [2101]="${RPC_CORE_1:-192.168.11.211}" + [2102]="192.168.11.212" + [2103]="192.168.11.217" + [2201]="${RPC_PUBLIC_1:-192.168.11.221}" + [2301]="${RPC_PRIVATE_1:-192.168.11.232}" + [2303]="192.168.11.233" + [2304]="192.168.11.234" + [2305]="192.168.11.235" + [2306]="192.168.11.236" + [2307]="192.168.11.237" + [2308]="192.168.11.238" + [2400]="192.168.11.240" + [2401]="${RPC_THIRDWEB_1:-192.168.11.241}" + [2402]="${RPC_THIRDWEB_2:-192.168.11.242}" + [2403]="${RPC_THIRDWEB_3:-192.168.11.243}" + [2420]="192.168.11.172" + [2430]="192.168.11.173" + [2440]="192.168.11.174" + [2460]="192.168.11.246" + [2470]="192.168.11.247" + [2480]="192.168.11.248" +) + +declare -A NODE_NAMES=( + [1505]="besu-sentry-alltra-1" + [1506]="besu-sentry-alltra-2" + [1507]="besu-sentry-hybx-1" + [1508]="besu-sentry-hybx-2" + [1509]="besu-sentry-thirdweb-1" + [1510]="besu-sentry-thirdweb-2" + [2101]="besu-rpc-core-1" + [2102]="besu-rpc-core-2" + [2103]="besu-rpc-admin-core-3" + [2201]="besu-rpc-public-1" + [2301]="besu-rpc-private-1" + [2303]="besu-rpc-private-3" + [2304]="besu-rpc-private-4" + [2305]="besu-rpc-private-5" + [2306]="besu-rpc-private-6" + [2307]="besu-rpc-private-7" + [2308]="besu-rpc-private-8" + [2400]="besu-rpc-thirdweb-primary" + [2401]="besu-rpc-thirdweb-1" + [2402]="besu-rpc-thirdweb-2" + [2403]="besu-rpc-thirdweb-3" + [2420]="besu-rpc-alltra-1" + [2430]="besu-rpc-alltra-2" + [2440]="besu-rpc-alltra-3" + [2460]="besu-rpc-hybx-1" + [2470]="besu-rpc-hybx-2" + [2480]="besu-rpc-hybx-3" +) + +TARGET_VMIDS=() + +usage() { + cat <<'EOF' +Usage: ./scripts/collect-enodes-via-rpc.sh --vmid [--vmid ...] + +Options: + --vmid Required. Collect enodes only for the selected VMIDs. +EOF } +while [[ $# -gt 0 ]]; do + case "$1" in + --vmid) + [[ $# -ge 2 ]] || { usage >&2; exit 2; } + TARGET_VMIDS+=("$2") + shift 2 + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Unknown argument: $1" >&2 + usage >&2 + exit 2 + ;; + esac +done + +[[ ${#TARGET_VMIDS[@]} -gt 0 ]] || { usage >&2; exit 2; } + collect_enode() { local vmid=$1 local ip=$2 local hostname=$3 - local host=$(get_host_for_vmid $vmid) + local host + host="$(get_host_for_vmid "$vmid")" # Try RPC first local enode=$(ssh -o StrictHostKeyChecking=no root@${host} "pct exec $vmid -- curl -s -X POST -H 'Content-Type: application/json' --data '{\"jsonrpc\":\"2.0\",\"method\":\"admin_nodeInfo\",\"params\":[],\"id\":1}' http://localhost:8545 2>/dev/null | grep -o '\"enode\":\"[^\"]*\"' | cut -d'\"' -f4" 2>/dev/null) @@ -42,17 +124,10 @@ collect_enode() { echo "$vmid|$hostname|$ip|$enode" } -for vmid in 1505 1506 2500 2501 2502 1507 1508 2503 2504 2505; do - case $vmid in - 1505) collect_enode 1505 "${IP_SERVICE_21:-${IP_SERVICE_21:-${IP_SERVICE_21:-${IP_SERVICE_21:-${IP_SERVICE_21:-192.168.11.21}}}}}3" "besu-sentry-alltra-1" ;; - 1506) collect_enode 1506 "${IP_SERVICE_21:-${IP_SERVICE_21:-${IP_SERVICE_21:-${IP_SERVICE_21:-${IP_SERVICE_21:-192.168.11.21}}}}}4" "besu-sentry-alltra-2" ;; - 2500) collect_enode 2500 "${IP_SERVICE_172:-${IP_SERVICE_172:-192.168.11.172}}" "besu-rpc-alltra-1" ;; - 2501) collect_enode 2501 "${IP_SERVICE_173:-${IP_SERVICE_173:-192.168.11.173}}" "besu-rpc-alltra-2" ;; - 2502) collect_enode 2502 "${IP_SERVICE_174:-${IP_SERVICE_174:-192.168.11.174}}" "besu-rpc-alltra-3" ;; - 1507) collect_enode 1507 "${IP_RPC_244:-${IP_RPC_244:-${IP_RPC_244:-192.168.11.244}}}" "besu-sentry-hybx-1" ;; - 1508) collect_enode 1508 "${IP_RPC_245:-${IP_RPC_245:-${IP_RPC_245:-192.168.11.245}}}" "besu-sentry-hybx-2" ;; - 2503) collect_enode 2503 "${IP_RPC_246:-${IP_RPC_246:-${IP_RPC_246:-192.168.11.246}}}" "besu-rpc-hybx-1" ;; - 2504) collect_enode 2504 "${IP_RPC_247:-${IP_RPC_247:-${IP_RPC_247:-192.168.11.247}}}" "besu-rpc-hybx-2" ;; - 2505) collect_enode 2505 "${IP_RPC_248:-${IP_RPC_248:-${IP_RPC_248:-192.168.11.248}}}" "besu-rpc-hybx-3" ;; - esac +for vmid in "${TARGET_VMIDS[@]}"; do + if [[ -z "${NODE_IPS[$vmid]:-}" || -z "${NODE_NAMES[$vmid]:-}" ]]; then + echo "$vmid|unknown|unknown|UNSUPPORTED_VMID" + continue + fi + collect_enode "$vmid" "${NODE_IPS[$vmid]}" "${NODE_NAMES[$vmid]}" done diff --git a/scripts/configure-rpc-nodes.sh b/scripts/configure-rpc-nodes.sh index 8c616b63..13a44b0f 100755 --- a/scripts/configure-rpc-nodes.sh +++ b/scripts/configure-rpc-nodes.sh @@ -3,19 +3,76 @@ set -euo pipefail -# Load IP configuration -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" -source "${PROJECT_ROOT}/config/ip-addresses.conf" 2>/dev/null || true - - SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +source "${PROJECT_ROOT}/scripts/lib/load-project-env.sh" log() { echo "[INFO] $1"; } success() { echo "[✓] $1"; } error() { echo "[ERROR] $1"; } +PROFILE="" +TARGET_VMIDS=() + +usage() { + cat <<'EOF' +Usage: ./scripts/configure-rpc-nodes.sh --profile --vmid [--vmid ...] + +Options: + --profile Required. Choose the config template to generate. + --vmid Required. Generate config only for the selected VMIDs. +EOF +} + +while [[ $# -gt 0 ]]; do + case "$1" in + --profile) + [[ $# -ge 2 ]] || { usage >&2; exit 2; } + PROFILE="$2" + shift 2 + ;; + --vmid) + [[ $# -ge 2 ]] || { usage >&2; exit 2; } + TARGET_VMIDS+=("$2") + shift 2 + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Unknown argument: $1" >&2 + usage >&2 + exit 2 + ;; + esac +done + +[[ -n "$PROFILE" ]] || { usage >&2; exit 2; } +[[ ${#TARGET_VMIDS[@]} -gt 0 ]] || { usage >&2; exit 2; } + +declare -A RPC_IPS=( + [2101]="${RPC_CORE_1:-192.168.11.211}" + [2201]="${RPC_PUBLIC_1:-192.168.11.221}" + [2301]="${RPC_PRIVATE_1:-192.168.11.232}" + [2303]="192.168.11.233" + [2304]="192.168.11.234" + [2305]="192.168.11.235" + [2306]="192.168.11.236" + [2307]="192.168.11.237" + [2308]="192.168.11.238" + [2400]="192.168.11.240" + [2401]="${RPC_THIRDWEB_1:-192.168.11.241}" + [2402]="${RPC_THIRDWEB_2:-192.168.11.242}" + [2403]="${RPC_THIRDWEB_3:-192.168.11.243}" + [2420]="192.168.11.172" + [2430]="192.168.11.173" + [2440]="192.168.11.174" + [2460]="192.168.11.246" + [2470]="192.168.11.247" + [2480]="192.168.11.248" +) + # Function to create full-function RPC config create_fullfunction_config() { local vmid=$1 @@ -113,26 +170,28 @@ log "RPC Node Configuration Generator" log "===================================" echo "" -# ALLTRA Network -log "Configuring ALLTRA Network RPC Nodes..." -create_fullfunction_config 2500 "${IP_SERVICE_172:-${IP_SERVICE_172:-192.168.11.172}}" -create_standardbase_config 2501 "${IP_SERVICE_173:-${IP_SERVICE_173:-192.168.11.173}}" -create_standardbase_config 2502 "${IP_SERVICE_174:-${IP_SERVICE_174:-192.168.11.174}}" +for vmid in "${TARGET_VMIDS[@]}"; do + ip="${RPC_IPS[$vmid]:-}" + if [[ -z "$ip" ]]; then + error "Unsupported VMID: $vmid" + exit 2 + fi + case "$PROFILE" in + fullfunction) create_fullfunction_config "$vmid" "$ip" ;; + standardbase) create_standardbase_config "$vmid" "$ip" ;; + *) + error "Unknown profile: $PROFILE" + usage >&2 + exit 2 + ;; + esac +done + echo "" - -# HYBX Network -log "Configuring HYBX Network RPC Nodes..." -create_fullfunction_config 2503 "${IP_RPC_246:-${IP_RPC_246:-${IP_RPC_246:-192.168.11.246}}}" -create_standardbase_config 2504 "${IP_RPC_247:-${IP_RPC_247:-${IP_RPC_247:-192.168.11.247}}}" -create_standardbase_config 2505 "${IP_RPC_248:-${IP_RPC_248:-${IP_RPC_248:-192.168.11.248}}}" -echo "" - -log "Configuration files created in /tmp/" -log "Deploy these to respective RPC node config directories:" -log " ALLTRA-RPC-1 (Full): /tmp/besu-config-fullfunction-2500.toml → /opt/besu/config/" -log " ALLTRA-RPC-2 (Std): /tmp/besu-config-standardbase-2501.toml → /opt/besu/config/" -log " ALLTRA-RPC-3 (Std): /tmp/besu-config-standardbase-2502.toml → /opt/besu/config/" -log " HYBX-RPC-1 (Full): /tmp/besu-config-fullfunction-2503.toml → /opt/besu/config/" -log " HYBX-RPC-2 (Std): /tmp/besu-config-standardbase-2504.toml → /opt/besu/config/" -log " HYBX-RPC-3 (Std): /tmp/besu-config-standardbase-2505.toml → /opt/besu/config/" - +log "Configuration files created in /tmp/ for profile '$PROFILE':" +for vmid in "${TARGET_VMIDS[@]}"; do + case "$PROFILE" in + fullfunction) log " /tmp/besu-config-fullfunction-$vmid.toml → /opt/besu/config/" ;; + standardbase) log " /tmp/besu-config-standardbase-$vmid.toml → /opt/besu/config/" ;; + esac +done diff --git a/scripts/create-missing-containers-2506-2508.sh b/scripts/create-missing-containers-2506-2508.sh index e86ab133..81e057da 100755 --- a/scripts/create-missing-containers-2506-2508.sh +++ b/scripts/create-missing-containers-2506-2508.sh @@ -4,8 +4,19 @@ # # Usage: PROXMOX_HOST=192.168.11.11 bash scripts/create-missing-containers-2506-2508.sh [--dry-run] +# HISTORICAL SCRIPT +# VMIDs 2506-2508 were part of a retired migration plan and are documented as destroyed/decommissioned. +# This file remains for reference only. + set -euo pipefail +if [[ "${HISTORICAL_ALLOW_RUN:-0}" != "1" ]]; then + echo "HISTORICAL: create-missing-containers-2506-2508.sh is not a current provisioning runbook." >&2 + echo "See docs/04-configuration/ALL_VMIDS_ENDPOINTS.md for the live inventory before creating any CTs." >&2 + echo "Set HISTORICAL_ALLOW_RUN=1 only if you intentionally need this legacy script." >&2 + exit 1 +fi + SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" source "${PROJECT_ROOT}/config/ip-addresses.conf" 2>/dev/null || true diff --git a/scripts/deployment/deploy-mainnet-aave-quote-push-receiver.sh b/scripts/deployment/deploy-mainnet-aave-quote-push-receiver.sh new file mode 100644 index 00000000..b47037a5 --- /dev/null +++ b/scripts/deployment/deploy-mainnet-aave-quote-push-receiver.sh @@ -0,0 +1,107 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Deploy only the Mainnet Aave quote-push receiver. +# Default: simulation only. Use --apply to broadcast. +# +# Env: +# PRIVATE_KEY, ETHEREUM_MAINNET_RPC required +# AAVE_POOL_ADDRESS optional; defaults inside the Forge script +# QUOTE_PUSH_RECEIVER_OWNER optional; defaults to deployer derived from PRIVATE_KEY +# +# Usage: +# bash scripts/deployment/deploy-mainnet-aave-quote-push-receiver.sh --dry-run +# bash scripts/deployment/deploy-mainnet-aave-quote-push-receiver.sh --apply + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROXMOX_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)" +SMOM="${PROXMOX_ROOT}/smom-dbis-138" + +_qp_private_key="${PRIVATE_KEY-}" +_qp_rpc="${ETHEREUM_MAINNET_RPC-}" +_qp_pool="${AAVE_POOL_ADDRESS-}" +_qp_owner="${QUOTE_PUSH_RECEIVER_OWNER-}" + +# shellcheck disable=SC1091 +source "${PROXMOX_ROOT}/scripts/lib/load-project-env.sh" 2>/dev/null || true +# shellcheck disable=SC1091 +source "${SMOM}/scripts/load-env.sh" >/dev/null 2>&1 || true + +[[ -n "$_qp_private_key" ]] && export PRIVATE_KEY="$_qp_private_key" +[[ -n "$_qp_rpc" ]] && export ETHEREUM_MAINNET_RPC="$_qp_rpc" +[[ -n "$_qp_pool" ]] && export AAVE_POOL_ADDRESS="$_qp_pool" +[[ -n "$_qp_owner" ]] && export QUOTE_PUSH_RECEIVER_OWNER="$_qp_owner" + +unset _qp_private_key _qp_rpc _qp_pool _qp_owner + +require_cmd() { + command -v "$1" >/dev/null 2>&1 || { + echo "[fail] missing required command: $1" >&2 + exit 1 + } +} + +require_env() { + local name="$1" + if [[ -z "${!name:-}" ]]; then + echo "[fail] missing required env: $name" >&2 + exit 1 + fi +} + +pick_latest_receiver() { + local mode="$1" + local latest_json="${SMOM}/broadcast/DeployAaveQuotePushFlashReceiver.s.sol/1/run-latest.json" + if [[ "$mode" == "dry-run" ]]; then + latest_json="${SMOM}/broadcast/DeployAaveQuotePushFlashReceiver.s.sol/1/dry-run/run-latest.json" + fi + if [[ ! -f "$latest_json" ]] || ! command -v jq >/dev/null 2>&1; then + return 1 + fi + jq -r '.transactions[]? | select(.transactionType == "CREATE" and .contractName == "AaveQuotePushFlashReceiver") | .contractAddress' \ + "$latest_json" | tail -n1 +} + +require_cmd forge + +MODE="dry-run" +BROADCAST=() +for arg in "$@"; do + case "$arg" in + --dry-run) MODE="dry-run"; BROADCAST=() ;; + --apply) MODE="apply"; BROADCAST=(--broadcast) ;; + *) + echo "[fail] unknown arg: $arg (use --dry-run or --apply)" >&2 + exit 2 + ;; + esac +done + +require_env PRIVATE_KEY +require_env ETHEREUM_MAINNET_RPC + +echo "=== deploy-mainnet-aave-quote-push-receiver ($MODE) ===" +if [[ -n "${QUOTE_PUSH_RECEIVER_OWNER:-}" ]]; then + echo "receiver_owner=$QUOTE_PUSH_RECEIVER_OWNER" +fi + +( + cd "$SMOM" + forge script script/deploy/DeployAaveQuotePushFlashReceiver.s.sol:DeployAaveQuotePushFlashReceiver \ + --rpc-url "$ETHEREUM_MAINNET_RPC" \ + "${BROADCAST[@]}" \ + -vvvv +) + +receiver_addr="$(pick_latest_receiver "$MODE" || true)" +echo +if [[ "$MODE" == "dry-run" ]]; then + echo "Projected receiver address from this dry-run:" +else + echo "After --apply: copy deployed address into .env:" +fi +echo " AAVE_QUOTE_PUSH_RECEIVER_MAINNET=${receiver_addr:-...}" +echo "Shortest manager handoff:" +echo " AAVE_QUOTE_PUSH_RECEIVER_MAINNET=${receiver_addr:-...} QUOTE_PUSH_TREASURY_TAKE_RECEIVER_OWNERSHIP=1 bash scripts/deployment/deploy-mainnet-quote-push-treasury-manager.sh --apply" +echo "Full stack alternative:" +echo " bash scripts/deployment/deploy-mainnet-aave-quote-push-stack.sh --apply" diff --git a/scripts/deployment/deploy-mainnet-aave-quote-push-stack.sh b/scripts/deployment/deploy-mainnet-aave-quote-push-stack.sh index 6cb949e8..c3e74ce9 100755 --- a/scripts/deployment/deploy-mainnet-aave-quote-push-stack.sh +++ b/scripts/deployment/deploy-mainnet-aave-quote-push-stack.sh @@ -3,6 +3,7 @@ set -euo pipefail # Deploy Mainnet flash quote-push stack (Aave receiver + external unwinder). # Default: simulation only (no --broadcast). Use --apply to broadcast. +# For receiver-only migrations, use deploy-mainnet-aave-quote-push-receiver.sh. # # Env: # PRIVATE_KEY, ETHEREUM_MAINNET_RPC @@ -165,6 +166,8 @@ unwinder_addr="$(pick_latest_create_address "$unwinder_script" "$unwinder_contra echo "After --apply: copy deployed addresses into .env:" echo " AAVE_QUOTE_PUSH_RECEIVER_MAINNET=${receiver_addr:-...}" echo " QUOTE_PUSH_EXTERNAL_UNWINDER_MAINNET=${unwinder_addr:-...}" +echo "Optional retained-surplus manager:" +echo " QUOTE_PUSH_TREASURY_TAKE_RECEIVER_OWNERSHIP=1 bash scripts/deployment/deploy-mainnet-quote-push-treasury-manager.sh --apply" echo "Or rerun immediately with QUOTE_PUSH_UNWINDER_TYPE=${UNW} so run-mainnet-aave-cwusdc-quote-push-once.sh can auto-pick the latest broadcast unwinder." echo "Then set FLASH_QUOTE_AMOUNT_RAW, UNWIND_MODE, UNWIND_V3_FEE_U24 (or UNWIND_DODO_POOL / two-hop vars) and run:" echo " bash scripts/deployment/run-mainnet-aave-cwusdc-quote-push-once.sh --dry-run" diff --git a/scripts/deployment/deploy-mainnet-quote-push-treasury-manager.sh b/scripts/deployment/deploy-mainnet-quote-push-treasury-manager.sh new file mode 100644 index 00000000..90c7b60e --- /dev/null +++ b/scripts/deployment/deploy-mainnet-quote-push-treasury-manager.sh @@ -0,0 +1,137 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Deploy the Mainnet quote-push treasury manager and optionally transfer the +# receiver ownership to it. Default: simulation only. Use --apply to broadcast. +# +# Env: +# PRIVATE_KEY, ETHEREUM_MAINNET_RPC required +# AAVE_QUOTE_PUSH_RECEIVER_MAINNET optional; auto-picks latest receiver broadcast +# QUOTE_PUSH_SURPLUS_TOKEN_MAINNET optional; defaults to mainnet USDC +# QUOTE_PUSH_TREASURY_OWNER optional; defaults to deployer +# QUOTE_PUSH_TREASURY_OPERATOR optional; defaults to owner +# QUOTE_PUSH_TREASURY_GAS_RECIPIENT optional; defaults to owner +# QUOTE_PUSH_TREASURY_RECYCLE_RECIPIENT optional; defaults to owner +# QUOTE_PUSH_RECEIVER_RESERVE_RAW optional; defaults to 0 +# QUOTE_PUSH_TREASURY_RESERVE_RAW optional; defaults to 0 +# QUOTE_PUSH_TREASURY_TAKE_RECEIVER_OWNERSHIP optional; 1 transfers receiver ownership to manager +# +# Usage: +# bash scripts/deployment/deploy-mainnet-quote-push-treasury-manager.sh --dry-run +# QUOTE_PUSH_TREASURY_TAKE_RECEIVER_OWNERSHIP=1 \ +# bash scripts/deployment/deploy-mainnet-quote-push-treasury-manager.sh --apply + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROXMOX_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)" +SMOM="${PROXMOX_ROOT}/smom-dbis-138" + +_qp_private_key="${PRIVATE_KEY-}" +_qp_rpc="${ETHEREUM_MAINNET_RPC-}" +_qp_receiver="${AAVE_QUOTE_PUSH_RECEIVER_MAINNET-}" +_qp_token="${QUOTE_PUSH_SURPLUS_TOKEN_MAINNET-}" +_qp_owner="${QUOTE_PUSH_TREASURY_OWNER-}" +_qp_operator="${QUOTE_PUSH_TREASURY_OPERATOR-}" +_qp_gas_recipient="${QUOTE_PUSH_TREASURY_GAS_RECIPIENT-}" +_qp_recycle_recipient="${QUOTE_PUSH_TREASURY_RECYCLE_RECIPIENT-}" +_qp_receiver_reserve="${QUOTE_PUSH_RECEIVER_RESERVE_RAW-}" +_qp_manager_reserve="${QUOTE_PUSH_TREASURY_RESERVE_RAW-}" +_qp_take_receiver="${QUOTE_PUSH_TREASURY_TAKE_RECEIVER_OWNERSHIP-}" + +# shellcheck disable=SC1091 +source "${PROXMOX_ROOT}/scripts/lib/load-project-env.sh" 2>/dev/null || true +# shellcheck disable=SC1091 +source "${SMOM}/scripts/load-env.sh" >/dev/null 2>&1 || true + +[[ -n "$_qp_private_key" ]] && export PRIVATE_KEY="$_qp_private_key" +[[ -n "$_qp_rpc" ]] && export ETHEREUM_MAINNET_RPC="$_qp_rpc" +[[ -n "$_qp_receiver" ]] && export AAVE_QUOTE_PUSH_RECEIVER_MAINNET="$_qp_receiver" +[[ -n "$_qp_token" ]] && export QUOTE_PUSH_SURPLUS_TOKEN_MAINNET="$_qp_token" +[[ -n "$_qp_owner" ]] && export QUOTE_PUSH_TREASURY_OWNER="$_qp_owner" +[[ -n "$_qp_operator" ]] && export QUOTE_PUSH_TREASURY_OPERATOR="$_qp_operator" +[[ -n "$_qp_gas_recipient" ]] && export QUOTE_PUSH_TREASURY_GAS_RECIPIENT="$_qp_gas_recipient" +[[ -n "$_qp_recycle_recipient" ]] && export QUOTE_PUSH_TREASURY_RECYCLE_RECIPIENT="$_qp_recycle_recipient" +[[ -n "$_qp_receiver_reserve" ]] && export QUOTE_PUSH_RECEIVER_RESERVE_RAW="$_qp_receiver_reserve" +[[ -n "$_qp_manager_reserve" ]] && export QUOTE_PUSH_TREASURY_RESERVE_RAW="$_qp_manager_reserve" +[[ -n "$_qp_take_receiver" ]] && export QUOTE_PUSH_TREASURY_TAKE_RECEIVER_OWNERSHIP="$_qp_take_receiver" + +unset _qp_private_key _qp_rpc _qp_receiver _qp_token _qp_owner _qp_operator _qp_gas_recipient +unset _qp_recycle_recipient _qp_receiver_reserve _qp_manager_reserve _qp_take_receiver + +require_cmd() { + command -v "$1" >/dev/null 2>&1 || { + echo "[fail] missing required command: $1" >&2 + exit 1 + } +} + +require_env() { + local name="$1" + if [[ -z "${!name:-}" ]]; then + echo "[fail] missing required env: $name" >&2 + exit 1 + fi +} + +pick_latest_create_address() { + local script_name="$1" + local contract_name="$2" + local mode="${3:-apply}" + local latest_json="${SMOM}/broadcast/${script_name}/1/run-latest.json" + if [[ "$mode" == "dry-run" ]]; then + latest_json="${SMOM}/broadcast/${script_name}/1/dry-run/run-latest.json" + fi + if [[ ! -f "$latest_json" ]] || ! command -v jq >/dev/null 2>&1; then + return 1 + fi + jq -r --arg contract "$contract_name" \ + '.transactions[]? | select(.transactionType == "CREATE" and .contractName == $contract) | .contractAddress' \ + "$latest_json" | tail -n1 +} + +require_cmd forge + +MODE="dry-run" +BROADCAST=() +for arg in "$@"; do + case "$arg" in + --dry-run) MODE="dry-run"; BROADCAST=() ;; + --apply) MODE="apply"; BROADCAST=(--broadcast) ;; + *) + echo "[fail] unknown arg: $arg (use --dry-run or --apply)" >&2 + exit 2 + ;; + esac +done + +require_env PRIVATE_KEY +require_env ETHEREUM_MAINNET_RPC +if [[ -z "${AAVE_QUOTE_PUSH_RECEIVER_MAINNET:-}" ]]; then + inferred_receiver="$(pick_latest_create_address "DeployAaveQuotePushFlashReceiver.s.sol" "AaveQuotePushFlashReceiver" "apply" || true)" + if [[ -n "$inferred_receiver" && "$inferred_receiver" != "null" ]]; then + export AAVE_QUOTE_PUSH_RECEIVER_MAINNET="$inferred_receiver" + fi +fi +require_env AAVE_QUOTE_PUSH_RECEIVER_MAINNET + +echo "=== deploy-mainnet-quote-push-treasury-manager ($MODE) ===" +echo "receiver=$AAVE_QUOTE_PUSH_RECEIVER_MAINNET" +echo "take_receiver_ownership=${QUOTE_PUSH_TREASURY_TAKE_RECEIVER_OWNERSHIP:-0}" + +( + cd "$SMOM" + forge script script/deploy/DeployQuotePushTreasuryManager.s.sol:DeployQuotePushTreasuryManager \ + --rpc-url "$ETHEREUM_MAINNET_RPC" \ + "${BROADCAST[@]}" \ + -vvvv +) + +manager_addr="$(pick_latest_create_address "DeployQuotePushTreasuryManager.s.sol" "QuotePushTreasuryManager" "$MODE" || true)" +echo +if [[ "$MODE" == "dry-run" ]]; then + echo "Projected treasury manager address from this dry-run:" +else + echo "After --apply: copy deployed addresses into .env:" +fi +echo " QUOTE_PUSH_TREASURY_MANAGER_MAINNET=${manager_addr:-...}" +echo "Optional keeper entrypoint:" +echo " bash scripts/deployment/run-mainnet-aave-quote-push-keeper.sh --dry-run" diff --git a/scripts/deployment/manage-mainnet-quote-push-treasury.sh b/scripts/deployment/manage-mainnet-quote-push-treasury.sh new file mode 100644 index 00000000..77ea441e --- /dev/null +++ b/scripts/deployment/manage-mainnet-quote-push-treasury.sh @@ -0,0 +1,124 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Harvest receiver surplus into the treasury manager and/or distribute quote to +# the configured gas and recycle recipients. Default: simulation only. +# +# Env: +# PRIVATE_KEY, ETHEREUM_MAINNET_RPC required +# QUOTE_PUSH_TREASURY_MANAGER_MAINNET optional; auto-picks latest manager broadcast +# QUOTE_PUSH_TREASURY_HARVEST optional; defaults to 1 +# QUOTE_PUSH_TREASURY_GAS_DISTRIBUTION_RAW optional; defaults to 0 +# QUOTE_PUSH_TREASURY_RECYCLE_DISTRIBUTION_RAW optional; defaults to 0 +# +# Usage: +# bash scripts/deployment/manage-mainnet-quote-push-treasury.sh --dry-run +# QUOTE_PUSH_TREASURY_GAS_DISTRIBUTION_RAW=1000 \ +# QUOTE_PUSH_TREASURY_RECYCLE_DISTRIBUTION_RAW=2000 \ +# bash scripts/deployment/manage-mainnet-quote-push-treasury.sh --apply + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROXMOX_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)" +SMOM="${PROXMOX_ROOT}/smom-dbis-138" + +_qp_private_key="${PRIVATE_KEY-}" +_qp_rpc="${ETHEREUM_MAINNET_RPC-}" +_qp_manager="${QUOTE_PUSH_TREASURY_MANAGER_MAINNET-}" +_qp_harvest="${QUOTE_PUSH_TREASURY_HARVEST-}" +_qp_gas_raw="${QUOTE_PUSH_TREASURY_GAS_DISTRIBUTION_RAW-}" +_qp_recycle_raw="${QUOTE_PUSH_TREASURY_RECYCLE_DISTRIBUTION_RAW-}" + +# shellcheck disable=SC1091 +source "${PROXMOX_ROOT}/scripts/lib/load-project-env.sh" 2>/dev/null || true +# shellcheck disable=SC1091 +source "${SMOM}/scripts/load-env.sh" >/dev/null 2>&1 || true + +[[ -n "$_qp_private_key" ]] && export PRIVATE_KEY="$_qp_private_key" +[[ -n "$_qp_rpc" ]] && export ETHEREUM_MAINNET_RPC="$_qp_rpc" +[[ -n "$_qp_manager" ]] && export QUOTE_PUSH_TREASURY_MANAGER_MAINNET="$_qp_manager" +[[ -n "$_qp_harvest" ]] && export QUOTE_PUSH_TREASURY_HARVEST="$_qp_harvest" +[[ -n "$_qp_gas_raw" ]] && export QUOTE_PUSH_TREASURY_GAS_DISTRIBUTION_RAW="$_qp_gas_raw" +[[ -n "$_qp_recycle_raw" ]] && export QUOTE_PUSH_TREASURY_RECYCLE_DISTRIBUTION_RAW="$_qp_recycle_raw" + +unset _qp_private_key _qp_rpc _qp_manager _qp_harvest _qp_gas_raw _qp_recycle_raw + +require_cmd() { + command -v "$1" >/dev/null 2>&1 || { + echo "[fail] missing required command: $1" >&2 + exit 1 + } +} + +require_env() { + local name="$1" + if [[ -z "${!name:-}" ]]; then + echo "[fail] missing required env: $name" >&2 + exit 1 + fi +} + +pick_latest_manager() { + local latest_json="${SMOM}/broadcast/DeployQuotePushTreasuryManager.s.sol/1/run-latest.json" + if [[ ! -f "$latest_json" ]] || ! command -v jq >/dev/null 2>&1; then + return 1 + fi + jq -r '.transactions[]? | select(.transactionType == "CREATE" and .contractName == "QuotePushTreasuryManager") | .contractAddress' \ + "$latest_json" | tail -n1 +} + +require_cmd cast +require_cmd forge + +MODE="dry-run" +BROADCAST=() +for arg in "$@"; do + case "$arg" in + --dry-run) MODE="dry-run"; BROADCAST=() ;; + --apply) MODE="apply"; BROADCAST=(--broadcast) ;; + *) + echo "[fail] unknown arg: $arg (use --dry-run or --apply)" >&2 + exit 2 + ;; + esac +done + +require_env PRIVATE_KEY +require_env ETHEREUM_MAINNET_RPC +if [[ -z "${QUOTE_PUSH_TREASURY_MANAGER_MAINNET:-}" ]]; then + inferred_manager="$(pick_latest_manager || true)" + if [[ -n "$inferred_manager" && "$inferred_manager" != "null" ]]; then + export QUOTE_PUSH_TREASURY_MANAGER_MAINNET="$inferred_manager" + fi +fi +require_env QUOTE_PUSH_TREASURY_MANAGER_MAINNET + +DEPLOYER="$(cast wallet address --private-key "$PRIVATE_KEY")" +manager_owner="$(cast call "$QUOTE_PUSH_TREASURY_MANAGER_MAINNET" 'owner()(address)' --rpc-url "$ETHEREUM_MAINNET_RPC" | awk '{print $1}')" +manager_operator="$(cast call "$QUOTE_PUSH_TREASURY_MANAGER_MAINNET" 'operator()(address)' --rpc-url "$ETHEREUM_MAINNET_RPC" | awk '{print $1}')" +if [[ "${manager_owner,,}" != "${DEPLOYER,,}" && "${manager_operator,,}" != "${DEPLOYER,,}" ]]; then + echo "[fail] deployer $DEPLOYER is neither manager owner ($manager_owner) nor operator ($manager_operator)" >&2 + exit 1 +fi + +quote_balance="$(cast call "$QUOTE_PUSH_TREASURY_MANAGER_MAINNET" 'quoteBalance()(uint256)' --rpc-url "$ETHEREUM_MAINNET_RPC" | awk '{print $1}')" +available_quote="$(cast call "$QUOTE_PUSH_TREASURY_MANAGER_MAINNET" 'availableQuote()(uint256)' --rpc-url "$ETHEREUM_MAINNET_RPC" | awk '{print $1}')" +receiver_sweepable="$(cast call "$QUOTE_PUSH_TREASURY_MANAGER_MAINNET" 'receiverSweepableQuote()(uint256)' --rpc-url "$ETHEREUM_MAINNET_RPC" | awk '{print $1}')" + +echo "=== manage-mainnet-quote-push-treasury ($MODE) ===" +echo "manager=$QUOTE_PUSH_TREASURY_MANAGER_MAINNET" +echo "manager_owner=$manager_owner" +echo "manager_operator=$manager_operator" +echo "harvest=${QUOTE_PUSH_TREASURY_HARVEST:-1}" +echo "gas_distribution_raw=${QUOTE_PUSH_TREASURY_GAS_DISTRIBUTION_RAW:-0}" +echo "recycle_distribution_raw=${QUOTE_PUSH_TREASURY_RECYCLE_DISTRIBUTION_RAW:-0}" +echo "quote_balance_raw=$quote_balance" +echo "available_quote_raw=$available_quote" +echo "receiver_sweepable_raw=$receiver_sweepable" + +( + cd "$SMOM" + forge script script/flash/ManageQuotePushTreasuryManager.s.sol:ManageQuotePushTreasuryManager \ + --rpc-url "$ETHEREUM_MAINNET_RPC" \ + "${BROADCAST[@]}" \ + -vvvv +) diff --git a/scripts/deployment/plan-mainnet-cwusdc-flash-quote-push-rebalance.sh b/scripts/deployment/plan-mainnet-cwusdc-flash-quote-push-rebalance.sh index a79013e9..6e277183 100755 --- a/scripts/deployment/plan-mainnet-cwusdc-flash-quote-push-rebalance.sh +++ b/scripts/deployment/plan-mainnet-cwusdc-flash-quote-push-rebalance.sh @@ -10,6 +10,8 @@ set -euo pipefail # (Aave flashLoan USDC → PMM swap USDC→cWUSDC → external unwind cWUSDC→USDC # → repay Aave + premium). Each successful round **raises PMM quote reserves** and # **draws base** from the pool, moving base-heavy / quote-thin books toward peg. +# Retained quote surplus stays on the receiver until swept by the owner and can +# then be recycled into wallet-funded pool growth. # # This script is read-only + local modeling: # - reads live pool reserves (cast) @@ -102,7 +104,12 @@ echo echo "4) Reserve peg monitor after any live work:" echo " bash scripts/verify/check-mainnet-cwusdc-usdc-reserve-peg.sh" echo -echo "5) Pick a valid Uniswap V3 unwind (no guessing fee tiers):" +echo "5) Receiver surplus accounting and recycle path:" +echo " bash scripts/verify/report-mainnet-aave-quote-push-surplus-accounting.sh" +echo " bash scripts/deployment/sweep-mainnet-aave-quote-push-receiver-surplus.sh --dry-run" +echo " bash scripts/deployment/recycle-mainnet-aave-quote-push-surplus.sh --dry-run" +echo +echo "6) Pick a valid Uniswap V3 unwind (no guessing fee tiers):" echo " bash scripts/verify/probe-uniswap-v3-cwusdc-usdc-mainnet.sh" echo " If no pool: UNWIND_MODE=2 — build path: bash scripts/verify/build-uniswap-v3-exact-input-path-hex.sh ... (VERIFY_POOLS=1 optional)" echo " Calculations report (dry-run snapshots): reports/status/mainnet_cwusdc_usdc_quote_push_calculations_2026-04-12.md" diff --git a/scripts/deployment/pmm-soak-operator-fund-grid.sh b/scripts/deployment/pmm-soak-operator-fund-grid.sh index d4dfee9a..c37efbcc 100755 --- a/scripts/deployment/pmm-soak-operator-fund-grid.sh +++ b/scripts/deployment/pmm-soak-operator-fund-grid.sh @@ -185,8 +185,11 @@ _pmm_fund_grid_err() { trap '_pmm_fund_grid_err' ERR _chunk_wall_start="$SECONDS" -_prog_every="${PMM_SOAK_FUND_PROGRESS_EVERY:-50}" -[[ "$_prog_every" =~ ^[0-9]+$ ]] || _prog_every=50 +# Avoid names starting with "_" inside (( )) under set -u (some shells/envs treat expansion oddly). +fund_progress_every=50 +if [[ -n "${PMM_SOAK_FUND_PROGRESS_EVERY:-}" && "${PMM_SOAK_FUND_PROGRESS_EVERY}" =~ ^[0-9]+$ ]]; then + fund_progress_every="${PMM_SOAK_FUND_PROGRESS_EVERY}" +fi n=0 for r in "${RECIPIENTS[@]}"; do n=$((n + 1)) @@ -197,10 +200,12 @@ for r in "${RECIPIENTS[@]}"; do cast send "$TOKEN_ADDR" 'transfer(address,uint256)(bool)' "$r" "$AMOUNT" \ --rpc-url "$RPC" --private-key "$PK" --legacy --gas-price "$GAS_WEI" fi - if [[ "$_prog_every" -gt 0 ]] && (( n % _prog_every == 0 || n == total )); then - _el=$((SECONDS - _chunk_wall_start)) - python3 -c "n=$n;total=$total;el=$_el;avg=el/n if n else 0.0;rem=total-n;eta=int(rem*avg) if rem>0 else 0;print(f'[fund-grid] progress {n}/{total} chunk_elapsed_s={el} avg_s_per_tx={avg:.2f} est_remaining_this_chunk_s={eta}')" 2>/dev/null || true - elif [[ "$_prog_every" -eq 0 ]] && [[ "$n" -eq "$total" ]]; then + if [[ "${fund_progress_every}" -gt 0 ]]; then + if (( n % fund_progress_every == 0 )) || (( n == total )); then + _el=$((SECONDS - _chunk_wall_start)) + python3 -c "n=$n;total=$total;el=$_el;avg=el/n if n else 0.0;rem=total-n;eta=int(rem*avg) if rem>0 else 0;print(f'[fund-grid] progress {n}/{total} chunk_elapsed_s={el} avg_s_per_tx={avg:.2f} est_remaining_this_chunk_s={eta}')" 2>/dev/null || true + fi + elif [[ "$n" -eq "$total" ]]; then echo "[fund-grid] progress ${n}/${total} chunk_elapsed_s=$((SECONDS - _chunk_wall_start)) (final)" fi done diff --git a/scripts/deployment/recycle-mainnet-aave-quote-push-surplus.sh b/scripts/deployment/recycle-mainnet-aave-quote-push-surplus.sh new file mode 100644 index 00000000..1befa0b5 --- /dev/null +++ b/scripts/deployment/recycle-mainnet-aave-quote-push-surplus.sh @@ -0,0 +1,155 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Sweep retained quote surplus from the receiver to the deployer and, when the +# deployer gas reserve is healthy, immediately recycle that quote into the +# wallet-funded cWUSDC/USDC peg tranche helper. +# +# Default: simulation only. Use --apply to broadcast / execute. +# +# Env: +# ETHEREUM_MAINNET_RPC required +# PRIVATE_KEY required +# AAVE_QUOTE_PUSH_RECEIVER_MAINNET required +# QUOTE_PUSH_SURPLUS_TOKEN_MAINNET optional; defaults to mainnet USDC +# QUOTE_PUSH_RECEIVER_RESERVE_RAW optional; amount to keep on receiver after sweep +# QUOTE_PUSH_DEPLOYER_GAS_FLOOR_ETH optional; default 0.003 +# QUOTE_PUSH_OPERATION_BUFFER_ETH optional; default 0.0005 +# QUOTE_PUSH_NATIVE_TOKEN_PRICE optional; default 3200 +# +# Usage: +# source scripts/lib/load-project-env.sh +# bash scripts/deployment/recycle-mainnet-aave-quote-push-surplus.sh --dry-run +# bash scripts/deployment/recycle-mainnet-aave-quote-push-surplus.sh --apply + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROXMOX_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)" +SMOM="${PROXMOX_ROOT}/smom-dbis-138" +DEFAULT_USDC_MAINNET="0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" + +# shellcheck disable=SC1091 +source "${PROXMOX_ROOT}/scripts/lib/load-project-env.sh" 2>/dev/null || true +# shellcheck disable=SC1091 +source "${SMOM}/scripts/load-env.sh" >/dev/null 2>&1 || true + +require_cmd() { + command -v "$1" >/dev/null 2>&1 || { + echo "[fail] missing required command: $1" >&2 + exit 1 + } +} + +require_env() { + local name="$1" + if [[ -z "${!name:-}" ]]; then + echo "[fail] missing required env: $name" >&2 + exit 1 + fi +} + +pick_latest_receiver() { + local latest_json="${SMOM}/broadcast/DeployAaveQuotePushFlashReceiver.s.sol/1/run-latest.json" + if [[ ! -f "$latest_json" ]] || ! command -v jq >/dev/null 2>&1; then + return 1 + fi + jq -r '.transactions[]? | select(.transactionType == "CREATE" and .contractName == "AaveQuotePushFlashReceiver") | .contractAddress' \ + "$latest_json" | tail -n1 +} + +require_cmd cast +require_cmd python3 + +MODE="dry-run" +for arg in "$@"; do + case "$arg" in + --dry-run) MODE="dry-run" ;; + --apply) MODE="apply" ;; + *) + echo "[fail] unknown arg: $arg (use --dry-run or --apply)" >&2 + exit 2 + ;; + esac +done + +require_env ETHEREUM_MAINNET_RPC +require_env PRIVATE_KEY +if [[ -z "${AAVE_QUOTE_PUSH_RECEIVER_MAINNET:-}" ]]; then + inferred_receiver="$(pick_latest_receiver || true)" + if [[ -n "$inferred_receiver" && "$inferred_receiver" != "null" ]]; then + export AAVE_QUOTE_PUSH_RECEIVER_MAINNET="$inferred_receiver" + fi +fi +require_env AAVE_QUOTE_PUSH_RECEIVER_MAINNET + +DEPLOYER="$(cast wallet address --private-key "$PRIVATE_KEY")" +TOKEN="${QUOTE_PUSH_SURPLUS_TOKEN_MAINNET:-$DEFAULT_USDC_MAINNET}" +RECEIVER_RESERVE_RAW="${QUOTE_PUSH_RECEIVER_RESERVE_RAW:-0}" +GAS_FLOOR_ETH="${QUOTE_PUSH_DEPLOYER_GAS_FLOOR_ETH:-0.003}" +OP_BUFFER_ETH="${QUOTE_PUSH_OPERATION_BUFFER_ETH:-0.0005}" +NATIVE_TOKEN_PRICE="${QUOTE_PUSH_NATIVE_TOKEN_PRICE:-3200}" + +deployer_eth="$(cast balance "$DEPLOYER" --ether --rpc-url "$ETHEREUM_MAINNET_RPC")" +receiver_quote_raw="$(cast call "$TOKEN" 'balanceOf(address)(uint256)' "$AAVE_QUOTE_PUSH_RECEIVER_MAINNET" --rpc-url "$ETHEREUM_MAINNET_RPC" | awk '{print $1}')" + +read -r sweepable_raw gas_shortfall_eth < 0 else "no") +PY +)" + +echo "=== recycle-mainnet-aave-quote-push-surplus ($MODE) ===" +echo "deployer=$DEPLOYER" +echo "receiver=$AAVE_QUOTE_PUSH_RECEIVER_MAINNET" +echo "token=$TOKEN" +echo "receiver_quote_raw=$receiver_quote_raw" +echo "receiver_reserve_raw=$RECEIVER_RESERVE_RAW" +echo "sweepable_raw=$sweepable_raw" +echo "deployer_eth=$deployer_eth" +echo "gas_floor_eth=$GAS_FLOOR_ETH" +echo "operation_buffer_eth=$OP_BUFFER_ETH" +echo "native_token_price=$NATIVE_TOKEN_PRICE" + +bash "${PROXMOX_ROOT}/scripts/verify/report-mainnet-aave-quote-push-surplus-accounting.sh" + +if (( sweepable_raw == 0 )); then + echo "[stop] no sweepable receiver surplus is available" >&2 + exit 3 +fi + +if [[ "$MODE" == "dry-run" ]]; then + bash "${PROXMOX_ROOT}/scripts/deployment/sweep-mainnet-aave-quote-push-receiver-surplus.sh" --dry-run + if [[ "$gas_floor_breached" == "yes" ]]; then + echo "[stop] deployer gas reserve is below recycle floor; sweep can proceed, but pool recycle is intentionally skipped" + exit 0 + fi + bash "${PROXMOX_ROOT}/scripts/deployment/apply-mainnet-cwusdc-usdc-peg-tranche-from-wallet.sh" --dry-run + exit 0 +fi + +bash "${PROXMOX_ROOT}/scripts/deployment/sweep-mainnet-aave-quote-push-receiver-surplus.sh" --apply + +if [[ "$gas_floor_breached" == "yes" ]]; then + echo "[stop] swept surplus to deployer, but deployer ETH is still below recycle floor; skipping pool-growth tranche" + exit 0 +fi + +bash "${PROXMOX_ROOT}/scripts/deployment/apply-mainnet-cwusdc-usdc-peg-tranche-from-wallet.sh" --apply diff --git a/scripts/deployment/run-mainnet-aave-cwusdc-quote-push-once.sh b/scripts/deployment/run-mainnet-aave-cwusdc-quote-push-once.sh index e544f8ad..5c5a5447 100755 --- a/scripts/deployment/run-mainnet-aave-cwusdc-quote-push-once.sh +++ b/scripts/deployment/run-mainnet-aave-cwusdc-quote-push-once.sh @@ -285,3 +285,4 @@ echo "flash_quote_amount_raw=$FLASH_QUOTE_AMOUNT_RAW unwind_mode=$UM" ) echo "Done. Re-check: bash scripts/verify/check-mainnet-cwusdc-usdc-reserve-peg.sh" +echo "Receiver surplus accounting: bash scripts/verify/report-mainnet-aave-quote-push-surplus-accounting.sh" diff --git a/scripts/deployment/run-mainnet-aave-quote-push-keeper.sh b/scripts/deployment/run-mainnet-aave-quote-push-keeper.sh new file mode 100644 index 00000000..a0426435 --- /dev/null +++ b/scripts/deployment/run-mainnet-aave-quote-push-keeper.sh @@ -0,0 +1,356 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Single entrypoint for the quote-push maintenance loop: +# 1. plan current accounting / gas policy +# 2. execute one flash quote-push +# 3. recycle retained quote via treasury manager or direct sweep fallback +# +# Default: simulation only. Use --apply to broadcast / execute. +# +# Env: +# PRIVATE_KEY, ETHEREUM_MAINNET_RPC required +# DODO_PMM_INTEGRATION_MAINNET required unless QUOTE_PUSH_KEEPER_SKIP_FLASH=1 +# QUOTE_PUSH_TREASURY_MANAGER_MAINNET optional; when set, manager path is preferred +# QUOTE_PUSH_SURPLUS_TOKEN_MAINNET optional; defaults to mainnet USDC +# QUOTE_PUSH_RECEIVER_RESERVE_RAW optional; defaults to 0 +# QUOTE_PUSH_DEPLOYER_GAS_FLOOR_ETH optional; defaults to 0.003 +# QUOTE_PUSH_OPERATION_BUFFER_ETH optional; defaults to 0.0005 +# QUOTE_PUSH_NATIVE_TOKEN_PRICE optional; defaults to 3200 +# QUOTE_PUSH_KEEPER_SKIP_FLASH optional; default 0 +# QUOTE_PUSH_KEEPER_SKIP_RECYCLE optional; default 0 +# +# Usage: +# bash scripts/deployment/run-mainnet-aave-quote-push-keeper.sh --dry-run +# bash scripts/deployment/run-mainnet-aave-quote-push-keeper.sh --apply + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROXMOX_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)" +SMOM="${PROXMOX_ROOT}/smom-dbis-138" +DEFAULT_USDC_MAINNET="0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" + +_qp_private_key="${PRIVATE_KEY-}" +_qp_rpc="${ETHEREUM_MAINNET_RPC-}" +_qp_manager="${QUOTE_PUSH_TREASURY_MANAGER_MAINNET-}" +_qp_token="${QUOTE_PUSH_SURPLUS_TOKEN_MAINNET-}" +_qp_receiver_reserve="${QUOTE_PUSH_RECEIVER_RESERVE_RAW-}" +_qp_gas_floor="${QUOTE_PUSH_DEPLOYER_GAS_FLOOR_ETH-}" +_qp_gas_buffer="${QUOTE_PUSH_OPERATION_BUFFER_ETH-}" +_qp_native_price="${QUOTE_PUSH_NATIVE_TOKEN_PRICE-}" +_qp_skip_flash="${QUOTE_PUSH_KEEPER_SKIP_FLASH-}" +_qp_skip_recycle="${QUOTE_PUSH_KEEPER_SKIP_RECYCLE-}" + +# shellcheck disable=SC1091 +source "${PROXMOX_ROOT}/scripts/lib/load-project-env.sh" 2>/dev/null || true +# shellcheck disable=SC1091 +source "${SMOM}/scripts/load-env.sh" >/dev/null 2>&1 || true + +[[ -n "$_qp_private_key" ]] && export PRIVATE_KEY="$_qp_private_key" +[[ -n "$_qp_rpc" ]] && export ETHEREUM_MAINNET_RPC="$_qp_rpc" +[[ -n "$_qp_manager" ]] && export QUOTE_PUSH_TREASURY_MANAGER_MAINNET="$_qp_manager" +[[ -n "$_qp_token" ]] && export QUOTE_PUSH_SURPLUS_TOKEN_MAINNET="$_qp_token" +[[ -n "$_qp_receiver_reserve" ]] && export QUOTE_PUSH_RECEIVER_RESERVE_RAW="$_qp_receiver_reserve" +[[ -n "$_qp_gas_floor" ]] && export QUOTE_PUSH_DEPLOYER_GAS_FLOOR_ETH="$_qp_gas_floor" +[[ -n "$_qp_gas_buffer" ]] && export QUOTE_PUSH_OPERATION_BUFFER_ETH="$_qp_gas_buffer" +[[ -n "$_qp_native_price" ]] && export QUOTE_PUSH_NATIVE_TOKEN_PRICE="$_qp_native_price" +[[ -n "$_qp_skip_flash" ]] && export QUOTE_PUSH_KEEPER_SKIP_FLASH="$_qp_skip_flash" +[[ -n "$_qp_skip_recycle" ]] && export QUOTE_PUSH_KEEPER_SKIP_RECYCLE="$_qp_skip_recycle" + +unset _qp_private_key _qp_rpc _qp_manager _qp_token _qp_receiver_reserve _qp_gas_floor +unset _qp_gas_buffer _qp_native_price _qp_skip_flash _qp_skip_recycle + +require_cmd() { + command -v "$1" >/dev/null 2>&1 || { + echo "[fail] missing required command: $1" >&2 + exit 1 + } +} + +pick_latest_manager() { + local latest_json="${SMOM}/broadcast/DeployQuotePushTreasuryManager.s.sol/1/run-latest.json" + if [[ ! -f "$latest_json" ]] || ! command -v jq >/dev/null 2>&1; then + return 1 + fi + jq -r '.transactions[]? | select(.transactionType == "CREATE" and .contractName == "QuotePushTreasuryManager") | .contractAddress' \ + "$latest_json" | tail -n1 +} + +pick_latest_receiver() { + local latest_json="${SMOM}/broadcast/DeployAaveQuotePushFlashReceiver.s.sol/1/run-latest.json" + if [[ ! -f "$latest_json" ]] || ! command -v jq >/dev/null 2>&1; then + return 1 + fi + jq -r '.transactions[]? | select(.transactionType == "CREATE" and .contractName == "AaveQuotePushFlashReceiver") | .contractAddress' \ + "$latest_json" | tail -n1 +} + +to_human() { + python3 - "$1" <<'PY' +import sys +print(f"{int(sys.argv[1]) / 1_000_000:.6f}") +PY +} + +compute_keeper_plan() { + local manager_addr="${1:-}" + local deployer_eth="$2" + local token_addr="$3" + local receiver_addr="$4" + local receiver_reserve_raw="$5" + local gas_floor_eth="$6" + local gas_buffer_eth="$7" + local native_price="$8" + + local receiver_quote_raw=0 + local manager_quote_raw=0 + local manager_available_raw=0 + local receiver_sweepable_raw=0 + local total_controlled_raw=0 + local gas_distribution_raw=0 + local recycle_distribution_raw=0 + local gas_shortfall_eth=0 + local gas_shortfall_quote_raw=0 + local gas_recipient="" + local recycle_recipient="" + + if [[ -n "$manager_addr" ]]; then + manager_quote_raw="$(cast call "$manager_addr" 'quoteBalance()(uint256)' --rpc-url "$ETHEREUM_MAINNET_RPC" | awk '{print $1}')" + manager_available_raw="$(cast call "$manager_addr" 'availableQuote()(uint256)' --rpc-url "$ETHEREUM_MAINNET_RPC" | awk '{print $1}')" + receiver_sweepable_raw="$(cast call "$manager_addr" 'receiverSweepableQuote()(uint256)' --rpc-url "$ETHEREUM_MAINNET_RPC" | awk '{print $1}')" + gas_recipient="$(cast call "$manager_addr" 'gasRecipient()(address)' --rpc-url "$ETHEREUM_MAINNET_RPC" | awk '{print $1}')" + recycle_recipient="$(cast call "$manager_addr" 'recycleRecipient()(address)' --rpc-url "$ETHEREUM_MAINNET_RPC" | awk '{print $1}')" + else + receiver_quote_raw="$(cast call "$token_addr" 'balanceOf(address)(uint256)' "$receiver_addr" --rpc-url "$ETHEREUM_MAINNET_RPC" | awk '{print $1}')" + receiver_sweepable_raw="$( + python3 - "$receiver_quote_raw" "$receiver_reserve_raw" <<'PY' +import sys +receiver_quote_raw = int(sys.argv[1]) +receiver_reserve_raw = int(sys.argv[2]) +print(max(0, receiver_quote_raw - receiver_reserve_raw)) +PY + )" + fi + + eval "$( + python3 - "$deployer_eth" "$gas_floor_eth" "$gas_buffer_eth" "$native_price" \ + "${manager_available_raw:-0}" "${receiver_sweepable_raw:-0}" <<'PY' +import math +import sys + +deployer_eth = float(sys.argv[1]) +gas_floor_eth = float(sys.argv[2]) +gas_buffer_eth = float(sys.argv[3]) +native_price = float(sys.argv[4]) +manager_available_raw = int(sys.argv[5]) +receiver_sweepable_raw = int(sys.argv[6]) + +gas_shortfall_eth = max(0.0, gas_floor_eth + gas_buffer_eth - deployer_eth) +gas_shortfall_quote_raw = math.ceil(gas_shortfall_eth * native_price * 1_000_000) +total_controlled_raw = manager_available_raw + receiver_sweepable_raw +gas_distribution_raw = min(total_controlled_raw, gas_shortfall_quote_raw) +recycle_distribution_raw = max(0, total_controlled_raw - gas_distribution_raw) + +print(f"GAS_SHORTFALL_ETH={gas_shortfall_eth}") +print(f"GAS_SHORTFALL_QUOTE_RAW={gas_shortfall_quote_raw}") +print(f"TOTAL_CONTROLLED_RAW={total_controlled_raw}") +print(f"GAS_DISTRIBUTION_RAW={gas_distribution_raw}") +print(f"RECYCLE_DISTRIBUTION_RAW={recycle_distribution_raw}") +PY + )" + + KEEPER_MANAGER_QUOTE_RAW="${manager_quote_raw:-0}" + KEEPER_MANAGER_AVAILABLE_RAW="${manager_available_raw:-0}" + KEEPER_RECEIVER_QUOTE_RAW="${receiver_quote_raw:-0}" + KEEPER_RECEIVER_SWEEPABLE_RAW="${receiver_sweepable_raw:-0}" + KEEPER_TOTAL_CONTROLLED_RAW="${TOTAL_CONTROLLED_RAW:-0}" + KEEPER_GAS_SHORTFALL_ETH="${GAS_SHORTFALL_ETH:-0}" + KEEPER_GAS_SHORTFALL_QUOTE_RAW="${GAS_SHORTFALL_QUOTE_RAW:-0}" + KEEPER_GAS_DISTRIBUTION_RAW="${GAS_DISTRIBUTION_RAW:-0}" + KEEPER_RECYCLE_DISTRIBUTION_RAW="${RECYCLE_DISTRIBUTION_RAW:-0}" + KEEPER_GAS_RECIPIENT="${gas_recipient:-}" + KEEPER_RECYCLE_RECIPIENT="${recycle_recipient:-}" +} + +require_cmd cast +require_cmd python3 +require_cmd forge + +MODE="dry-run" +for arg in "$@"; do + case "$arg" in + --dry-run) MODE="dry-run" ;; + --apply) MODE="apply" ;; + *) + echo "[fail] unknown arg: $arg (use --dry-run or --apply)" >&2 + exit 2 + ;; + esac +done + +if [[ -z "${PRIVATE_KEY:-}" || -z "${ETHEREUM_MAINNET_RPC:-}" ]]; then + echo "[fail] PRIVATE_KEY and ETHEREUM_MAINNET_RPC are required" >&2 + exit 1 +fi + +if [[ -z "${QUOTE_PUSH_TREASURY_MANAGER_MAINNET:-}" ]]; then + inferred_manager="$(pick_latest_manager || true)" + if [[ -n "$inferred_manager" && "$inferred_manager" != "null" ]]; then + export QUOTE_PUSH_TREASURY_MANAGER_MAINNET="$inferred_manager" + fi +fi + +if [[ -z "${AAVE_QUOTE_PUSH_RECEIVER_MAINNET:-}" ]]; then + inferred_receiver="$(pick_latest_receiver || true)" + if [[ -n "$inferred_receiver" && "$inferred_receiver" != "null" ]]; then + export AAVE_QUOTE_PUSH_RECEIVER_MAINNET="$inferred_receiver" + fi +fi + +SKIP_FLASH="${QUOTE_PUSH_KEEPER_SKIP_FLASH:-0}" +SKIP_RECYCLE="${QUOTE_PUSH_KEEPER_SKIP_RECYCLE:-0}" +TOKEN="${QUOTE_PUSH_SURPLUS_TOKEN_MAINNET:-$DEFAULT_USDC_MAINNET}" +RECEIVER="${AAVE_QUOTE_PUSH_RECEIVER_MAINNET:-}" +RECEIVER_RESERVE_RAW="${QUOTE_PUSH_RECEIVER_RESERVE_RAW:-0}" +GAS_FLOOR_ETH="${QUOTE_PUSH_DEPLOYER_GAS_FLOOR_ETH:-0.003}" +OP_BUFFER_ETH="${QUOTE_PUSH_OPERATION_BUFFER_ETH:-0.0005}" +NATIVE_TOKEN_PRICE="${QUOTE_PUSH_NATIVE_TOKEN_PRICE:-3200}" +DEPLOYER="$(cast wallet address --private-key "$PRIVATE_KEY")" +MANAGER="${QUOTE_PUSH_TREASURY_MANAGER_MAINNET:-}" + +echo "=== run-mainnet-aave-quote-push-keeper ($MODE) ===" +echo "deployer=$DEPLOYER" +echo "manager=${MANAGER:-}" +echo "skip_flash=$SKIP_FLASH" +echo "skip_recycle=$SKIP_RECYCLE" + +bash "${PROXMOX_ROOT}/scripts/verify/report-mainnet-aave-quote-push-surplus-accounting.sh" + +deployer_eth="$(cast balance "$DEPLOYER" --ether --rpc-url "$ETHEREUM_MAINNET_RPC")" +compute_keeper_plan "$MANAGER" "$deployer_eth" "$TOKEN" "$RECEIVER" "$RECEIVER_RESERVE_RAW" "$GAS_FLOOR_ETH" "$OP_BUFFER_ETH" "$NATIVE_TOKEN_PRICE" + +echo +echo "=== Keeper policy plan ===" +echo "deployer_eth=$deployer_eth" +echo "gas_shortfall_eth=$KEEPER_GAS_SHORTFALL_ETH" +echo "gas_shortfall_quote_raw=$KEEPER_GAS_SHORTFALL_QUOTE_RAW human=$(to_human "$KEEPER_GAS_SHORTFALL_QUOTE_RAW")" +if [[ -n "$MANAGER" ]]; then + echo "manager_quote_raw=$KEEPER_MANAGER_QUOTE_RAW human=$(to_human "$KEEPER_MANAGER_QUOTE_RAW")" + echo "manager_available_raw=$KEEPER_MANAGER_AVAILABLE_RAW human=$(to_human "$KEEPER_MANAGER_AVAILABLE_RAW")" + echo "receiver_sweepable_raw=$KEEPER_RECEIVER_SWEEPABLE_RAW human=$(to_human "$KEEPER_RECEIVER_SWEEPABLE_RAW")" + echo "gas_recipient=${KEEPER_GAS_RECIPIENT:-}" + echo "recycle_recipient=${KEEPER_RECYCLE_RECIPIENT:-}" +else + echo "receiver_quote_raw=$KEEPER_RECEIVER_QUOTE_RAW human=$(to_human "$KEEPER_RECEIVER_QUOTE_RAW")" + echo "receiver_sweepable_raw=$KEEPER_RECEIVER_SWEEPABLE_RAW human=$(to_human "$KEEPER_RECEIVER_SWEEPABLE_RAW")" +fi +echo "total_controlled_raw=$KEEPER_TOTAL_CONTROLLED_RAW human=$(to_human "$KEEPER_TOTAL_CONTROLLED_RAW")" +echo "planned_gas_distribution_raw=$KEEPER_GAS_DISTRIBUTION_RAW human=$(to_human "$KEEPER_GAS_DISTRIBUTION_RAW")" +echo "planned_recycle_distribution_raw=$KEEPER_RECYCLE_DISTRIBUTION_RAW human=$(to_human "$KEEPER_RECYCLE_DISTRIBUTION_RAW")" + +if [[ "$SKIP_RECYCLE" != "1" ]]; then + if [[ -n "$MANAGER" ]]; then + manager_receiver_owned="$(cast call "$MANAGER" 'isReceiverOwnedByManager()(bool)' --rpc-url "$ETHEREUM_MAINNET_RPC" | awk '{print $1}')" + if [[ "$manager_receiver_owned" != "true" ]]; then + cat >&2 < QUOTE_PUSH_TREASURY_TAKE_RECEIVER_OWNERSHIP=1 bash scripts/deployment/deploy-mainnet-quote-push-treasury-manager.sh --apply +EOF + exit 1 + fi + else + receiver_owner="$(cast call "$RECEIVER" 'owner()(address)' --rpc-url "$ETHEREUM_MAINNET_RPC" 2>/dev/null | awk '{print $1}' || true)" + if [[ -z "$receiver_owner" ]]; then + cat >&2 <} +[hint] Redeploy the updated receiver, then hand it to the treasury manager: + bash scripts/deployment/deploy-mainnet-aave-quote-push-receiver.sh --apply + AAVE_QUOTE_PUSH_RECEIVER_MAINNET= QUOTE_PUSH_TREASURY_TAKE_RECEIVER_OWNERSHIP=1 bash scripts/deployment/deploy-mainnet-quote-push-treasury-manager.sh --apply +EOF + exit 1 + fi + fi +fi + +if [[ "$MODE" == "dry-run" && -n "$MANAGER" ]]; then + export QUOTE_PUSH_TREASURY_HARVEST=1 + export QUOTE_PUSH_TREASURY_GAS_HOLDBACK_TARGET_RAW="$KEEPER_GAS_SHORTFALL_QUOTE_RAW" + bash "${PROXMOX_ROOT}/scripts/deployment/run-mainnet-aave-quote-push-managed-cycle.sh" --dry-run + + if [[ "${KEEPER_RECYCLE_RECIPIENT,,}" == "${DEPLOYER,,}" ]]; then + echo "[plan] A live managed cycle would route recycle quote back to the deployer, after which the wallet LP helper can be attempted." + fi + exit 0 +fi + +if [[ "$SKIP_FLASH" != "1" ]]; then + bash "${PROXMOX_ROOT}/scripts/deployment/run-mainnet-aave-cwusdc-quote-push-once.sh" "--${MODE}" +fi + +echo +echo "=== Post-execution accounting ===" +bash "${PROXMOX_ROOT}/scripts/verify/report-mainnet-aave-quote-push-surplus-accounting.sh" + +if [[ "$SKIP_RECYCLE" == "1" ]]; then + echo "[stop] recycle phase skipped by QUOTE_PUSH_KEEPER_SKIP_RECYCLE=1" + exit 0 +fi + +deployer_eth="$(cast balance "$DEPLOYER" --ether --rpc-url "$ETHEREUM_MAINNET_RPC")" +compute_keeper_plan "$MANAGER" "$deployer_eth" "$TOKEN" "$RECEIVER" "$RECEIVER_RESERVE_RAW" "$GAS_FLOOR_ETH" "$OP_BUFFER_ETH" "$NATIVE_TOKEN_PRICE" + +if (( KEEPER_TOTAL_CONTROLLED_RAW == 0 )); then + echo "[stop] no controllable quote is available for recycle" + exit 0 +fi + +if [[ -n "$MANAGER" ]]; then + export QUOTE_PUSH_TREASURY_HARVEST="$( + python3 - "$KEEPER_RECEIVER_SWEEPABLE_RAW" <<'PY' +import sys +print("1" if int(sys.argv[1]) > 0 else "0") +PY + )" + export QUOTE_PUSH_TREASURY_GAS_DISTRIBUTION_RAW="$KEEPER_GAS_DISTRIBUTION_RAW" + export QUOTE_PUSH_TREASURY_RECYCLE_DISTRIBUTION_RAW="$KEEPER_RECYCLE_DISTRIBUTION_RAW" + + bash "${PROXMOX_ROOT}/scripts/deployment/manage-mainnet-quote-push-treasury.sh" "--${MODE}" + + if [[ "$MODE" == "dry-run" ]]; then + if [[ "${KEEPER_RECYCLE_RECIPIENT,,}" == "${DEPLOYER,,}" && "$KEEPER_RECYCLE_DISTRIBUTION_RAW" != "0" ]]; then + echo "[plan] After a live manager distribution to the deployer, the wallet tranche helper will be attempted." + fi + exit 0 + fi + + if python3 - "$KEEPER_GAS_SHORTFALL_ETH" <<'PY' +import sys +sys.exit(0 if float(sys.argv[1]) > 0 else 1) +PY + then + echo "[stop] quote was distributed, but deployer ETH is still below the recycle floor; skipping wallet LP tranche" + exit 0 + fi + + if (( KEEPER_RECYCLE_DISTRIBUTION_RAW == 0 )); then + echo "[stop] no recycle allocation remains after gas holdback" + exit 0 + fi + + if [[ -z "${KEEPER_RECYCLE_RECIPIENT:-}" || "${KEEPER_RECYCLE_RECIPIENT,,}" != "${DEPLOYER,,}" ]]; then + echo "[stop] recycle recipient is not the deployer wallet, so the wallet LP helper is intentionally skipped" + exit 0 + fi + + if ! bash "${PROXMOX_ROOT}/scripts/deployment/apply-mainnet-cwusdc-usdc-peg-tranche-from-wallet.sh" --apply; then + status=$? + if [[ "$status" == "3" ]]; then + echo "[stop] recycle distribution completed, but no wallet-funded LP tranche is currently affordable" + exit 0 + fi + exit "$status" + fi +else + bash "${PROXMOX_ROOT}/scripts/deployment/recycle-mainnet-aave-quote-push-surplus.sh" "--${MODE}" +fi diff --git a/scripts/deployment/run-mainnet-aave-quote-push-managed-cycle.sh b/scripts/deployment/run-mainnet-aave-quote-push-managed-cycle.sh new file mode 100644 index 00000000..9f48a23a --- /dev/null +++ b/scripts/deployment/run-mainnet-aave-quote-push-managed-cycle.sh @@ -0,0 +1,278 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Run one manager-backed Mainnet quote-push cycle: +# flash quote-push -> harvest retained quote into manager -> distribute to configured recipients. +# +# Default: simulation only. Use --apply to broadcast. +# +# Required env: +# PRIVATE_KEY, ETHEREUM_MAINNET_RPC +# DODO_PMM_INTEGRATION_MAINNET +# QUOTE_PUSH_TREASURY_MANAGER_MAINNET +# AAVE_QUOTE_PUSH_RECEIVER_MAINNET optional; defaults to latest broadcast or canonical receiver +# QUOTE_PUSH_EXTERNAL_UNWINDER_MAINNET optional; can be auto-picked from latest broadcast +# FLASH_QUOTE_AMOUNT_RAW optional; defaults to 200000 +# +# Optional treasury env: +# QUOTE_PUSH_TREASURY_HARVEST optional; defaults to 1 +# QUOTE_PUSH_TREASURY_GAS_HOLDBACK_TARGET_RAW optional; defaults to 0 +# +# Usage: +# bash scripts/deployment/run-mainnet-aave-quote-push-managed-cycle.sh --dry-run +# QUOTE_PUSH_TREASURY_GAS_HOLDBACK_TARGET_RAW=0 bash scripts/deployment/run-mainnet-aave-quote-push-managed-cycle.sh --apply + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROXMOX_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)" +SMOM="${PROXMOX_ROOT}/smom-dbis-138" +DEFAULT_AAVE_QUOTE_PUSH_RECEIVER_MAINNET="0x241cb416aaFC2654078b7E2376adED2bDeFbCBa2" +DEFAULT_POOL_CWUSDC_USDC_MAINNET="0x69776fc607e9edA8042e320e7e43f54d06c68f0E" + +_qp_private_key="${PRIVATE_KEY-}" +_qp_rpc="${ETHEREUM_MAINNET_RPC-}" +_qp_receiver="${AAVE_QUOTE_PUSH_RECEIVER_MAINNET-}" +_qp_manager="${QUOTE_PUSH_TREASURY_MANAGER_MAINNET-}" +_qp_unwinder="${QUOTE_PUSH_EXTERNAL_UNWINDER_MAINNET-}" +_qp_amount="${FLASH_QUOTE_AMOUNT_RAW-}" +_qp_unwind_type="${QUOTE_PUSH_UNWINDER_TYPE-}" +_qp_unwind_mode="${UNWIND_MODE-}" +_qp_pool="${POOL_CWUSDC_USDC_MAINNET-}" +_qp_integration="${DODO_PMM_INTEGRATION_MAINNET-}" +_qp_pool_a="${UNWIND_TWO_HOP_POOL_A-}" +_qp_pool_b="${UNWIND_TWO_HOP_POOL_B-}" +_qp_mid_token="${UNWIND_TWO_HOP_MID_TOKEN-}" +_qp_min_mid_out="${UNWIND_MIN_MID_OUT_RAW-}" +_qp_min_out_pmm="${MIN_OUT_PMM-}" +_qp_min_out_unwind="${MIN_OUT_UNWIND-}" +_qp_fee_u24="${UNWIND_V3_FEE_U24-}" +_qp_dodo_pool="${UNWIND_DODO_POOL-}" +_qp_v3_path="${UNWIND_V3_PATH_HEX-}" +_qp_intermediate_token="${UNWIND_INTERMEDIATE_TOKEN-}" +_qp_min_intermediate_out="${UNWIND_MIN_INTERMEDIATE_OUT_RAW-}" +_qp_treasury_harvest="${QUOTE_PUSH_TREASURY_HARVEST-}" +_qp_treasury_holdback="${QUOTE_PUSH_TREASURY_GAS_HOLDBACK_TARGET_RAW-}" + +# shellcheck disable=SC1091 +source "${PROXMOX_ROOT}/scripts/lib/load-project-env.sh" 2>/dev/null || true +# shellcheck disable=SC1091 +source "${SMOM}/scripts/load-env.sh" >/dev/null 2>&1 || true + +[[ -n "$_qp_private_key" ]] && export PRIVATE_KEY="$_qp_private_key" +[[ -n "$_qp_rpc" ]] && export ETHEREUM_MAINNET_RPC="$_qp_rpc" +[[ -n "$_qp_receiver" ]] && export AAVE_QUOTE_PUSH_RECEIVER_MAINNET="$_qp_receiver" +[[ -n "$_qp_manager" ]] && export QUOTE_PUSH_TREASURY_MANAGER_MAINNET="$_qp_manager" +[[ -n "$_qp_unwinder" ]] && export QUOTE_PUSH_EXTERNAL_UNWINDER_MAINNET="$_qp_unwinder" +[[ -n "$_qp_amount" ]] && export FLASH_QUOTE_AMOUNT_RAW="$_qp_amount" +[[ -n "$_qp_unwind_type" ]] && export QUOTE_PUSH_UNWINDER_TYPE="$_qp_unwind_type" +[[ -n "$_qp_unwind_mode" ]] && export UNWIND_MODE="$_qp_unwind_mode" +[[ -n "$_qp_pool" ]] && export POOL_CWUSDC_USDC_MAINNET="$_qp_pool" +[[ -n "$_qp_integration" ]] && export DODO_PMM_INTEGRATION_MAINNET="$_qp_integration" +[[ -n "$_qp_pool_a" ]] && export UNWIND_TWO_HOP_POOL_A="$_qp_pool_a" +[[ -n "$_qp_pool_b" ]] && export UNWIND_TWO_HOP_POOL_B="$_qp_pool_b" +[[ -n "$_qp_mid_token" ]] && export UNWIND_TWO_HOP_MID_TOKEN="$_qp_mid_token" +[[ -n "$_qp_min_mid_out" ]] && export UNWIND_MIN_MID_OUT_RAW="$_qp_min_mid_out" +[[ -n "$_qp_min_out_pmm" ]] && export MIN_OUT_PMM="$_qp_min_out_pmm" +[[ -n "$_qp_min_out_unwind" ]] && export MIN_OUT_UNWIND="$_qp_min_out_unwind" +[[ -n "$_qp_fee_u24" ]] && export UNWIND_V3_FEE_U24="$_qp_fee_u24" +[[ -n "$_qp_dodo_pool" ]] && export UNWIND_DODO_POOL="$_qp_dodo_pool" +[[ -n "$_qp_v3_path" ]] && export UNWIND_V3_PATH_HEX="$_qp_v3_path" +[[ -n "$_qp_intermediate_token" ]] && export UNWIND_INTERMEDIATE_TOKEN="$_qp_intermediate_token" +[[ -n "$_qp_min_intermediate_out" ]] && export UNWIND_MIN_INTERMEDIATE_OUT_RAW="$_qp_min_intermediate_out" +[[ -n "$_qp_treasury_harvest" ]] && export QUOTE_PUSH_TREASURY_HARVEST="$_qp_treasury_harvest" +[[ -n "$_qp_treasury_holdback" ]] && export QUOTE_PUSH_TREASURY_GAS_HOLDBACK_TARGET_RAW="$_qp_treasury_holdback" + +unset _qp_private_key _qp_rpc _qp_receiver _qp_manager _qp_unwinder _qp_amount _qp_unwind_type _qp_unwind_mode +unset _qp_pool _qp_integration _qp_pool_a _qp_pool_b _qp_mid_token _qp_min_mid_out _qp_min_out_pmm +unset _qp_min_out_unwind _qp_fee_u24 _qp_dodo_pool _qp_v3_path _qp_intermediate_token _qp_min_intermediate_out +unset _qp_treasury_harvest _qp_treasury_holdback + +BROADCAST=() +if (($# == 0)); then + : +else + for a in "$@"; do + case "$a" in + --apply) BROADCAST=(--broadcast) ;; + --dry-run) BROADCAST=() ;; + *) + echo "[fail] unknown arg: $a" >&2 + exit 2 + ;; + esac + done +fi + +require() { + local n="$1" + if [[ -z "${!n:-}" ]]; then + echo "[fail] missing required env: $n" >&2 + exit 1 + fi +} + +pick_latest_create_address() { + local script_name="$1" + local contract_name="$2" + local latest_json="${SMOM}/broadcast/${script_name}/1/run-latest.json" + if [[ ! -f "$latest_json" ]]; then + return 1 + fi + if ! command -v jq >/dev/null 2>&1; then + return 1 + fi + jq -r --arg contract "$contract_name" \ + '.transactions[]? | select(.transactionType == "CREATE" and .contractName == $contract) | .contractAddress' \ + "$latest_json" | tail -n1 +} + +pick_default_unwinder() { + local addr="" + PICK_DEFAULT_UNWINDER_ADDR="" + PICK_DEFAULT_UNWINDER_MODE="" + + addr="$(pick_latest_create_address "DeployTwoHopDodoIntegrationUnwinder.s.sol" "TwoHopDodoIntegrationUnwinder" || true)" + if [[ -n "$addr" && "$addr" != "null" ]]; then + PICK_DEFAULT_UNWINDER_ADDR="$addr" + PICK_DEFAULT_UNWINDER_MODE="4" + return 0 + fi + + addr="$(pick_latest_create_address "DeployDODOIntegrationExternalUnwinder.s.sol" "DODOIntegrationExternalUnwinder" || true)" + if [[ -n "$addr" && "$addr" != "null" ]]; then + PICK_DEFAULT_UNWINDER_ADDR="$addr" + PICK_DEFAULT_UNWINDER_MODE="1" + return 0 + fi + + addr="$(pick_latest_create_address "DeployUniswapV3ExternalUnwinder.s.sol" "UniswapV3ExternalUnwinder" || true)" + if [[ -n "$addr" && "$addr" != "null" ]]; then + PICK_DEFAULT_UNWINDER_ADDR="$addr" + PICK_DEFAULT_UNWINDER_MODE="0" + return 0 + fi + + addr="$(pick_latest_create_address "DeployDODOToUniswapV3MultiHopExternalUnwinder.s.sol" "DODOToUniswapV3MultiHopExternalUnwinder" || true)" + if [[ -n "$addr" && "$addr" != "null" ]]; then + PICK_DEFAULT_UNWINDER_ADDR="$addr" + PICK_DEFAULT_UNWINDER_MODE="5" + return 0 + fi + + return 1 +} + +UNW="${QUOTE_PUSH_UNWINDER_TYPE:-}" +if [[ -z "${AAVE_QUOTE_PUSH_RECEIVER_MAINNET:-}" ]]; then + inferred_receiver="$(pick_latest_create_address "DeployAaveQuotePushFlashReceiver.s.sol" "AaveQuotePushFlashReceiver" || true)" + export AAVE_QUOTE_PUSH_RECEIVER_MAINNET="${inferred_receiver:-$DEFAULT_AAVE_QUOTE_PUSH_RECEIVER_MAINNET}" +fi + +if [[ -z "${POOL_CWUSDC_USDC_MAINNET:-}" || "${_qp_pool:-}" == "" ]]; then + export POOL_CWUSDC_USDC_MAINNET="$DEFAULT_POOL_CWUSDC_USDC_MAINNET" +fi + +if [[ -z "${FLASH_QUOTE_AMOUNT_RAW:-}" ]]; then + export FLASH_QUOTE_AMOUNT_RAW=200000 +fi + +if [[ -z "${MIN_OUT_PMM:-}" ]]; then + export MIN_OUT_PMM=1 +fi + +if [[ -z "${QUOTE_PUSH_EXTERNAL_UNWINDER_MAINNET:-}" && -n "$UNW" ]]; then + unwind_script="" + unwind_contract="" + case "$UNW" in + univ3) + unwind_script="DeployUniswapV3ExternalUnwinder.s.sol" + unwind_contract="UniswapV3ExternalUnwinder" + export UNWIND_MODE="${UNWIND_MODE:-0}" + ;; + dodo) + unwind_script="DeployDODOIntegrationExternalUnwinder.s.sol" + unwind_contract="DODOIntegrationExternalUnwinder" + export UNWIND_MODE="${UNWIND_MODE:-1}" + ;; + two_hop_dodo) + unwind_script="DeployTwoHopDodoIntegrationUnwinder.s.sol" + unwind_contract="TwoHopDodoIntegrationUnwinder" + export UNWIND_MODE="${UNWIND_MODE:-4}" + ;; + dodo_univ3) + unwind_script="DeployDODOToUniswapV3MultiHopExternalUnwinder.s.sol" + unwind_contract="DODOToUniswapV3MultiHopExternalUnwinder" + export UNWIND_MODE="${UNWIND_MODE:-5}" + ;; + *) + echo "[fail] QUOTE_PUSH_UNWINDER_TYPE must be univ3, dodo, two_hop_dodo, or dodo_univ3 when set" >&2 + exit 1 + ;; + esac + + inferred_unwinder="$(pick_latest_create_address "$unwind_script" "$unwind_contract" || true)" + if [[ -n "$inferred_unwinder" && "$inferred_unwinder" != "null" ]]; then + export QUOTE_PUSH_EXTERNAL_UNWINDER_MAINNET="$inferred_unwinder" + fi +fi + +if [[ -z "${QUOTE_PUSH_EXTERNAL_UNWINDER_MAINNET:-}" ]]; then + if pick_default_unwinder; then + if [[ -n "$PICK_DEFAULT_UNWINDER_ADDR" && "$PICK_DEFAULT_UNWINDER_ADDR" != "null" ]]; then + export QUOTE_PUSH_EXTERNAL_UNWINDER_MAINNET="$PICK_DEFAULT_UNWINDER_ADDR" + export UNWIND_MODE="$PICK_DEFAULT_UNWINDER_MODE" + fi + fi +fi + +if [[ "${UNWIND_MODE:-}" == "4" ]]; then + export UNWIND_TWO_HOP_POOL_A="${UNWIND_TWO_HOP_POOL_A:-0xe944b7Cb012A0820c07f54D51e92f0e1C74168DB}" + export UNWIND_TWO_HOP_POOL_B="${UNWIND_TWO_HOP_POOL_B:-0x27f3aE7EE71Be3d77bAf17d4435cF8B895DD25D2}" + export UNWIND_TWO_HOP_MID_TOKEN="${UNWIND_TWO_HOP_MID_TOKEN:-0xaF5017d0163ecb99d9B5D94e3b4D7b09Af44D8AE}" + export UNWIND_MIN_MID_OUT_RAW="${UNWIND_MIN_MID_OUT_RAW:-1}" +elif [[ "${UNWIND_MODE:-}" == "5" ]]; then + export UNWIND_DODO_POOL="${UNWIND_DODO_POOL:-0xCC0fd27A40775c9AfcD2BBd3f7c902b0192c247A}" + export UNWIND_INTERMEDIATE_TOKEN="${UNWIND_INTERMEDIATE_TOKEN:-0xdAC17F958D2ee523a2206206994597C13D831ec7}" + export UNWIND_MIN_INTERMEDIATE_OUT_RAW="${UNWIND_MIN_INTERMEDIATE_OUT_RAW:-1}" +fi + +require ETHEREUM_MAINNET_RPC +require PRIVATE_KEY +require QUOTE_PUSH_TREASURY_MANAGER_MAINNET +require AAVE_QUOTE_PUSH_RECEIVER_MAINNET +require QUOTE_PUSH_EXTERNAL_UNWINDER_MAINNET +require DODO_PMM_INTEGRATION_MAINNET +require FLASH_QUOTE_AMOUNT_RAW + +UM="${UNWIND_MODE:-0}" +if [[ "$UM" == "0" ]]; then + require UNWIND_V3_FEE_U24 +elif [[ "$UM" == "1" ]]; then + require UNWIND_DODO_POOL +elif [[ "$UM" == "2" ]]; then + require UNWIND_V3_PATH_HEX +elif [[ "$UM" == "4" ]]; then + require UNWIND_TWO_HOP_POOL_A + require UNWIND_TWO_HOP_POOL_B + require UNWIND_TWO_HOP_MID_TOKEN +elif [[ "$UM" == "5" ]]; then + require UNWIND_DODO_POOL + require UNWIND_INTERMEDIATE_TOKEN + require UNWIND_V3_PATH_HEX +else + echo "[fail] UNWIND_MODE must be 0, 1, 2, 4, or 5" >&2 + exit 1 +fi + +echo "receiver=$AAVE_QUOTE_PUSH_RECEIVER_MAINNET" +echo "manager=$QUOTE_PUSH_TREASURY_MANAGER_MAINNET" +echo "unwinder=$QUOTE_PUSH_EXTERNAL_UNWINDER_MAINNET" +echo "flash_quote_amount_raw=$FLASH_QUOTE_AMOUNT_RAW unwind_mode=$UM" +echo "gas_holdback_target_raw=${QUOTE_PUSH_TREASURY_GAS_HOLDBACK_TARGET_RAW:-0}" + +( + cd "$SMOM" + forge script script/flash/RunManagedMainnetAaveCwusdcUsdcQuotePushCycle.s.sol:RunManagedMainnetAaveCwusdcUsdcQuotePushCycle \ + --rpc-url "$ETHEREUM_MAINNET_RPC" \ + "${BROADCAST[@]}" \ + -vvvv +) diff --git a/scripts/deployment/run-mainnet-cwusdc-flash-quote-push-model-sweep.sh b/scripts/deployment/run-mainnet-cwusdc-flash-quote-push-model-sweep.sh index 5cffb543..085cebcb 100755 --- a/scripts/deployment/run-mainnet-cwusdc-flash-quote-push-model-sweep.sh +++ b/scripts/deployment/run-mainnet-cwusdc-flash-quote-push-model-sweep.sh @@ -9,6 +9,7 @@ set -euo pipefail # FLASH_MODEL_SCAN_SIZES — comma-separated gross flash quote sizes in raw units (default 5e6,1e7,2e7) # PMM_FLASH_EXIT_PRICE_CMD — passed to node --external-exit-price-cmd (default: printf 1.02) # GAS_GWEI, NATIVE_PRICE — optional overrides for the economics model +# If GAS_GWEI is unset, the script reads the live mainnet gas price and converts it to gwei. # FLASH_MODEL_GAS_TX_COUNT, FLASH_MODEL_GAS_PER_TX — gas row (defaults 3 / 250000) # FLASH_MODEL_MAX_POST_TRADE_DEV_BPS — deviation guard (default 500; raise only for stress math, not production) # @@ -40,7 +41,7 @@ INTEGRATION="${DODO_PMM_INTEGRATION_MAINNET:-}" POOL="${POOL_CWUSDC_USDC_MAINNET:-0x69776fc607e9edA8042e320e7e43f54d06c68f0E}" SCAN="${FLASH_MODEL_SCAN_SIZES:-5000000,10000000,25000000}" EXIT_CMD="${PMM_FLASH_EXIT_PRICE_CMD:-printf 1.02}" -GAS_GWEI="${GAS_GWEI:-40}" +GAS_GWEI="${GAS_GWEI:-}" NATIVE_PRICE="${NATIVE_PRICE:-3200}" GAS_TXN="${FLASH_MODEL_GAS_TX_COUNT:-3}" GAS_PER="${FLASH_MODEL_GAS_PER_TX:-250000}" @@ -62,6 +63,15 @@ out="$(cast call "$POOL" 'getVaultReserve()(uint256,uint256)' --rpc-url "$RPC_UR B="$(printf '%s\n' "$out" | sed -n '1p' | awk '{print $1}')" Q="$(printf '%s\n' "$out" | sed -n '2p' | awk '{print $1}')" +if [[ -z "$GAS_GWEI" ]]; then + gas_price_wei="$(cast gas-price --rpc-url "$RPC_URL" | awk '{print $1}')" + GAS_GWEI="$(python3 - "$gas_price_wei" <<'PY' +import sys +print(f"{int(sys.argv[1]) / 1_000_000_000:.9f}") +PY +)" +fi + PMM_JS="${PROXMOX_ROOT}/scripts/analytics/pmm-flash-push-break-even.mjs" echo "=== Flash quote-push model sweep (dry-run only) ===" @@ -92,3 +102,4 @@ for x in "${sizes[@]}"; do done echo "Live execution: deploy-mainnet-aave-quote-push-stack.sh then run-mainnet-aave-cwusdc-quote-push-once.sh (see plan-mainnet-cwusdc-flash-quote-push-rebalance.sh)" +echo "Receiver surplus accounting: bash scripts/verify/report-mainnet-aave-quote-push-surplus-accounting.sh" diff --git a/scripts/deployment/sweep-mainnet-aave-quote-push-receiver-surplus.sh b/scripts/deployment/sweep-mainnet-aave-quote-push-receiver-surplus.sh new file mode 100644 index 00000000..b2799698 --- /dev/null +++ b/scripts/deployment/sweep-mainnet-aave-quote-push-receiver-surplus.sh @@ -0,0 +1,166 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Sweep retained surplus from a deployed Mainnet Aave quote-push receiver. +# Default: simulation only. Use --apply to broadcast. +# +# Env: +# PRIVATE_KEY, ETHEREUM_MAINNET_RPC, AAVE_QUOTE_PUSH_RECEIVER_MAINNET +# QUOTE_PUSH_SURPLUS_TOKEN_MAINNET optional; defaults to mainnet USDC +# QUOTE_PUSH_SURPLUS_RECIPIENT optional; defaults to deployer derived from PRIVATE_KEY +# QUOTE_PUSH_SURPLUS_RESERVE_RAW optional; keep this much on the receiver when sweeping surplus mode +# QUOTE_PUSH_SURPLUS_EXACT_AMOUNT_RAW optional; if > 0, sweep this exact amount instead of balance - reserve +# +# Usage: +# source scripts/lib/load-project-env.sh +# bash scripts/deployment/sweep-mainnet-aave-quote-push-receiver-surplus.sh --dry-run +# QUOTE_PUSH_SURPLUS_RESERVE_RAW=50000 bash scripts/deployment/sweep-mainnet-aave-quote-push-receiver-surplus.sh --apply + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROXMOX_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)" +SMOM="${PROXMOX_ROOT}/smom-dbis-138" +DEFAULT_USDC_MAINNET="0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" + +_qp_private_key="${PRIVATE_KEY-}" +_qp_rpc="${ETHEREUM_MAINNET_RPC-}" +_qp_receiver="${AAVE_QUOTE_PUSH_RECEIVER_MAINNET-}" +_qp_token="${QUOTE_PUSH_SURPLUS_TOKEN_MAINNET-}" +_qp_recipient="${QUOTE_PUSH_SURPLUS_RECIPIENT-}" +_qp_reserve="${QUOTE_PUSH_SURPLUS_RESERVE_RAW-}" +_qp_exact="${QUOTE_PUSH_SURPLUS_EXACT_AMOUNT_RAW-}" + +# shellcheck disable=SC1091 +source "${PROXMOX_ROOT}/scripts/lib/load-project-env.sh" 2>/dev/null || true +# shellcheck disable=SC1091 +source "${SMOM}/scripts/load-env.sh" >/dev/null 2>&1 || true + +[[ -n "$_qp_private_key" ]] && export PRIVATE_KEY="$_qp_private_key" +[[ -n "$_qp_rpc" ]] && export ETHEREUM_MAINNET_RPC="$_qp_rpc" +[[ -n "$_qp_receiver" ]] && export AAVE_QUOTE_PUSH_RECEIVER_MAINNET="$_qp_receiver" +[[ -n "$_qp_token" ]] && export QUOTE_PUSH_SURPLUS_TOKEN_MAINNET="$_qp_token" +[[ -n "$_qp_recipient" ]] && export QUOTE_PUSH_SURPLUS_RECIPIENT="$_qp_recipient" +[[ -n "$_qp_reserve" ]] && export QUOTE_PUSH_SURPLUS_RESERVE_RAW="$_qp_reserve" +[[ -n "$_qp_exact" ]] && export QUOTE_PUSH_SURPLUS_EXACT_AMOUNT_RAW="$_qp_exact" + +unset _qp_private_key _qp_rpc _qp_receiver _qp_token _qp_recipient _qp_reserve _qp_exact + +require_cmd() { + command -v "$1" >/dev/null 2>&1 || { + echo "[fail] missing required command: $1" >&2 + exit 1 + } +} + +require_cmd cast +require_cmd forge + +require_env() { + local name="$1" + if [[ -z "${!name:-}" ]]; then + echo "[fail] missing required env: $name" >&2 + exit 1 + fi +} + +pick_latest_receiver() { + local latest_json="${SMOM}/broadcast/DeployAaveQuotePushFlashReceiver.s.sol/1/run-latest.json" + if [[ ! -f "$latest_json" ]] || ! command -v jq >/dev/null 2>&1; then + return 1 + fi + jq -r '.transactions[]? | select(.transactionType == "CREATE" and .contractName == "AaveQuotePushFlashReceiver") | .contractAddress' \ + "$latest_json" | tail -n1 +} + +MODE="dry-run" +BROADCAST=() +for arg in "$@"; do + case "$arg" in + --dry-run) MODE="dry-run"; BROADCAST=() ;; + --apply) MODE="apply"; BROADCAST=(--broadcast) ;; + *) + echo "[fail] unknown arg: $arg (use --dry-run or --apply)" >&2 + exit 2 + ;; + esac +done + +require_env PRIVATE_KEY +require_env ETHEREUM_MAINNET_RPC +if [[ -z "${AAVE_QUOTE_PUSH_RECEIVER_MAINNET:-}" ]]; then + inferred_receiver="$(pick_latest_receiver || true)" + if [[ -n "$inferred_receiver" && "$inferred_receiver" != "null" ]]; then + export AAVE_QUOTE_PUSH_RECEIVER_MAINNET="$inferred_receiver" + fi +fi +require_env AAVE_QUOTE_PUSH_RECEIVER_MAINNET + +TOKEN="${QUOTE_PUSH_SURPLUS_TOKEN_MAINNET:-$DEFAULT_USDC_MAINNET}" +DEPLOYER="$(cast wallet address --private-key "$PRIVATE_KEY")" +RECIPIENT="${QUOTE_PUSH_SURPLUS_RECIPIENT:-$DEPLOYER}" +RESERVE_RAW="${QUOTE_PUSH_SURPLUS_RESERVE_RAW:-0}" +EXACT_RAW="${QUOTE_PUSH_SURPLUS_EXACT_AMOUNT_RAW:-0}" +receiver_owner="$(cast call "$AAVE_QUOTE_PUSH_RECEIVER_MAINNET" 'owner()(address)' --rpc-url "$ETHEREUM_MAINNET_RPC" 2>/dev/null | awk '{print $1}' || true)" + +if [[ -z "$receiver_owner" ]]; then + cat >&2 <&2 + exit 1 +fi + +receiver_balance_raw="$( + cast call "$TOKEN" 'balanceOf(address)(uint256)' "$AAVE_QUOTE_PUSH_RECEIVER_MAINNET" --rpc-url "$ETHEREUM_MAINNET_RPC" \ + | awk '{print $1}' +)" + +if (( EXACT_RAW > 0 )); then + if (( receiver_balance_raw < EXACT_RAW )); then + echo "[fail] receiver balance too small for exact sweep: have=$receiver_balance_raw need=$EXACT_RAW" >&2 + exit 1 + fi + sweep_raw="$EXACT_RAW" +else + if (( receiver_balance_raw <= RESERVE_RAW )); then + echo "[stop] nothing to sweep: receiver_balance_raw=$receiver_balance_raw reserve_raw=$RESERVE_RAW" >&2 + exit 3 + fi + sweep_raw=$((receiver_balance_raw - RESERVE_RAW)) +fi + +echo "=== sweep-mainnet-aave-quote-push-receiver-surplus ($MODE) ===" +echo "receiver=$AAVE_QUOTE_PUSH_RECEIVER_MAINNET" +echo "receiver_owner=$receiver_owner" +echo "token=$TOKEN" +echo "recipient=$RECIPIENT" +echo "receiver_balance_raw=$receiver_balance_raw" +echo "reserve_raw=$RESERVE_RAW" +echo "exact_raw=$EXACT_RAW" +echo "sweep_raw=$sweep_raw" + +( + cd "$SMOM" + forge script script/flash/SweepAaveQuotePushFlashReceiverSurplus.s.sol:SweepAaveQuotePushFlashReceiverSurplus \ + --rpc-url "$ETHEREUM_MAINNET_RPC" \ + "${BROADCAST[@]}" \ + -vvvv +) + +if [[ "$MODE" == "apply" ]]; then + receiver_after="$( + cast call "$TOKEN" 'balanceOf(address)(uint256)' "$AAVE_QUOTE_PUSH_RECEIVER_MAINNET" --rpc-url "$ETHEREUM_MAINNET_RPC" \ + | awk '{print $1}' + )" + recipient_after="$( + cast call "$TOKEN" 'balanceOf(address)(uint256)' "$RECIPIENT" --rpc-url "$ETHEREUM_MAINNET_RPC" \ + | awk '{print $1}' + )" + echo "receiver_balance_after_raw=$receiver_after" + echo "recipient_balance_after_raw=$recipient_after" +fi diff --git a/scripts/diagnose-and-fix-migration-storage.sh b/scripts/diagnose-and-fix-migration-storage.sh index c60dc1ea..c4b0f367 100755 --- a/scripts/diagnose-and-fix-migration-storage.sh +++ b/scripts/diagnose-and-fix-migration-storage.sh @@ -2,8 +2,19 @@ # Diagnose and Fix Storage Issues for Proxmox Container Migrations # This script checks storage configuration and fixes issues to enable migrations +# HISTORICAL SCRIPT +# Targets migration-era CTs (1504/2503/2504/6201) and includes embedded passwords from that period. +# Keep for reference only; do not treat as a live runbook. + set -euo pipefail +if [[ "${HISTORICAL_ALLOW_RUN:-0}" != "1" ]]; then + echo "HISTORICAL: diagnose-and-fix-migration-storage.sh is a migration-era helper, not a current operator script." >&2 + echo "Use current Proxmox storage and rebalance runbooks instead." >&2 + echo "Set HISTORICAL_ALLOW_RUN=1 only if you intentionally need this legacy script." >&2 + exit 1 +fi + # Load IP configuration SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" @@ -490,4 +501,3 @@ main() { } main "$@" - diff --git a/scripts/fix-besu-installation.sh b/scripts/fix-besu-installation.sh index 4c79aa72..9c007f7e 100755 --- a/scripts/fix-besu-installation.sh +++ b/scripts/fix-besu-installation.sh @@ -1,25 +1,62 @@ #!/usr/bin/env bash -# Fix Besu installation on all nodes +# Fix Besu installation on selected nodes. set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" -source "$PROJECT_ROOT/config/ip-addresses.conf" +source "$PROJECT_ROOT/scripts/lib/load-project-env.sh" -get_host_for_vmid() { - local vmid=$1 - if [[ "$vmid" =~ ^(1505|1506|1507|1508)$ ]]; then - echo "${PROXMOX_HOST_ML110}" - elif [[ "$vmid" =~ ^(2500|2501|2502|2503|2504|2505)$ ]]; then - echo "${PROXMOX_HOST_R630_01}" - else - echo "${PROXMOX_HOST_R630_01}" - fi +APPLY=false +TARGET_VMIDS=() + +usage() { + cat <<'EOF' +Usage: ./scripts/fix-besu-installation.sh --vmid [--vmid ...] [--apply] + +Options: + --vmid Required. Limit fix to one or more VMIDs. + --apply Perform the install fix. Without this flag, the script prints the target VMIDs and exits. +EOF } +while [[ $# -gt 0 ]]; do + case "$1" in + --vmid) + [[ $# -ge 2 ]] || { usage >&2; exit 2; } + TARGET_VMIDS+=("$2") + shift 2 + ;; + --apply) + APPLY=true + shift + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Unknown argument: $1" >&2 + usage >&2 + exit 2 + ;; + esac +done + +[[ ${#TARGET_VMIDS[@]} -gt 0 ]] || { usage >&2; exit 2; } + +if ! $APPLY; then + echo "Dry-run only. Target VMIDs:" + for vmid in "${TARGET_VMIDS[@]}"; do + echo " VMID $vmid on $(get_host_for_vmid "$vmid")" + done + echo "Re-run with --apply to perform the Besu installation fix." + exit 0 +fi + fix_besu() { local vmid=$1 - local host=$(get_host_for_vmid $vmid) + local host + host="$(get_host_for_vmid "$vmid")" ssh -o StrictHostKeyChecking=no root@${host} "pct exec $vmid -- bash -c ' cd /opt @@ -37,8 +74,8 @@ fix_besu() { '" 2>&1 | grep -E "(Extracting|fixed)" || true } -for vmid in 1505 1506 2500 2501 2502 1507 1508 2503 2504 2505; do - fix_besu $vmid & +for vmid in "${TARGET_VMIDS[@]}"; do + fix_besu "$vmid" & done wait -echo "Besu installation fixed on all nodes" +echo "Besu installation fix attempted on selected nodes" diff --git a/scripts/flush-all-mempools-proxmox.sh b/scripts/flush-all-mempools-proxmox.sh index d0b5ce93..109218df 100755 --- a/scripts/flush-all-mempools-proxmox.sh +++ b/scripts/flush-all-mempools-proxmox.sh @@ -1,10 +1,16 @@ #!/usr/bin/env bash -# Flush mempools on all Besu nodes (validators, sentries, RPC) -# This script must be run on the Proxmox host -# Usage: ./flush-all-mempools-proxmox.sh +# Flush mempools on selected Besu nodes (validators, sentries, RPC) +# This script must be run on the Proxmox host. +# Usage: +# ./flush-all-mempools-proxmox.sh --vmid 2101 +# ./flush-all-mempools-proxmox.sh --apply --vmid 2101 set -euo pipefail +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +source "${PROJECT_ROOT}/scripts/lib/load-project-env.sh" + # Colors RED='\033[0;31m' GREEN='\033[0;32m' @@ -25,16 +31,63 @@ if ! command -v pct &>/dev/null; then exit 1 fi -# All Besu nodes -VALIDATORS=(1000 1001 1002 1003 1004) -SENTRIES=(1500 1501 1502 1503) -RPC_NODES=(2500 2501 2502) +APPLY=false +TARGET_VMIDS=() + +usage() { + cat <<'EOF' +Usage: ./flush-all-mempools-proxmox.sh --vmid [--vmid ...] [--apply] + +Options: + --vmid Required. Limit restart to one or more VMIDs. + --apply Restart services. Without this flag, the script prints the target VMIDs and exits. +EOF +} + +while [[ $# -gt 0 ]]; do + case "$1" in + --vmid) + [[ $# -ge 2 ]] || { usage >&2; exit 2; } + TARGET_VMIDS+=("$2") + shift 2 + ;; + --apply) + APPLY=true + shift + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Unknown argument: $1" >&2 + usage >&2 + exit 2 + ;; + esac +done + +[[ ${#TARGET_VMIDS[@]} -gt 0 ]] || { log_error "At least one --vmid is required."; usage >&2; exit 2; } + +declare -A SERVICE_BY_VMID +for vmid in 1000 1001 1002 1003 1004; do SERVICE_BY_VMID[$vmid]="besu-validator.service"; done +for vmid in 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510; do SERVICE_BY_VMID[$vmid]="besu-sentry.service"; done +for vmid in 2101 2102 2103 2201 2301 2303 2304 2305 2306 2307 2308 2400 2401 2402 2403 2420 2430 2440 2460 2470 2480; do SERVICE_BY_VMID[$vmid]="besu-rpc.service"; done echo "=========================================" echo "Flush All Besu Mempools" echo "=========================================" echo "" +if ! $APPLY; then + log_warn "Dry-run only. Target VMIDs:" + for vmid in "${TARGET_VMIDS[@]}"; do + log_info " VMID $vmid service ${SERVICE_BY_VMID[$vmid]:-unknown}" + done + log_info "Re-run with --apply to restart services." + exit 0 +fi + # Function to restart Besu service restart_besu_service() { local vmid=$1 @@ -57,48 +110,19 @@ restart_besu_service() { fi } -# Restart validators -log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -log_info "Validators (1000-1004)" -log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -VALIDATOR_SUCCESS=0 -for vmid in "${VALIDATORS[@]}"; do - if restart_besu_service "$vmid" "besu-validator.service"; then - ((VALIDATOR_SUCCESS++)) +SUCCESS=0 +for vmid in "${TARGET_VMIDS[@]}"; do + service="${SERVICE_BY_VMID[$vmid]:-besu.service}" + if restart_besu_service "$vmid" "$service"; then + ((SUCCESS++)) fi done -log_info "Validators restarted: $VALIDATOR_SUCCESS/${#VALIDATORS[@]}" -echo "" - -# Restart sentries -log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -log_info "Sentries (1500-1503)" -log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -SENTRY_SUCCESS=0 -for vmid in "${SENTRIES[@]}"; do - if restart_besu_service "$vmid" "besu-sentry.service"; then - ((SENTRY_SUCCESS++)) - fi -done -log_info "Sentries restarted: $SENTRY_SUCCESS/${#SENTRIES[@]}" -echo "" - -# Restart RPC nodes -log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -log_info "RPC Nodes (2500-2502)" -log_info "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" -RPC_SUCCESS=0 -for vmid in "${RPC_NODES[@]}"; do - if restart_besu_service "$vmid" "besu-rpc.service"; then - ((RPC_SUCCESS++)) - fi -done -log_info "RPC nodes restarted: $RPC_SUCCESS/${#RPC_NODES[@]}" +log_info "Nodes restarted: $SUCCESS/${#TARGET_VMIDS[@]}" echo "" # Summary -TOTAL_SUCCESS=$((VALIDATOR_SUCCESS + SENTRY_SUCCESS + RPC_SUCCESS)) -TOTAL_NODES=$((${#VALIDATORS[@]} + ${#SENTRIES[@]} + ${#RPC_NODES[@]})) +TOTAL_SUCCESS=$SUCCESS +TOTAL_NODES=${#TARGET_VMIDS[@]} echo "=========================================" echo "Summary" @@ -112,7 +136,7 @@ sleep 15 log_info "Verifying services are running..." VERIFIED=0 -for vmid in "${VALIDATORS[@]}" "${SENTRIES[@]}" "${RPC_NODES[@]}"; do +for vmid in "${TARGET_VMIDS[@]}"; do if pct status "$vmid" 2>/dev/null | grep -q "running"; then if pct exec "$vmid" -- pgrep -f "besu" >/dev/null 2>&1; then log_success "✓ VMID $vmid: Besu running" @@ -134,4 +158,3 @@ log_info "Next steps:" log_info " 1. Wait for all nodes to sync" log_info " 2. Run: ./scripts/configure-ethereum-mainnet-final.sh" log_info "" - diff --git a/scripts/generate-jwt-token-for-container.sh b/scripts/generate-jwt-token-for-container.sh index b670f2c2..a8f42bd5 100755 --- a/scripts/generate-jwt-token-for-container.sh +++ b/scripts/generate-jwt-token-for-container.sh @@ -4,13 +4,10 @@ set -euo pipefail -# Load IP configuration SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" -source "${PROJECT_ROOT}/config/ip-addresses.conf" 2>/dev/null || true +source "${PROJECT_ROOT}/scripts/lib/load-project-env.sh" - -PROXMOX_HOST="${PROXMOX_HOST:-192.168.11.10}" VMID="${1:-}" USERNAME="${2:-rpc-user}" EXPIRY_DAYS="${3:-365}" @@ -28,10 +25,15 @@ error() { echo -e "${RED}[ERROR]${NC} $1"; } if [ -z "$VMID" ]; then error "Usage: $0 [expiry_days]" - error "Example: $0 2503 ali-full-access 365" + error "Example: $0 2101 fireblocks-access 365" exit 1 fi +PROXMOX_HOST="$(get_host_for_vmid "$VMID")" +if [ "$VMID" != "2101" ]; then + warn "VMID $VMID is non-standard for the JWT-protected private RPC; current documented target is VMID 2101." +fi + # Get JWT secret from container or saved file JWT_SECRET="" @@ -115,24 +117,12 @@ PYTHON_SCRIPT echo "" echo "Token: $TOKEN" echo "" - - # Get IP address - declare -A RPC_IPS=( - [2503]="${RPC_ALI_1_ALT:-${RPC_ALI_1_ALT:-${RPC_ALI_1_ALT:-192.168.11.253}}}" - [2504]="${RPC_ALI_2_ALT:-${RPC_ALI_2_ALT:-${RPC_ALI_2_ALT:-192.168.11.254}}}" - [2505]="${RPC_LUIS_1:-${RPC_LUIS_1:-${RPC_LUIS_1:-192.168.11.255}}}" - [2506]="${RPC_LUIS_2:-${RPC_LUIS_2:-${RPC_LUIS_2:-192.168.11.202}}}" - [2507]="${RPC_PUTU_1:-${RPC_PUTU_1:-${RPC_PUTU_1:-192.168.11.203}}}" - [2508]="${RPC_PUTU_2:-${RPC_PUTU_2:-${RPC_PUTU_2:-192.168.11.204}}}" - ) - - IP="${RPC_IPS[$VMID]:-unknown}" - + echo "Usage:" echo " curl -k -H 'Authorization: Bearer $TOKEN' \\" echo " -H 'Content-Type: application/json' \\" echo " -d '{\"jsonrpc\":\"2.0\",\"method\":\"eth_chainId\",\"params\":[],\"id\":1}' \\" - echo " https://${IP}/" + echo " https://rpc-http-prv.d-bis.org/" echo "" exit 0 fi @@ -140,4 +130,3 @@ fi error "Failed to generate JWT token. Python3 is required." exit 1 - diff --git a/scripts/jwt-quick-reference.sh b/scripts/jwt-quick-reference.sh index a0ce5397..c691ec33 100755 --- a/scripts/jwt-quick-reference.sh +++ b/scripts/jwt-quick-reference.sh @@ -2,6 +2,11 @@ set -euo pipefail # Quick reference guide for JWT authentication +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +source "${PROJECT_ROOT}/scripts/lib/load-project-env.sh" +JWT_VMID="${JWT_VMID:-2101}" +JWT_HOST="$(get_host_for_vmid "$JWT_VMID")" cat <<'REF' ╔════════════════════════════════════════════════════════════════╗ @@ -20,10 +25,10 @@ Public (No Auth): 🔑 GENERATE TOKEN ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -./scripts/generate-jwt-token.sh [username] [expiry_days] +./scripts/generate-jwt-token-for-container.sh 2101 [username] [expiry_days] Example: - ./scripts/generate-jwt-token.sh my-app 30 + ./scripts/generate-jwt-token-for-container.sh 2101 my-app 30 🧪 TEST ENDPOINT ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ @@ -34,36 +39,35 @@ curl -k \ -d '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}' \ https://rpc-http-prv.d-bis.org +REF + +cat </dev/null || true - -ssh root@${PROXMOX_HOST_ML110:-192.168.11.10} "pct exec 2501 -- systemctl status nginx jwt-validator" +ssh root@${JWT_HOST} "pct exec ${JWT_VMID} -- systemctl status nginx jwt-validator" 📊 VIEW LOGS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ # Access logs -ssh root@${PROXMOX_HOST_ML110:-192.168.11.10} "pct exec 2501 -- tail -f /var/log/nginx/rpc-http-prv-access.log" +ssh root@${JWT_HOST} "pct exec ${JWT_VMID} -- tail -f /var/log/nginx/rpc-http-prv-access.log" # Error logs -ssh root@${PROXMOX_HOST_ML110:-192.168.11.10} "pct exec 2501 -- tail -f /var/log/nginx/rpc-http-prv-error.log" +ssh root@${JWT_HOST} "pct exec ${JWT_VMID} -- tail -f /var/log/nginx/rpc-http-prv-error.log" # JWT validator logs -ssh root@${PROXMOX_HOST_ML110:-192.168.11.10} "pct exec 2501 -- journalctl -u jwt-validator -f" +ssh root@${JWT_HOST} "pct exec ${JWT_VMID} -- journalctl -u jwt-validator -f" 🔧 TROUBLESHOOTING ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ # Restart services -ssh root@${PROXMOX_HOST_ML110:-192.168.11.10} "pct exec 2501 -- systemctl restart nginx jwt-validator" +ssh root@${JWT_HOST} "pct exec ${JWT_VMID} -- systemctl restart nginx jwt-validator" # Test nginx config -ssh root@${PROXMOX_HOST_ML110:-192.168.11.10} "pct exec 2501 -- nginx -t" +ssh root@${JWT_HOST} "pct exec ${JWT_VMID} -- nginx -t" # Check JWT secret -ssh root@${PROXMOX_HOST_ML110:-192.168.11.10} "pct exec 2501 -- cat /etc/nginx/jwt_secret" +ssh root@${JWT_HOST} "pct exec ${JWT_VMID} -- cat /etc/nginx/jwt_secret" 📚 DOCUMENTATION ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ @@ -71,4 +75,4 @@ docs/04-configuration/RPC_JWT_AUTHENTICATION.md docs/04-configuration/RPC_JWT_SETUP_COMPLETE.md docs/04-configuration/RPC_DNS_CONFIGURATION.md -REF +EOF diff --git a/scripts/maintenance/README.md b/scripts/maintenance/README.md index d66a541f..2a2c0d77 100644 --- a/scripts/maintenance/README.md +++ b/scripts/maintenance/README.md @@ -31,7 +31,7 @@ **ensure-legacy-monitor-networkd-via-ssh.sh** — SSHs to r630-01 and fixes the legacy `3000`-`3003` monitor/RPC-adjacent LXCs so `systemd-networkd` is enabled host-side and started in-guest. This is the safe path for unprivileged guests where `systemctl enable` fails from inside the CT. `--dry-run` / `--apply`; same `PROXMOX_SAFE_DEFAULTS` behavior as other guarded maintenance scripts. -**check-and-fix-explorer-lag.sh** — Checks RPC vs Blockscout block; if lag > threshold (default 500), runs `fix-explorer-indexer-lag.sh` (restart Blockscout). +**check-and-fix-explorer-lag.sh** — Checks both RPC vs Blockscout head lag and recent transaction visibility lag. If the explorer head is behind, or if recent on-chain non-empty blocks are present but the explorer’s latest indexed transaction trails them by more than the configured threshold, it runs `fix-explorer-indexer-lag.sh` (restart Blockscout). It does **not** restart for a genuinely quiet chain with empty recent head blocks. **schedule-explorer-lag-cron.sh** — Install cron for lag check-and-fix: every 6 hours (0, 6, 12, 18). Log: `logs/explorer-lag-fix.log`. Use `--show` to print the line, `--install` to add to crontab, `--remove` to remove. Run from a persistent host checkout; set `CRON_PROJECT_ROOT=/srv/proxmox` when installing on a Proxmox node. **All schedule-*.sh installers** — Refuse transient roots such as `/tmp/...`. Install from a persistent checkout only. diff --git a/scripts/maintenance/check-and-fix-explorer-lag.sh b/scripts/maintenance/check-and-fix-explorer-lag.sh index a7b530ab..06f09374 100644 --- a/scripts/maintenance/check-and-fix-explorer-lag.sh +++ b/scripts/maintenance/check-and-fix-explorer-lag.sh @@ -1,8 +1,12 @@ #!/usr/bin/env bash -# Check explorer indexer lag; if above threshold, run fix-explorer-indexer-lag.sh (restart Blockscout). +# Check explorer data-plane lag; if block lag or transaction visibility lag is high, +# run fix-explorer-indexer-lag.sh (restart Blockscout). # For use from cron. Run from project root. Requires LAN/SSH to r630-02 for the fix. # Usage: bash scripts/maintenance/check-and-fix-explorer-lag.sh -# Env: EXPLORER_INDEXER_LAG_THRESHOLD (default 500) +# Env: +# EXPLORER_INDEXER_LAG_THRESHOLD (default 500) +# EXPLORER_TX_VISIBILITY_LAG_BLOCK_THRESHOLD (default 32) +# EXPLORER_TX_VISIBILITY_SAMPLE_BLOCKS (default 128) set -euo pipefail @@ -14,6 +18,8 @@ IP_RPC_2201="${RPC_2201:-192.168.11.221}" IP_BLOCKSCOUT="${IP_BLOCKSCOUT:-192.168.11.140}" BLOCKSCOUT_API_PORT="${BLOCKSCOUT_API_PORT:-4000}" EXPLORER_INDEXER_LAG_THRESHOLD="${EXPLORER_INDEXER_LAG_THRESHOLD:-500}" +EXPLORER_TX_VISIBILITY_LAG_BLOCK_THRESHOLD="${EXPLORER_TX_VISIBILITY_LAG_BLOCK_THRESHOLD:-32}" +EXPLORER_TX_VISIBILITY_SAMPLE_BLOCKS="${EXPLORER_TX_VISIBILITY_SAMPLE_BLOCKS:-128}" get_rpc_block() { local hex @@ -32,8 +38,45 @@ get_explorer_block() { [ -n "$block" ] && echo "$block" } +get_explorer_latest_tx_block() { + local body block + body=$(curl -sf --max-time 10 "http://${IP_BLOCKSCOUT}:${BLOCKSCOUT_API_PORT}/api/v2/stats" 2>/dev/null || true) + [ -z "$body" ] && return + block=$(echo "$body" | jq -r '.freshness.latest_indexed_transaction.block_number // empty' 2>/dev/null || true) + [ -n "$block" ] && [ "$block" != "null" ] && echo "$block" +} + +get_recent_chain_activity() { + local latest="$1" + local newest_non_empty="" + local total_txs=0 + local non_empty_count=0 + local block_num block_json tx_count + + for ((offset=0; offset/dev/null || true) + [ -z "$block_json" ] && continue + tx_count=$(echo "$block_json" | jq -r '.result.transactions | length' 2>/dev/null || echo "") + [ -z "$tx_count" ] && continue + total_txs=$((total_txs + tx_count)) + if [ "$tx_count" -gt 0 ] 2>/dev/null; then + non_empty_count=$((non_empty_count + 1)) + if [ -z "$newest_non_empty" ]; then + newest_non_empty="$block_num" + fi + fi + done + + printf '%s %s %s\n' "${newest_non_empty:-}" "$non_empty_count" "$total_txs" +} + rpc_block=$(get_rpc_block) explorer_block=$(get_explorer_block) +explorer_latest_tx_block=$(get_explorer_latest_tx_block) if [ -z "$rpc_block" ] || [ -z "$explorer_block" ]; then echo "$(date -Iseconds) SKIP (RPC or Blockscout unreachable)" @@ -42,9 +85,31 @@ fi lag=$((rpc_block - explorer_block)) if [ "$lag" -le "${EXPLORER_INDEXER_LAG_THRESHOLD}" ] 2>/dev/null; then - echo "$(date -Iseconds) OK lag=$lag (threshold=${EXPLORER_INDEXER_LAG_THRESHOLD})" + echo "$(date -Iseconds) OK block_lag=$lag (threshold=${EXPLORER_INDEXER_LAG_THRESHOLD})" +else + echo "$(date -Iseconds) BLOCK_LAG $lag > ${EXPLORER_INDEXER_LAG_THRESHOLD} — running fix" + bash "$PROJECT_ROOT/scripts/fix-explorer-indexer-lag.sh" 2>&1 || true exit 0 fi -echo "$(date -Iseconds) LAG $lag > ${EXPLORER_INDEXER_LAG_THRESHOLD} — running fix" -bash "$PROJECT_ROOT/scripts/fix-explorer-indexer-lag.sh" 2>&1 || true +read -r newest_non_empty recent_non_empty_count recent_tx_total <<<"$(get_recent_chain_activity "$rpc_block")" + +if [ -z "$newest_non_empty" ]; then + echo "$(date -Iseconds) QUIET_CHAIN sample_blocks=${EXPLORER_TX_VISIBILITY_SAMPLE_BLOCKS} non_empty=0 txs=0" + exit 0 +fi + +if [ -z "$explorer_latest_tx_block" ]; then + echo "$(date -Iseconds) TX_VISIBILITY missing explorer latest tx while chain shows recent txs (newest_non_empty=$newest_non_empty) — running fix" + bash "$PROJECT_ROOT/scripts/fix-explorer-indexer-lag.sh" 2>&1 || true + exit 0 +fi + +tx_visibility_gap=$((newest_non_empty - explorer_latest_tx_block)) +if [ "$tx_visibility_gap" -gt "${EXPLORER_TX_VISIBILITY_LAG_BLOCK_THRESHOLD}" ] 2>/dev/null; then + echo "$(date -Iseconds) TX_VISIBILITY_LAG gap=$tx_visibility_gap newest_non_empty=$newest_non_empty explorer_latest_tx=$explorer_latest_tx_block sample_non_empty=$recent_non_empty_count sample_txs=$recent_tx_total — running fix" + bash "$PROJECT_ROOT/scripts/fix-explorer-indexer-lag.sh" 2>&1 || true + exit 0 +fi + +echo "$(date -Iseconds) OK tx_visibility_gap=$tx_visibility_gap newest_non_empty=$newest_non_empty explorer_latest_tx=$explorer_latest_tx_block sample_non_empty=$recent_non_empty_count sample_txs=$recent_tx_total" diff --git a/scripts/maintenance/diagnose-and-fix-502s-via-ssh.sh b/scripts/maintenance/diagnose-and-fix-502s-via-ssh.sh index 32483307..75252c3d 100755 --- a/scripts/maintenance/diagnose-and-fix-502s-via-ssh.sh +++ b/scripts/maintenance/diagnose-and-fix-502s-via-ssh.sh @@ -2,7 +2,7 @@ # Deep dive: diagnose and fix every 502 from E2E routing. # For each known backend (domain → IP:port), SSH to Proxmox, check container + port, fix. # -# Usage: ./scripts/maintenance/diagnose-and-fix-502s-via-ssh.sh [--dry-run] [--diagnose-only] +# Usage: ./scripts/maintenance/diagnose-and-fix-502s-via-ssh.sh [--apply] [--dry-run] [--diagnose-only] # Requires: SSH to r630-01, r630-02, ml110 (key-based). set -euo pipefail @@ -10,12 +10,14 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" [[ -f "${PROJECT_ROOT}/scripts/lib/load-project-env.sh" ]] && source "${PROJECT_ROOT}/scripts/lib/load-project-env.sh" 2>/dev/null || true [[ -f "${PROJECT_ROOT}/config/ip-addresses.conf" ]] && source "${PROJECT_ROOT}/config/ip-addresses.conf" 2>/dev/null || true -# HYBX RPC 2503,2504,2505 are on ML110 per get_host_for_vmid -type get_host_for_vmid &>/dev/null && HYBX_HOST="$(get_host_for_vmid 2503)" || HYBX_HOST="$R630_01" -DRY_RUN=false +DRY_RUN=true DIAGNOSE_ONLY=false -for a in "$@"; do [[ "$a" == "--dry-run" ]] && DRY_RUN=true; [[ "$a" == "--diagnose-only" ]] && DIAGNOSE_ONLY=true; done +for a in "$@"; do + [[ "$a" == "--dry-run" ]] && DRY_RUN=true + [[ "$a" == "--apply" ]] && DRY_RUN=false + [[ "$a" == "--diagnose-only" ]] && DIAGNOSE_ONLY=true +done R630_01="${PROXMOX_HOST_R630_01:-192.168.11.11}" R630_02="${PROXMOX_HOST_R630_02:-192.168.11.12}" @@ -25,7 +27,7 @@ ML110="${PROXMOX_HOST_ML110:-192.168.11.10}" # DBIS (r630-01) # rpc-http-prv (r630-01) # MIM4U www (r630-02) -# Alltra/HYBX RPC (r630-01 per BESU_NODES) +# Edge RPC (r630-01) # Cacti-alltra/hybx - IPs .177 and .251 (VMID TBD) BACKENDS=( "dbis-admin.d-bis.org|192.168.11.130|80|10130|$R630_01|dbis-frontend nginx" @@ -34,12 +36,12 @@ BACKENDS=( "dbis-api-2.d-bis.org|192.168.11.156|3000|10151|$R630_01|dbis-api node" "rpc-http-prv.d-bis.org|192.168.11.211|8545|2101|$R630_01|besu RPC" "www.mim4u.org|192.168.11.37|80|7810|$R630_02|mim-web nginx" - "rpc-alltra.d-bis.org|192.168.11.172|8545|2500|$R630_01|besu alltra" - "rpc-alltra-2.d-bis.org|192.168.11.173|8545|2501|$R630_01|besu alltra" - "rpc-alltra-3.d-bis.org|192.168.11.174|8545|2502|$R630_01|besu alltra" - "rpc-hybx.d-bis.org|192.168.11.246|8545|2503|${HYBX_HOST:-$R630_01}|besu hybx" - "rpc-hybx-2.d-bis.org|192.168.11.247|8545|2504|${HYBX_HOST:-$R630_01}|besu hybx" - "rpc-hybx-3.d-bis.org|192.168.11.248|8545|2505|${HYBX_HOST:-$R630_01}|besu hybx" + "rpc-alltra.d-bis.org|192.168.11.172|8545|2420|$R630_01|besu alltra" + "rpc-alltra-2.d-bis.org|192.168.11.173|8545|2430|$R630_01|besu alltra" + "rpc-alltra-3.d-bis.org|192.168.11.174|8545|2440|$R630_01|besu alltra" + "rpc-hybx.d-bis.org|192.168.11.246|8545|2460|$R630_01|besu hybx" + "rpc-hybx-2.d-bis.org|192.168.11.247|8545|2470|$R630_01|besu hybx" + "rpc-hybx-3.d-bis.org|192.168.11.248|8545|2480|$R630_01|besu hybx" "cacti-alltra.d-bis.org|192.168.11.177|80|5201|$R630_02|cacti web" "cacti-hybx.d-bis.org|192.168.11.251|80|5202|$R630_02|cacti web" ) @@ -86,14 +88,6 @@ for line in "${BACKENDS[@]}"; do continue fi status=$(run_ssh "$host" "pct status $vmid 2>/dev/null | awk '{print \$2}'" 2>/dev/null || echo "missing") - # If HYBX (2503–2505) empty on ML110, try r630-01 - if [[ -z "$status" || "$status" == "missing" ]] && [[ "$vmid" == "2503" || "$vmid" == "2504" || "$vmid" == "2505" ]] && [[ "$host" == "$ML110" ]]; then - alt_status=$(run_ssh "$R630_01" "pct status $vmid 2>/dev/null | awk '{print \$2}'" 2>/dev/null || echo "") - if [[ "$alt_status" == "running" ]]; then - host="$R630_01" - status="running" - fi - fi if [[ "$status" != "running" ]]; then log_warn " Container $vmid status: ${status:-empty} (host $host)" if [[ "$DRY_RUN" != true && "$DIAGNOSE_ONLY" != true ]]; then diff --git a/scripts/maintenance/diagnose-rpc-502s.sh b/scripts/maintenance/diagnose-rpc-502s.sh index 133149b7..8a3b18fc 100755 --- a/scripts/maintenance/diagnose-rpc-502s.sh +++ b/scripts/maintenance/diagnose-rpc-502s.sh @@ -1,31 +1,59 @@ #!/usr/bin/env bash -# Collect RPC diagnostics for VMIDs 2101 and 2500-2505: listening ports and Besu journal. -# Run from project root. Requires SSH to r630-01 (and ml110 if 2503-2505 are there). +# Collect RPC diagnostics for selected core/edge RPC VMIDs: listening ports and Besu journal. +# Run from project root. Uses the shared live VMID placement map. # Output is suitable for piping to a file or tee. # -# Usage: ./scripts/maintenance/diagnose-rpc-502s.sh +# Usage: +# ./scripts/maintenance/diagnose-rpc-502s.sh +# ./scripts/maintenance/diagnose-rpc-502s.sh --vmid 2101 # See: docs/00-meta/502_DEEP_DIVE_ROOT_CAUSES_AND_FIXES.md set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" -[[ -f "${PROJECT_ROOT}/config/ip-addresses.conf" ]] && source "${PROJECT_ROOT}/config/ip-addresses.conf" 2>/dev/null || true +source "${PROJECT_ROOT}/scripts/lib/load-project-env.sh" -R630_01="${PROXMOX_HOST_R630_01:-${PROXMOX_R630_01:-192.168.11.11}}" -ML110="${PROXMOX_HOST_ML110:-${PROXMOX_ML110:-192.168.11.10}}" SSH_OPTS="-o ConnectTimeout=8 -o StrictHostKeyChecking=accept-new" +TARGET_VMIDS=() + +usage() { + cat <<'EOF' +Usage: ./scripts/maintenance/diagnose-rpc-502s.sh [--vmid ] + +Options: + --vmid Limit to one VMID; repeatable +EOF +} + +while [[ $# -gt 0 ]]; do + case "$1" in + --vmid) + [[ $# -ge 2 ]] || { usage >&2; exit 2; } + TARGET_VMIDS+=("$2") + shift 2 + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Unknown argument: $1" >&2 + usage >&2 + exit 2 + ;; + esac +done run() { ssh $SSH_OPTS "root@$1" "$2" 2>/dev/null || echo "(command failed or host unreachable)"; } - -# VMID -> host (2503-2505 may be on ml110 or r630-01) -get_host() { - local v=$1 - case $v in - 2101|2500|2501|2502) echo "$R630_01" ;; - 2503|2504|2505) echo "$R630_01" ;; # default; try ml110 if not running on r630 - *) echo "$R630_01" ;; - esac +selected_vmid() { + local vmid="$1" + [[ ${#TARGET_VMIDS[@]} -eq 0 ]] && return 0 + local wanted + for wanted in "${TARGET_VMIDS[@]}"; do + [[ "$vmid" == "$wanted" ]] && return 0 + done + return 1 } echo "==============================================" @@ -33,20 +61,12 @@ echo "RPC 502 diagnostics — $(date -Iseconds)" echo "==============================================" echo "" -for vmid in 2101 2500 2501 2502 2503 2504 2505; do - host=$(get_host "$vmid") +for vmid in 2101 2420 2430 2440 2460 2470 2480; do + selected_vmid "$vmid" || continue + host="$(get_host_for_vmid "$vmid")" status=$(run "$host" "pct status $vmid 2>/dev/null | awk '{print \$2}'" || echo "unknown") echo "--- VMID $vmid @ $host (status: $status) ---" if [[ "$status" != "running" ]]; then - # If on r630 and not running, try ml110 for 2503-2505 - if [[ "$vmid" =~ ^250[345]$ ]] && [[ "$host" == "$R630_01" ]]; then - status2=$(run "$ML110" "pct status $vmid 2>/dev/null | awk '{print \$2}'" || echo "") - if [[ "$status2" == "running" ]]; then - host="$ML110" - status="$status2" - echo " (found on $ML110)" - fi - fi if [[ "$status" != "running" ]]; then echo " Container not running. Skip." echo "" @@ -66,5 +86,5 @@ done echo "==============================================" echo "If 8545 is not in ss -tlnp, Besu is not binding. Check journal for genesis/nodekey/config errors." -echo "Then run: ./scripts/besu/fix-all-besu-nodes.sh (optionally --no-restart first)" +echo "Then run: ./scripts/besu/fix-all-besu-nodes.sh --vmid (optionally --no-restart first)" echo "==============================================" diff --git a/scripts/maintenance/fix-all-502s-comprehensive.sh b/scripts/maintenance/fix-all-502s-comprehensive.sh index eaca1fd0..9cc8b479 100755 --- a/scripts/maintenance/fix-all-502s-comprehensive.sh +++ b/scripts/maintenance/fix-all-502s-comprehensive.sh @@ -1,8 +1,8 @@ #!/usr/bin/env bash -# Fix all 502 backends using all means: DBIS (nginx + dbis-api), Besu (2101 + 2500-2505), Cacti (nginx). +# Fix all 502 backends using all means: DBIS (nginx + dbis-api), Besu (2101 + edge RPCs), Cacti (nginx). # Run from project root. Requires SSH to r630-01, r630-02. # -# Usage: ./scripts/maintenance/fix-all-502s-comprehensive.sh [--dry-run] +# Usage: ./scripts/maintenance/fix-all-502s-comprehensive.sh [--apply] [--dry-run] set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" @@ -13,8 +13,11 @@ PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" R630_01="${PROXMOX_HOST_R630_01:-192.168.11.11}" R630_02="${PROXMOX_HOST_R630_02:-192.168.11.12}" -DRY_RUN=false -[[ "${1:-}" == "--dry-run" ]] && DRY_RUN=true +DRY_RUN=true +for arg in "$@"; do + [[ "$arg" == "--dry-run" ]] && DRY_RUN=true + [[ "$arg" == "--apply" ]] && DRY_RUN=false +done run() { if $DRY_RUN; then echo -e "\033[0;36m[DRY-RUN]\033[0m Would run on $1: ${2:0:80}..."; return 0; fi @@ -69,16 +72,12 @@ if run "$R630_01" "pct status 2101 2>/dev/null | awk '{print \$2}'" 2>/dev/null fi if $DRY_RUN; then log "Would run fix-core-rpc-2101.sh"; else "${SCRIPT_DIR}/fix-core-rpc-2101.sh" --apply 2>/dev/null && ok "2101 fix run" || warn "2101 fix had issues"; fi -# --- 2500-2505 Alltra/HYBX RPC: ensure nodekey then start besu --- -for v in 2500 2501 2502 2503 2504 2505; do +# --- Edge RPCs: ensure nodekey then start besu --- +for v in 2420 2430 2440 2460 2470 2480; do host="$R630_01" type get_host_for_vmid &>/dev/null && host="$(get_host_for_vmid "$v" 2>/dev/null)" || true [[ -z "$host" ]] && host="$R630_01" status=$(run "$host" "pct status $v 2>/dev/null | awk '{print \$2}'" 2>/dev/null || echo "") - if [[ "$status" != "running" ]] && [[ "$host" == "192.168.11.10" ]]; then - status=$(run "$R630_01" "pct status $v 2>/dev/null | awk '{print \$2}'" 2>/dev/null || echo "") - [[ "$status" == "running" ]] && host="$R630_01" - fi log "$v (rpc-alltra/hybx): nodekey + Besu on $host..." if [[ "$status" == "running" ]]; then run "$host" "pct exec $v -- sh -c 'mkdir -p /data/besu; [ -f /data/besu/nodekey ] || [ -f /data/besu/key ] || openssl rand -hex 32 > /data/besu/nodekey'" 2>/dev/null || true diff --git a/scripts/maintenance/migrate-ml110-besu-rpc-to-r630-02-03.sh b/scripts/maintenance/migrate-ml110-besu-rpc-to-r630-02-03.sh index 672fe734..4cd1f57a 100755 --- a/scripts/maintenance/migrate-ml110-besu-rpc-to-r630-02-03.sh +++ b/scripts/maintenance/migrate-ml110-besu-rpc-to-r630-02-03.sh @@ -9,9 +9,10 @@ # r630-03 / local-lvm: everything else on ml110 (validators, core-2, private, 2304, sentries, thirdweb) # # Usage (from LAN, SSH key to Proxmox nodes): -# ./scripts/maintenance/migrate-ml110-besu-rpc-to-r630-02-03.sh # migrate all still on ml110 +# ./scripts/maintenance/migrate-ml110-besu-rpc-to-r630-02-03.sh # dry-run all still on ml110 +# ./scripts/maintenance/migrate-ml110-besu-rpc-to-r630-02-03.sh --apply # ./scripts/maintenance/migrate-ml110-besu-rpc-to-r630-02-03.sh --dry-run -# ./scripts/maintenance/migrate-ml110-besu-rpc-to-r630-02-03.sh 2305 # single VMID +# ./scripts/maintenance/migrate-ml110-besu-rpc-to-r630-02-03.sh --vmid 2305 # single VMID # # Prerequisites: ml110, r630-02, r630-03 in same cluster; storages active on targets. # @@ -20,7 +21,7 @@ set -uo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" -[[ -f "${PROJECT_ROOT}/config/ip-addresses.conf" ]] && source "${PROJECT_ROOT}/config/ip-addresses.conf" 2>/dev/null || true +source "${PROJECT_ROOT}/scripts/lib/load-project-env.sh" SRC_IP="${PROXMOX_HOST_ML110:-192.168.11.10}" SSH_OPTS="-o BatchMode=yes -o ConnectTimeout=20 -o StrictHostKeyChecking=accept-new" @@ -45,12 +46,45 @@ done ALL_ORDER=(1503 1504 1505 1506 1507 1508 2400 2402 2403 2305 2306 2307 2308 2304 2301 2102 1003 1004) -DRY_RUN=false +DRY_RUN=true SINGLE=() -for arg in "$@"; do - [[ "$arg" == "--dry-run" ]] && DRY_RUN=true - [[ "$arg" =~ ^[0-9]+$ ]] && SINGLE+=("$arg") +usage() { + cat <<'EOF' +Usage: ./scripts/maintenance/migrate-ml110-besu-rpc-to-r630-02-03.sh [--apply] [--dry-run] [--vmid ] + +Options: + --dry-run Print intended migration commands only (default) + --apply Run pct migrate for selected VMIDs + --vmid Limit to one VMID; repeatable +EOF +} + +while [[ $# -gt 0 ]]; do + case "$1" in + --dry-run) + DRY_RUN=true + shift + ;; + --apply) + DRY_RUN=false + shift + ;; + --vmid) + [[ $# -ge 2 ]] || { usage >&2; exit 2; } + SINGLE+=("$2") + shift 2 + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Unknown argument: $1" >&2 + usage >&2 + exit 2 + ;; + esac done log() { echo "[$(date -Iseconds)] $*"; } diff --git a/scripts/maintenance/run-all-maintenance-via-proxmox-ssh.sh b/scripts/maintenance/run-all-maintenance-via-proxmox-ssh.sh index d76b903e..02736759 100755 --- a/scripts/maintenance/run-all-maintenance-via-proxmox-ssh.sh +++ b/scripts/maintenance/run-all-maintenance-via-proxmox-ssh.sh @@ -4,6 +4,7 @@ # # Usage: # ./scripts/maintenance/run-all-maintenance-via-proxmox-ssh.sh +# ./scripts/maintenance/run-all-maintenance-via-proxmox-ssh.sh --apply # ./scripts/maintenance/run-all-maintenance-via-proxmox-ssh.sh --no-npm # ./scripts/maintenance/run-all-maintenance-via-proxmox-ssh.sh --e2e # ./scripts/maintenance/run-all-maintenance-via-proxmox-ssh.sh --verbose # show all step output (no 2>/dev/null) @@ -15,7 +16,7 @@ # 0. make-rpc-vmids-writable-via-ssh.sh — Stop 2101,2500-2505; e2fsck rootfs; start (r630-01) # 1. resolve-and-fix-all-via-proxmox-ssh.sh — Dev VM IP, start containers, DBIS (r630-01, ml110) # 2. fix-rpc-2101-jna-reinstall.sh — 2101 Besu reinstall (r630-01) -# 3. install-besu-permanent-on-missing-nodes.sh — Besu on 2500-2505, 1505-1508 (r630-01, ml110) +# 3. install-besu-permanent-on-missing-nodes.sh — Besu on 2420-2480 and 1505-1508 # 4. address-all-remaining-502s.sh — backends + NPM proxy + RPC diagnostics # 5. [optional] verify-end-to-end-routing.sh — E2E (if --e2e) # @@ -36,12 +37,13 @@ R630_02="${PROXMOX_HOST_R630_02:-192.168.11.12}" SKIP_NPM=false RUN_E2E=false -DRY_RUN=false +DRY_RUN=true VERBOSE=false for arg in "${@:-}"; do [[ "$arg" == "--no-npm" ]] && SKIP_NPM=true [[ "$arg" == "--e2e" ]] && RUN_E2E=true [[ "$arg" == "--dry-run" ]] && DRY_RUN=true + [[ "$arg" == "--apply" ]] && DRY_RUN=false [[ "$arg" == "--verbose" ]] && VERBOSE=true done @@ -128,8 +130,8 @@ echo "" # 3. Install Besu on missing nodes (r630-01, ml110) echo "[3/5] Install Besu on missing nodes..." -echo "--- 3/5: Install Besu on missing nodes (r630-01, ml110) ---" -if run_step "${PROJECT_ROOT}/scripts/besu/install-besu-permanent-on-missing-nodes.sh"; then +echo "--- 3/5: Install Besu on missing nodes ---" +if run_step "${PROJECT_ROOT}/scripts/besu/install-besu-permanent-on-missing-nodes.sh" --apply; then echo " Done." else echo " Step had failures (e.g. disk full or read-only CT)." diff --git a/scripts/migrate-containers-to-pve-local.sh b/scripts/migrate-containers-to-pve-local.sh index 6ff3ac58..8799da71 100755 --- a/scripts/migrate-containers-to-pve-local.sh +++ b/scripts/migrate-containers-to-pve-local.sh @@ -1,8 +1,18 @@ #!/usr/bin/env bash # Migrate containers 1504, 2503, 2504, 6201 from ml110 to pve using local storage +# HISTORICAL SCRIPT +# This migration plan targets retired 25xx-era placement and should not be used for current fleet moves. + set -euo pipefail +if [[ "${HISTORICAL_ALLOW_RUN:-0}" != "1" ]]; then + echo "HISTORICAL: migrate-containers-to-pve-local.sh is not a current migration runbook." >&2 + echo "Use docs/04-configuration/PROXMOX_LOAD_BALANCING_RUNBOOK.md and current health planners instead." >&2 + echo "Set HISTORICAL_ALLOW_RUN=1 only if you intentionally need this legacy script." >&2 + exit 1 +fi + # Load IP configuration SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" @@ -220,4 +230,3 @@ main() { } main "$@" - diff --git a/scripts/migrate-to-pve-thin1.sh b/scripts/migrate-to-pve-thin1.sh index 06f93937..45914294 100755 --- a/scripts/migrate-to-pve-thin1.sh +++ b/scripts/migrate-to-pve-thin1.sh @@ -1,8 +1,18 @@ #!/usr/bin/env bash # Migrate containers 1504, 2503, 2504, 6201 from ml110 to r630-01 using thin1 storage +# HISTORICAL SCRIPT +# This migration plan targets retired 25xx-era placement and should not be used for current fleet moves. + set -euo pipefail +if [[ "${HISTORICAL_ALLOW_RUN:-0}" != "1" ]]; then + echo "HISTORICAL: migrate-to-pve-thin1.sh is not a current migration runbook." >&2 + echo "Use docs/04-configuration/PROXMOX_LOAD_BALANCING_RUNBOOK.md and current health planners instead." >&2 + echo "Set HISTORICAL_ALLOW_RUN=1 only if you intentionally need this legacy script." >&2 + exit 1 +fi + # Load IP configuration SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" @@ -266,4 +276,3 @@ main() { } main "$@" - diff --git a/scripts/pre-check-jwt-setup.sh b/scripts/pre-check-jwt-setup.sh index 9c15191f..6bc3a177 100755 --- a/scripts/pre-check-jwt-setup.sh +++ b/scripts/pre-check-jwt-setup.sh @@ -4,14 +4,12 @@ set -euo pipefail -# Load IP configuration SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" -source "${PROJECT_ROOT}/config/ip-addresses.conf" 2>/dev/null || true +source "${PROJECT_ROOT}/scripts/lib/load-project-env.sh" - -PROXMOX_HOST="${PROXMOX_HOST:-192.168.11.10}" -VMID=2501 +VMID="${1:-2101}" +PROXMOX_HOST="$(get_host_for_vmid "$VMID")" # Colors RED='\033[0;31m' @@ -34,7 +32,7 @@ ISSUES=0 WARNINGS=0 # Check 1: Container status -check "Checking VMID $VMID status..." +check "Checking VMID $VMID status on $PROXMOX_HOST..." STATUS=$(ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@${PROXMOX_HOST} \ "pct status $VMID 2>/dev/null | awk '{print \$2}'" 2>/dev/null || echo "unknown") @@ -71,8 +69,8 @@ if [[ "$EXISTING_CONFIG" == "yes" ]]; then "pct exec $VMID -- grep -E 'server_name.*rpc-' /etc/nginx/sites-available/rpc 2>/dev/null | head -3" || echo "") if echo "$DOMAINS" | grep -q "rpc-http-pub\|rpc-ws-pub"; then - warn "Existing config uses rpc-http-pub/rpc-ws-pub (should be on VMID 2502)" - warn "Script will create new config 'rpc-perm' for rpc-http-prv/rpc-ws-prv" + warn "Existing config uses rpc-http-pub/rpc-ws-pub (should not be reused for the JWT-protected private endpoint)" + warn "Script will create new config 'rpc-perm' for rpc-http-prv/rpc-ws-prv on VMID $VMID" warn "Old config will be disabled but not deleted" fi else @@ -135,17 +133,16 @@ echo "Summary" echo "==========================================" if [ $ISSUES -eq 0 ] && [ $WARNINGS -eq 0 ]; then - info "All checks passed! Ready to run configure-nginx-jwt-auth.sh" + info "All checks passed! Ready to run configure-nginx-jwt-auth.sh for VMID $VMID" exit 0 elif [ $ISSUES -eq 0 ]; then warn "$WARNINGS warning(s) found, but setup can proceed" echo "" - info "Ready to run configure-nginx-jwt-auth.sh" + info "Ready to run configure-nginx-jwt-auth.sh for VMID $VMID" exit 0 else error "$ISSUES issue(s) found that must be resolved first" echo "" - error "Please fix the issues above before running configure-nginx-jwt-auth.sh" + error "Please fix the issues above before running configure-nginx-jwt-auth.sh for VMID $VMID" exit 1 fi - diff --git a/scripts/run-completable-tasks-from-anywhere.sh b/scripts/run-completable-tasks-from-anywhere.sh index 6b814f51..92e300c7 100755 --- a/scripts/run-completable-tasks-from-anywhere.sh +++ b/scripts/run-completable-tasks-from-anywhere.sh @@ -20,7 +20,7 @@ if $DRY_RUN; then echo "=== Completable from anywhere (--dry-run: commands only) ===" echo "" echo "10 steps (see script body). Summary:" - echo "1. Config validation: bash scripts/validation/validate-config-files.sh [--dry-run]" + echo "1. Config validation: bash scripts/validation/validate-config-files.sh [--dry-run] (includes GRU reference-primacy + peg-bands hook when cross-chain-pmm-lps is present)" echo " (optional: python3 -m pip install check-jsonschema — step 1 then validates config/dbis-institutional JSON Schemas too)" echo "2. On-chain check (138): SKIP_EXIT=1 bash scripts/verify/check-contracts-on-chain-138.sh || true" echo "3. All validation: bash scripts/verify/run-all-validation.sh --skip-genesis" diff --git a/scripts/troubleshoot-rpc-2500.sh b/scripts/troubleshoot-rpc-2500.sh index 434db5e4..8400d135 100755 --- a/scripts/troubleshoot-rpc-2500.sh +++ b/scripts/troubleshoot-rpc-2500.sh @@ -1,6 +1,16 @@ #!/usr/bin/env bash set -euo pipefail +# HISTORICAL SCRIPT +# VMID 2500 was replaced by the current RPC fleet (2101/2201/2301/24xx). +# This script is kept for migration-era forensics only. +if [[ "${HISTORICAL_ALLOW_RUN:-0}" != "1" ]]; then + echo "HISTORICAL: troubleshoot-rpc-2500.sh targets retired VMID 2500 and is not a current runbook." >&2 + echo "Use current health checks such as scripts/health/check-rpc-vms-health.sh --vmid instead." >&2 + echo "Set HISTORICAL_ALLOW_RUN=1 only if you intentionally need this legacy script." >&2 + exit 1 +fi + # Troubleshoot RPC-01 at VMID 2500 # Usage: ./troubleshoot-rpc-2500.sh @@ -243,4 +253,3 @@ echo "" log_info "For detailed logs, run:" log_info " pct exec $VMID -- journalctl -u besu-rpc.service -f" echo "" - diff --git a/scripts/validation/validate-config-files.sh b/scripts/validation/validate-config-files.sh index 7d43d1ec..c53c430b 100755 --- a/scripts/validation/validate-config-files.sh +++ b/scripts/validation/validate-config-files.sh @@ -54,6 +54,7 @@ if $DRY_RUN; then echo " REQUIRED_FILES: ${REQUIRED_FILES:-}" echo " OPTIONAL_ENV: ${OPTIONAL_ENV:-}" echo " config/xdc-zero: validate-xdc-zero-config.sh (when config/xdc-zero exists)" + echo " GRU reference primacy: scripts/verify/check-gru-reference-primacy-integration.sh (doc links + peg-bands hook)" exit 0 fi @@ -126,6 +127,12 @@ function readJson(relativePath) { return JSON.parse(fs.readFileSync(path.join(projectRoot, relativePath), 'utf8')); } +function readJsonMaybe(relativePath) { + const full = path.join(projectRoot, relativePath); + if (!fs.existsSync(full)) return null; + return JSON.parse(fs.readFileSync(full, 'utf8')); +} + function normalizeAddress(address) { return typeof address === 'string' ? address.trim().toLowerCase() : ''; } @@ -144,8 +151,17 @@ function refConfigured(ref) { const active = readJson('config/gru-transport-active.json'); const multichain = readJson('config/token-mapping-multichain.json'); -const deployment = readJson('cross-chain-pmm-lps/config/deployment-status.json'); -const poolMatrix = readJson('cross-chain-pmm-lps/config/pool-matrix.json'); +const deploymentRel = 'cross-chain-pmm-lps/config/deployment-status.json'; +const poolMatrixRel = 'cross-chain-pmm-lps/config/pool-matrix.json'; +const deployment = readJsonMaybe(deploymentRel); +const poolMatrix = readJsonMaybe(poolMatrixRel); +const hasDeploymentOverlay = deployment !== null && poolMatrix !== null; +if (!hasDeploymentOverlay) { + console.warn( + '[WARN] Missing cross-chain-pmm-lps deployment overlay (one of deployment-status.json / pool-matrix.json). ' + + 'Skipping deployment/pool-matrix cross-checks. For full checks: git submodule update --init cross-chain-pmm-lps' + ); +} const currencyManifest = readJson('config/gru-iso4217-currency-manifest.json'); const monetaryUnitManifest = readJson('config/gru-monetary-unit-manifest.json'); @@ -186,7 +202,8 @@ function getMappingToken(fromChainId, toChainId, mappingKey) { } function getExpectedPoolKey(chainId, mirroredSymbol) { - const chain = poolMatrix.chains?.[String(chainId)]; + if (!hasDeploymentOverlay || !poolMatrix?.chains) return null; + const chain = poolMatrix.chains[String(chainId)]; const hubStable = typeof chain?.hubStable === 'string' ? chain.hubStable.trim() : ''; if (!hubStable) return null; return `${chainId}-${mirroredSymbol}-${hubStable}`; @@ -279,12 +296,14 @@ for (const pair of active.transportPairs || []) { } } - const deploymentChain = deployment.chains?.[String(destinationChainId)]; - const deployedMirror = deploymentChain?.cwTokens?.[mirroredSymbol] || deploymentChain?.gasMirrors?.[mirroredSymbol]; - if (!deploymentChain || !isNonZeroAddress(deployedMirror)) { - errors.push(`transportPairs[${pair.key}] mapping exists but deployment-status.json has no deployed ${mirroredSymbol} for chain ${destinationChainId}`); - } else if (mappingToken && normalizeAddress(deployedMirror) !== normalizeAddress(mappingToken.addressTo)) { - errors.push(`transportPairs[${pair.key}] deployment-status.json ${mirroredSymbol} does not match token-mapping-multichain.json addressTo`); + if (hasDeploymentOverlay) { + const deploymentChain = deployment.chains?.[String(destinationChainId)]; + const deployedMirror = deploymentChain?.cwTokens?.[mirroredSymbol] || deploymentChain?.gasMirrors?.[mirroredSymbol]; + if (!deploymentChain || !isNonZeroAddress(deployedMirror)) { + errors.push(`transportPairs[${pair.key}] mapping exists but deployment-status.json has no deployed ${mirroredSymbol} for chain ${destinationChainId}`); + } else if (mappingToken && normalizeAddress(deployedMirror) !== normalizeAddress(mappingToken.addressTo)) { + errors.push(`transportPairs[${pair.key}] deployment-status.json ${mirroredSymbol} does not match token-mapping-multichain.json addressTo`); + } } if (pair.assetClass === 'gas_native') { @@ -349,19 +368,21 @@ for (const pool of active.publicPools || []) { errors.push(`publicPools[${pool.key}] is active but has no poolAddress`); continue; } - const deploymentChain = deployment.chains?.[String(pool.chainId)]; - const deployedStable = Array.isArray(deploymentChain?.pmmPools) ? deploymentChain.pmmPools : []; - const deployedVolatile = Array.isArray(deploymentChain?.pmmPoolsVolatile) ? deploymentChain.pmmPoolsVolatile : []; - const deployedGas = Array.isArray(deploymentChain?.gasPmmPools) ? deploymentChain.gasPmmPools : []; - const deploymentMatch = [...deployedStable, ...deployedVolatile].some( - (entry) => normalizeAddress(entry?.poolAddress) === normalizeAddress(pool.poolAddress) - ); - const gasDeploymentMatch = deployedGas.some( - (entry) => normalizeAddress(entry?.poolAddress) === normalizeAddress(pool.poolAddress) - ); - const stagedPlaceholder = String(pool.phase || '').toLowerCase().includes('staged'); - if (!deploymentMatch && !gasDeploymentMatch && !stagedPlaceholder) { - errors.push(`publicPools[${pool.key}] is active but deployment-status.json does not contain its poolAddress`); + if (hasDeploymentOverlay) { + const deploymentChain = deployment.chains?.[String(pool.chainId)]; + const deployedStable = Array.isArray(deploymentChain?.pmmPools) ? deploymentChain.pmmPools : []; + const deployedVolatile = Array.isArray(deploymentChain?.pmmPoolsVolatile) ? deploymentChain.pmmPoolsVolatile : []; + const deployedGas = Array.isArray(deploymentChain?.gasPmmPools) ? deploymentChain.gasPmmPools : []; + const deploymentMatch = [...deployedStable, ...deployedVolatile].some( + (entry) => normalizeAddress(entry?.poolAddress) === normalizeAddress(pool.poolAddress) + ); + const gasDeploymentMatch = deployedGas.some( + (entry) => normalizeAddress(entry?.poolAddress) === normalizeAddress(pool.poolAddress) + ); + const stagedPlaceholder = String(pool.phase || '').toLowerCase().includes('staged'); + if (!deploymentMatch && !gasDeploymentMatch && !stagedPlaceholder) { + errors.push(`publicPools[${pool.key}] is active but deployment-status.json does not contain its poolAddress`); + } } } } @@ -423,59 +444,61 @@ for (const exposure of active.gasProtocolExposure || []) { } } -for (const [chainIdKey, deploymentChain] of Object.entries(deployment.chains || {})) { - const destinationChainId = Number(chainIdKey); - if (destinationChainId === canonicalChainId) continue; - if (deploymentChain?.bridgeAvailable !== true) continue; +if (hasDeploymentOverlay) { + for (const [chainIdKey, deploymentChain] of Object.entries(deployment.chains || {})) { + const destinationChainId = Number(chainIdKey); + if (destinationChainId === canonicalChainId) continue; + if (deploymentChain?.bridgeAvailable !== true) continue; - const mappingPair = getMappingPair(canonicalChainId, destinationChainId); - if (!mappingPair) continue; + const mappingPair = getMappingPair(canonicalChainId, destinationChainId); + if (!mappingPair) continue; - let compatible = true; - for (const token of enabledCanonicalTokens.filter((entry) => entry.registryFamily !== 'gas_native')) { - const mappingKey = String(token.mappingKey || ''); - const mirroredSymbol = String(token.mirroredSymbol || ''); - const mappingToken = mappingKey ? (mappingPair.tokens || []).find((entry) => entry.key === mappingKey) : null; - const deployedMirror = deploymentChain?.cwTokens?.[mirroredSymbol]; - const expectedPoolKey = getExpectedPoolKey(destinationChainId, mirroredSymbol); + let compatible = true; + for (const token of enabledCanonicalTokens.filter((entry) => entry.registryFamily !== 'gas_native')) { + const mappingKey = String(token.mappingKey || ''); + const mirroredSymbol = String(token.mirroredSymbol || ''); + const mappingToken = mappingKey ? (mappingPair.tokens || []).find((entry) => entry.key === mappingKey) : null; + const deployedMirror = deploymentChain?.cwTokens?.[mirroredSymbol]; + const expectedPoolKey = getExpectedPoolKey(destinationChainId, mirroredSymbol); - if ( - !mappingKey || - !mappingToken || - !isNonZeroAddress(mappingToken.addressTo) || - !isNonZeroAddress(deployedMirror) || - normalizeAddress(mappingToken.addressTo) !== normalizeAddress(deployedMirror) || - !expectedPoolKey - ) { - compatible = false; - break; + if ( + !mappingKey || + !mappingToken || + !isNonZeroAddress(mappingToken.addressTo) || + !isNonZeroAddress(deployedMirror) || + normalizeAddress(mappingToken.addressTo) !== normalizeAddress(deployedMirror) || + !expectedPoolKey + ) { + compatible = false; + break; + } } - } - if (!compatible) continue; + if (!compatible) continue; - const enabledChain = enabledChainsArray.find((chain) => Number(chain.chainId) === destinationChainId); - if (!enabledChain) { - errors.push(`compatible destination chain ${destinationChainId} (${deploymentChain?.name || 'unknown'}) is missing from enabledDestinationChains`); - continue; - } - - for (const token of enabledCanonicalTokens.filter((entry) => entry.registryFamily !== 'gas_native')) { - const expectedPairKey = `${canonicalChainId}-${destinationChainId}-${token.symbol}-${token.mirroredSymbol}`; - const expectedPoolKey = getExpectedPoolKey(destinationChainId, String(token.mirroredSymbol || '')); - const pair = transportPairsByKey.get(expectedPairKey); - - if (!pair) { - errors.push(`compatible destination chain ${destinationChainId} is missing transport pair ${expectedPairKey}`); + const enabledChain = enabledChainsArray.find((chain) => Number(chain.chainId) === destinationChainId); + if (!enabledChain) { + errors.push(`compatible destination chain ${destinationChainId} (${deploymentChain?.name || 'unknown'}) is missing from enabledDestinationChains`); continue; } - if (expectedPoolKey && !publicPoolsByKey.has(expectedPoolKey)) { - errors.push(`compatible destination chain ${destinationChainId} is missing public pool placeholder ${expectedPoolKey}`); - } + for (const token of enabledCanonicalTokens.filter((entry) => entry.registryFamily !== 'gas_native')) { + const expectedPairKey = `${canonicalChainId}-${destinationChainId}-${token.symbol}-${token.mirroredSymbol}`; + const expectedPoolKey = getExpectedPoolKey(destinationChainId, String(token.mirroredSymbol || '')); + const pair = transportPairsByKey.get(expectedPairKey); - if (expectedPoolKey && !(pair.publicPoolKeys || []).includes(expectedPoolKey)) { - errors.push(`transportPairs[${pair.key}] must include the pool-matrix first-hop key ${expectedPoolKey}`); + if (!pair) { + errors.push(`compatible destination chain ${destinationChainId} is missing transport pair ${expectedPairKey}`); + continue; + } + + if (expectedPoolKey && !publicPoolsByKey.has(expectedPoolKey)) { + errors.push(`compatible destination chain ${destinationChainId} is missing public pool placeholder ${expectedPoolKey}`); + } + + if (expectedPoolKey && !(pair.publicPoolKeys || []).includes(expectedPoolKey)) { + errors.push(`transportPairs[${pair.key}] must include the pool-matrix first-hop key ${expectedPoolKey}`); + } } } } @@ -791,6 +814,15 @@ if command -v python3 &>/dev/null; then done fi +if [[ -f "$PROJECT_ROOT/scripts/verify/check-gru-reference-primacy-integration.sh" ]]; then + if bash "$PROJECT_ROOT/scripts/verify/check-gru-reference-primacy-integration.sh"; then + log_ok "GRU reference primacy (doc links + peg-bands gruPolicyIntegration when submodule present)" + else + log_err "GRU reference primacy integration check failed (see scripts/verify/check-gru-reference-primacy-integration.sh)" + ERRORS=$((ERRORS + 1)) + fi +fi + if [[ $ERRORS -gt 0 ]]; then log_err "Validation failed with $ERRORS error(s). Set VALIDATE_REQUIRED_FILES='path1 path2' to require specific files." exit 1 diff --git a/scripts/verify/check-gru-reference-primacy-integration.sh b/scripts/verify/check-gru-reference-primacy-integration.sh new file mode 100755 index 00000000..18e98e3d --- /dev/null +++ b/scripts/verify/check-gru-reference-primacy-integration.sh @@ -0,0 +1,100 @@ +#!/usr/bin/env bash +# Verify GRU reference-primacy doc exists, peg-bands.json carries the machine hook +# (when cross-chain-pmm-lps is present), and canonical consumers still link the doc. +# Usage: bash scripts/verify/check-gru-reference-primacy-integration.sh +# Exit: 0 ok, 1 failure + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" + +DOC_REL="docs/04-configuration/GRU_REFERENCE_PRIMACY_AND_MESH_EXECUTION_MODEL.md" +DOC="$PROJECT_ROOT/$DOC_REL" +MARKER="GRU_REFERENCE_PRIMACY_AND_MESH_EXECUTION_MODEL.md" + +err() { printf '[ERROR] %s\n' "$*" >&2; } +ok() { printf '[OK] %s\n' "$*"; } + +ERRORS=0 + +if [[ ! -f "$DOC" ]]; then + err "Missing $DOC_REL" + exit 1 +fi +if ! grep -qi 'reference primacy' "$DOC"; then + err "$DOC_REL: expected 'reference primacy' wording" + ERRORS=$((ERRORS + 1)) +fi +ok "Found and scanned $DOC_REL" + +# Parent-repo files that must keep a pointer to the canonical doc (integration, not orphan). +REQUIRED_LINK_FILES=( + "$PROJECT_ROOT/docs/04-configuration/GRU_C_STAR_V2_STANDARDS_MATRIX_AND_IMPLEMENTATION_PLAN.md" + "$PROJECT_ROOT/docs/MASTER_INDEX.md" + "$PROJECT_ROOT/AGENTS.md" + "$PROJECT_ROOT/docs/04-configuration/README.md" + "$PROJECT_ROOT/docs/11-references/PMM_DEX_ROUTING_STATUS.md" + "$PROJECT_ROOT/docs/11-references/LIQUIDITY_POOLS_MASTER_MAP.md" + "$PROJECT_ROOT/docs/11-references/CHAIN138_GRID_6534_WALLET_FUNDING_PLAN.md" + "$PROJECT_ROOT/docs/11-references/GRU_V2_PUBLIC_PROTOCOL_DEPLOYMENT_STATUS.md" + "$PROJECT_ROOT/docs/03-deployment/PHASE_C_CW_AND_EDGE_POOLS_RUNBOOK.md" + "$PROJECT_ROOT/.cursor/rules/project-doc-and-deployment-refs.mdc" +) + +for f in "${REQUIRED_LINK_FILES[@]}"; do + rel="${f#"$PROJECT_ROOT"/}" + if [[ ! -f "$f" ]]; then + err "Missing expected file: $rel" + ERRORS=$((ERRORS + 1)) + continue + fi + if ! grep -qF "$MARKER" "$f"; then + err "$rel: must reference $MARKER" + ERRORS=$((ERRORS + 1)) + else + ok "Link present: $rel" + fi +done + +CC_README="$PROJECT_ROOT/cross-chain-pmm-lps/README.md" +if [[ -f "$CC_README" ]]; then + if ! grep -qF "$MARKER" "$CC_README"; then + err "cross-chain-pmm-lps/README.md must reference $MARKER" + ERRORS=$((ERRORS + 1)) + else + ok "Link present: cross-chain-pmm-lps/README.md" + fi +else + ok "Submodule cross-chain-pmm-lps absent — skipped README check" +fi + +PEGB="$PROJECT_ROOT/cross-chain-pmm-lps/config/peg-bands.json" +if [[ -f "$PEGB" ]]; then + if command -v jq &>/dev/null; then + if jq -e \ + '(.gruPolicyIntegration | type == "object") + and (.gruPolicyIntegration.referencePrimacyDoc | type == "string") + and (.gruPolicyIntegration.referencePrimacyDoc | test("GRU_REFERENCE_PRIMACY_AND_MESH_EXECUTION_MODEL")) + and (.gruPolicyIntegration.meshExecutionRole | type == "string") + and (.gruPolicyIntegration.meshExecutionRole | length > 0)' \ + "$PEGB" &>/dev/null; then + ok "peg-bands.json: gruPolicyIntegration hook present" + else + err "peg-bands.json: missing or invalid .gruPolicyIntegration (referencePrimacyDoc + meshExecutionRole)" + ERRORS=$((ERRORS + 1)) + fi + else + err "jq not installed — cannot validate peg-bands.json gruPolicyIntegration" + ERRORS=$((ERRORS + 1)) + fi +else + ok "peg-bands.json absent (submodule not checked out) — skipped peg-bands hook check" +fi + +if [[ "$ERRORS" -gt 0 ]]; then + err "GRU reference primacy integration: $ERRORS error(s)" + exit 1 +fi +ok "GRU reference primacy integration checks passed." +exit 0 diff --git a/scripts/verify/check-mainnet-weth-relay-lane.sh b/scripts/verify/check-mainnet-weth-relay-lane.sh index 9828a341..7130b136 100644 --- a/scripts/verify/check-mainnet-weth-relay-lane.sh +++ b/scripts/verify/check-mainnet-weth-relay-lane.sh @@ -93,7 +93,11 @@ echo " Router paused(): $router_paused" echo if [[ "$delivery_enabled" == "true" && "$shedding" == "false" && ( "$router_paused" == "false" || "$router_paused" == "unknown" ) ]]; then - echo "Lane is already deliverable." + if [[ "$bridge_ready" == "yes" ]]; then + echo "Lane is already deliverable." + else + echo "Lane is operational, but current bridge float is below the configured floor." + fi exit 0 fi diff --git a/scripts/verify/report-mainnet-aave-quote-push-surplus-accounting.sh b/scripts/verify/report-mainnet-aave-quote-push-surplus-accounting.sh new file mode 100644 index 00000000..fce15530 --- /dev/null +++ b/scripts/verify/report-mainnet-aave-quote-push-surplus-accounting.sh @@ -0,0 +1,219 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Read-only accounting report for retained Mainnet quote-push surplus: +# - deployer ETH gas headroom vs configured floor +# - receiver quote balance and sweepable amount +# - recommended holdback for gas-cover accounting (in quote terms) +# - recommended recycleable quote for pool growth +# +# Env: +# ETHEREUM_MAINNET_RPC required +# PRIVATE_KEY or QUOTE_PUSH_DEPLOYER_ADDRESS one required +# AAVE_QUOTE_PUSH_RECEIVER_MAINNET required +# QUOTE_PUSH_SURPLUS_TOKEN_MAINNET optional; defaults to USDC mainnet +# QUOTE_PUSH_RECEIVER_RESERVE_RAW optional; receiver reserve kept after sweep (default 0) +# QUOTE_PUSH_DEPLOYER_GAS_FLOOR_ETH optional; default 0.003 +# QUOTE_PUSH_OPERATION_BUFFER_ETH optional; default 0.0005 +# QUOTE_PUSH_NATIVE_TOKEN_PRICE optional; default 3200 quote per native token +# +# Usage: +# source scripts/lib/load-project-env.sh +# bash scripts/verify/report-mainnet-aave-quote-push-surplus-accounting.sh + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROXMOX_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)" +SMOM="${PROXMOX_ROOT}/smom-dbis-138" +DEFAULT_USDC_MAINNET="0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" +DEFAULT_CWUSDC_MAINNET="0x2de5F116bFcE3d0f922d9C8351e0c5Fc24b9284a" + +# shellcheck disable=SC1091 +source "${PROXMOX_ROOT}/scripts/lib/load-project-env.sh" 2>/dev/null || true +# shellcheck disable=SC1091 +source "${SMOM}/scripts/load-env.sh" >/dev/null 2>&1 || true + +require_cmd() { + command -v "$1" >/dev/null 2>&1 || { + echo "[fail] missing required command: $1" >&2 + exit 1 + } +} + +require_env() { + local name="$1" + if [[ -z "${!name:-}" ]]; then + echo "[fail] missing required env: $name" >&2 + exit 1 + fi +} + +require_cmd cast +require_cmd python3 + +require_env ETHEREUM_MAINNET_RPC + +pick_latest_receiver() { + local latest_json="${SMOM}/broadcast/DeployAaveQuotePushFlashReceiver.s.sol/1/run-latest.json" + if [[ ! -f "$latest_json" ]] || ! command -v jq >/dev/null 2>&1; then + return 1 + fi + jq -r '.transactions[]? | select(.transactionType == "CREATE" and .contractName == "AaveQuotePushFlashReceiver") | .contractAddress' \ + "$latest_json" | tail -n1 +} + +pick_latest_manager() { + local latest_json="${SMOM}/broadcast/DeployQuotePushTreasuryManager.s.sol/1/run-latest.json" + if [[ ! -f "$latest_json" ]] || ! command -v jq >/dev/null 2>&1; then + return 1 + fi + jq -r '.transactions[]? | select(.transactionType == "CREATE" and .contractName == "QuotePushTreasuryManager") | .contractAddress' \ + "$latest_json" | tail -n1 +} + +if [[ -z "${AAVE_QUOTE_PUSH_RECEIVER_MAINNET:-}" ]]; then + inferred_receiver="$(pick_latest_receiver || true)" + if [[ -n "$inferred_receiver" && "$inferred_receiver" != "null" ]]; then + export AAVE_QUOTE_PUSH_RECEIVER_MAINNET="$inferred_receiver" + fi +fi + +if [[ -z "${QUOTE_PUSH_TREASURY_MANAGER_MAINNET:-}" ]]; then + inferred_manager="$(pick_latest_manager || true)" + if [[ -n "$inferred_manager" && "$inferred_manager" != "null" ]]; then + export QUOTE_PUSH_TREASURY_MANAGER_MAINNET="$inferred_manager" + fi +fi + +require_env AAVE_QUOTE_PUSH_RECEIVER_MAINNET + +if [[ -n "${PRIVATE_KEY:-}" ]]; then + DEPLOYER="$(cast wallet address --private-key "$PRIVATE_KEY")" +elif [[ -n "${QUOTE_PUSH_DEPLOYER_ADDRESS:-}" ]]; then + DEPLOYER="${QUOTE_PUSH_DEPLOYER_ADDRESS}" +else + echo "[fail] set PRIVATE_KEY or QUOTE_PUSH_DEPLOYER_ADDRESS" >&2 + exit 1 +fi + +TOKEN="${QUOTE_PUSH_SURPLUS_TOKEN_MAINNET:-$DEFAULT_USDC_MAINNET}" +CWUSDC="${CWUSDC_MAINNET:-$DEFAULT_CWUSDC_MAINNET}" +RECEIVER="${AAVE_QUOTE_PUSH_RECEIVER_MAINNET}" +RECEIVER_RESERVE_RAW="${QUOTE_PUSH_RECEIVER_RESERVE_RAW:-0}" +GAS_FLOOR_ETH="${QUOTE_PUSH_DEPLOYER_GAS_FLOOR_ETH:-0.003}" +OP_BUFFER_ETH="${QUOTE_PUSH_OPERATION_BUFFER_ETH:-0.0005}" +NATIVE_TOKEN_PRICE="${QUOTE_PUSH_NATIVE_TOKEN_PRICE:-3200}" + +deployer_eth="$(cast balance "$DEPLOYER" --ether --rpc-url "$ETHEREUM_MAINNET_RPC")" +deployer_quote_raw="$(cast call "$TOKEN" 'balanceOf(address)(uint256)' "$DEPLOYER" --rpc-url "$ETHEREUM_MAINNET_RPC" | awk '{print $1}')" +deployer_base_raw="$(cast call "$CWUSDC" 'balanceOf(address)(uint256)' "$DEPLOYER" --rpc-url "$ETHEREUM_MAINNET_RPC" | awk '{print $1}')" +receiver_quote_raw="$(cast call "$TOKEN" 'balanceOf(address)(uint256)' "$RECEIVER" --rpc-url "$ETHEREUM_MAINNET_RPC" | awk '{print $1}')" + +python3 - "$deployer_eth" "$deployer_quote_raw" "$deployer_base_raw" "$receiver_quote_raw" \ + "$RECEIVER_RESERVE_RAW" "$GAS_FLOOR_ETH" "$OP_BUFFER_ETH" "$NATIVE_TOKEN_PRICE" "$DEPLOYER" "$RECEIVER" "$TOKEN" <<'PY' +import math +import sys + +deployer_eth = float(sys.argv[1]) +deployer_quote_raw = int(sys.argv[2]) +deployer_base_raw = int(sys.argv[3]) +receiver_quote_raw = int(sys.argv[4]) +receiver_reserve_raw = int(sys.argv[5]) +gas_floor_eth = float(sys.argv[6]) +op_buffer_eth = float(sys.argv[7]) +native_token_price = float(sys.argv[8]) +deployer = sys.argv[9] +receiver = sys.argv[10] +token = sys.argv[11] + +recycle_floor_eth = gas_floor_eth + op_buffer_eth +gas_shortfall_eth = max(0.0, recycle_floor_eth - deployer_eth) +gas_shortfall_quote_raw = math.ceil(gas_shortfall_eth * native_token_price * 1_000_000) +sweepable_raw = max(0, receiver_quote_raw - receiver_reserve_raw) +holdback_for_gas_raw = min(sweepable_raw, gas_shortfall_quote_raw) +recycleable_raw = max(0, sweepable_raw - holdback_for_gas_raw) +matched_base_cap_raw = min(recycleable_raw, deployer_base_raw) + +def human(raw: int) -> str: + return f"{raw / 1_000_000:.6f}" + +print("=== Mainnet quote-push surplus accounting ===") +print(f"deployer={deployer}") +print(f"receiver={receiver}") +print(f"token={token}") +print(f"deployer_eth={deployer_eth:.18f}") +print(f"gas_floor_eth={gas_floor_eth:.18f}") +print(f"operation_buffer_eth={op_buffer_eth:.18f}") +print(f"recycle_floor_eth={recycle_floor_eth:.18f}") +print(f"gas_shortfall_eth={gas_shortfall_eth:.18f}") +print(f"native_token_price_quote={native_token_price:.6f}") +print(f"gas_shortfall_quote_raw={gas_shortfall_quote_raw} human={human(gas_shortfall_quote_raw)}") +print(f"receiver_quote_raw={receiver_quote_raw} human={human(receiver_quote_raw)}") +print(f"receiver_reserve_raw={receiver_reserve_raw} human={human(receiver_reserve_raw)}") +print(f"sweepable_raw={sweepable_raw} human={human(sweepable_raw)}") +print(f"deployer_quote_raw={deployer_quote_raw} human={human(deployer_quote_raw)}") +print(f"deployer_cWUSDC_raw={deployer_base_raw} human={human(deployer_base_raw)}") +print(f"holdback_for_gas_raw={holdback_for_gas_raw} human={human(holdback_for_gas_raw)}") +print(f"recycleable_quote_raw={recycleable_raw} human={human(recycleable_raw)}") +print(f"matched_base_cap_raw={matched_base_cap_raw} human={human(matched_base_cap_raw)}") +print("") +print("Recommended next steps:") +print("1. Preview receiver surplus sweep:") +print(" bash scripts/deployment/sweep-mainnet-aave-quote-push-receiver-surplus.sh --dry-run") +if gas_shortfall_eth > 0: + print("2. Replenish deployer gas reserve before recycling surplus to the pool.") + print( + f" At current assumptions, hold back about {human(holdback_for_gas_raw)} quote units to cover the ETH shortfall." + ) + print("3. After deployer ETH is back above the recycle floor, recycle the remainder into pool growth:") + print(" bash scripts/deployment/recycle-mainnet-aave-quote-push-surplus.sh --dry-run") +else: + print("2. Deployer gas reserve is above the recycle floor. Swept quote can be recycled into pool growth.") + print(" bash scripts/deployment/recycle-mainnet-aave-quote-push-surplus.sh --dry-run") +if matched_base_cap_raw == 0: + print("3. Wallet cWUSDC is the limiting asset for matched recycling; no pool-growth tranche is currently fundable.") +else: + print( + f"3. Current matched recycle ceiling is {human(matched_base_cap_raw)} quote/base units using deployer-held cWUSDC." + ) +PY + +if [[ -n "${QUOTE_PUSH_TREASURY_MANAGER_MAINNET:-}" ]]; then + manager_quote_raw="$(cast call "$QUOTE_PUSH_TREASURY_MANAGER_MAINNET" 'quoteBalance()(uint256)' --rpc-url "$ETHEREUM_MAINNET_RPC" 2>/dev/null | awk '{print $1}' || true)" + manager_available_raw="$(cast call "$QUOTE_PUSH_TREASURY_MANAGER_MAINNET" 'availableQuote()(uint256)' --rpc-url "$ETHEREUM_MAINNET_RPC" 2>/dev/null | awk '{print $1}' || true)" + manager_receiver_sweepable_raw="$(cast call "$QUOTE_PUSH_TREASURY_MANAGER_MAINNET" 'receiverSweepableQuote()(uint256)' --rpc-url "$ETHEREUM_MAINNET_RPC" 2>/dev/null | awk '{print $1}' || true)" + manager_gas_recipient="$(cast call "$QUOTE_PUSH_TREASURY_MANAGER_MAINNET" 'gasRecipient()(address)' --rpc-url "$ETHEREUM_MAINNET_RPC" 2>/dev/null | awk '{print $1}' || true)" + manager_recycle_recipient="$(cast call "$QUOTE_PUSH_TREASURY_MANAGER_MAINNET" 'recycleRecipient()(address)' --rpc-url "$ETHEREUM_MAINNET_RPC" 2>/dev/null | awk '{print $1}' || true)" + manager_receiver_owner="$(cast call "$QUOTE_PUSH_TREASURY_MANAGER_MAINNET" 'receiverOwner()(address)' --rpc-url "$ETHEREUM_MAINNET_RPC" 2>/dev/null | awk '{print $1}' || true)" + manager_receiver_owned="$(cast call "$QUOTE_PUSH_TREASURY_MANAGER_MAINNET" 'isReceiverOwnedByManager()(bool)' --rpc-url "$ETHEREUM_MAINNET_RPC" 2>/dev/null | awk '{print $1}' || true)" + + if [[ -n "$manager_quote_raw" && -n "$manager_available_raw" ]]; then + manager_quote_human="$(python3 - "$manager_quote_raw" <<'PY' +import sys +print(f"{int(sys.argv[1]) / 1_000_000:.6f}") +PY +)" + manager_available_human="$(python3 - "$manager_available_raw" <<'PY' +import sys +print(f"{int(sys.argv[1]) / 1_000_000:.6f}") +PY +)" + manager_receiver_sweepable_human="$(python3 - "${manager_receiver_sweepable_raw:-0}" <<'PY' +import sys +print(f"{int(sys.argv[1]) / 1_000_000:.6f}") +PY +)" + + cat <