From 265581182a5604fc9936c786b7d4e8cea3ff3b01 Mon Sep 17 00:00:00 2001 From: undercover-cactus Date: Wed, 4 Feb 2026 15:56:25 +0100 Subject: [PATCH 1/7] test: launch backend in e2e tests and cli (#418) ## Summary We are now launching the MSP backend when starting stpragehub services. In this PR, we also fix the MSP and BSP node configuration and register it with the correct keys. ## What changed * Added a launch Backend MSP function that is called when launching storage hub services * Fix the wrong genesis error message in storagehub node by removing the `--chain dev` flags (so it can be launch of the same network as our local datahaven nodes). * Use the correct keys to register MSP and BSP. We were injecting different keys that the one we used for MSP and BSP registration leading to the MSP and BSP node to never fully register as storage providers. --------- Co-authored-by: Ahmad Kaouk <56095276+ahmadkaouk@users.noreply.github.com> --- operator/node/Cargo.toml | 1 - test/cli/handlers/launch/storagehub.ts | 5 + test/launcher/storagehub-docker.ts | 156 +++++++++++++------------ test/scripts/fund-providers.ts | 51 ++------ 4 files changed, 94 insertions(+), 119 deletions(-) diff --git a/operator/node/Cargo.toml b/operator/node/Cargo.toml index 8c6df8ed..68861344 100644 --- a/operator/node/Cargo.toml +++ b/operator/node/Cargo.toml @@ -141,7 +141,6 @@ toml = { workspace = true } #### Needed to build static binaries #### pq-sys = { workspace = true, optional = true } - [build-dependencies] substrate-build-script-utils = { workspace = true, default-features = true } diff --git a/test/cli/handlers/launch/storagehub.ts b/test/cli/handlers/launch/storagehub.ts index fc162dde..51eca67e 100644 --- a/test/cli/handlers/launch/storagehub.ts +++ b/test/cli/handlers/launch/storagehub.ts @@ -1,6 +1,7 @@ import { logger, printHeader } from "utils"; import type { DataHavenOptions } from "../../../launcher/datahaven"; import { + launchBackend, launchBspNode, launchFishermanNode, launchIndexerNode, @@ -99,5 +100,9 @@ async function launchStorageHubDocker( logger.info("📝 Registering providers..."); await registerProviders({ launchedNetwork }); + // Launch Backend MSP + logger.info("📦 Launching StorageHub Backend..."); + await launchBackend(datahavenOptions, launchedNetwork); + logger.success("All StorageHub components launched and registered"); } diff --git a/test/launcher/storagehub-docker.ts b/test/launcher/storagehub-docker.ts index c1de22a9..a9f64c0e 100644 --- a/test/launcher/storagehub-docker.ts +++ b/test/launcher/storagehub-docker.ts @@ -1,11 +1,15 @@ import { $ } from "bun"; import { getPublicPort, killExistingContainers, logger, waitForContainerToStart } from "utils"; -import { DEFAULT_SUBSTRATE_WS_PORT } from "utils/constants"; +import { DEFAULT_SUBSTRATE_WS_PORT, SUBSTRATE_FUNDED_ACCOUNTS } from "utils/constants"; import { waitFor } from "utils/waits"; import type { DataHavenOptions } from "./datahaven"; import { isNetworkReady } from "./datahaven"; import type { LaunchedNetwork } from "./types/launchedNetwork"; +/** + * Important ! This is for local deployment only. We are using mDNS discovery when startinn node with the `--discover-local` flag + */ + /** * PostgreSQL configuration for StorageHub Indexer and Fisherman */ @@ -109,48 +113,25 @@ export const getPostgresUrl = (networkId: string): string => { * Injects a BCSV ECDSA key into a StorageHub provider node's keystore. * * @param containerName - Name of the Docker container - * @param seed - The seed phrase for key generation - * @param derivation - Key derivation path (e.g., "//Charlie") + * @param secretKey - The secret key (or private key) we want to add to the node */ export const injectStorageHubKey = async ( containerName: string, - seed: string, - derivation: string + secretKey: string ): Promise => { - logger.info(`🔑 Injecting key ${derivation} into ${containerName}...`); - - const suri = `${seed}${derivation}`; + logger.info(`🔑 Injecting key into ${containerName}...`); // Use Bun's $ directly with docker exec (no sh -c wrapper needed) // This properly handles the spaces in the seed phrase try { - await $`docker exec ${containerName} datahaven-node key insert --base-path /data --chain dev --key-type bcsv --scheme ecdsa --suri ${suri}`.nothrow(); - logger.success(`Key ${derivation} injected successfully`); + await $`docker exec ${containerName} datahaven-node key insert --base-path /data --key-type bcsv --scheme ecdsa --suri ${secretKey}`; + logger.success("Key injected successfully"); } catch (error) { - logger.error(`Failed to inject key ${derivation}: ${error}`); + logger.error(`Failed to inject key : ${error}`); throw error; } }; -/** - * Gets the bootnode address from a running validator node. - * - * For local development with Docker, nodes on the same network can discover each other - * via mDNS (--discover-local flag), so explicit bootnodes are optional. - * - * To use explicit bootnodes, we'd need to extract the peer ID from the validator node, - * which requires querying the RPC endpoint. For simplicity in local dev, we skip this. - * - * @param containerName - Name of the validator container (e.g., datahaven-alice-cli-launch) - * @returns Multiaddress string for bootnode, or empty string to skip bootnodes - */ -export const getBootnodeAddress = async (containerName: string): Promise => { - // For local Docker development, nodes discover each other via mDNS - // No explicit bootnode needed with --discover-local flag - logger.debug(`Skipping explicit bootnode for ${containerName} - using mDNS discovery`); - return ""; -}; - /** * Launches a StorageHub MSP (Main Storage Provider) node. * @@ -166,10 +147,6 @@ export const launchMspNode = async ( const containerName = `storagehub-msp-${options.networkId}`; const dockerNetworkName = `datahaven-${options.networkId}`; const wsPort = 9945; // External port for MSP node - const aliceContainer = `datahaven-alice-${options.networkId}`; - - // Get bootnode address (empty for local dev with mDNS discovery) - const bootnodeAddr = await getBootnodeAddress(aliceContainer); const command: string[] = [ "docker", @@ -182,10 +159,10 @@ export const launchMspNode = async ( "-p", `${wsPort}:${DEFAULT_SUBSTRATE_WS_PORT}`, options.datahavenImageTag, - "--chain", - "dev", "--name", "msp-charlie", + "--chain", + "local", "--rpc-port", `${DEFAULT_SUBSTRATE_WS_PORT}`, "--rpc-external", @@ -208,19 +185,13 @@ export const launchMspNode = async ( "1073741824" // 1 GiB ]; - // Only add bootnodes if we have a valid address - if (bootnodeAddr) { - command.push("--bootnodes", bootnodeAddr); - } - logger.debug(`Executing: ${command.join(" ")}`); await $`sh -c "${command.join(" ")}"`.nothrow(); await waitForContainerToStart(containerName); // Inject key - const seed = "bottom drive obey lake curtain smoke basket hold race lonely fit walk"; - await injectStorageHubKey(containerName, seed, "//Charlie"); + await injectStorageHubKey(containerName, SUBSTRATE_FUNDED_ACCOUNTS.CHARLETH.privateKey); // Restart container to load key logger.info("🔄 Restarting MSP node to load key..."); @@ -263,10 +234,6 @@ export const launchBspNode = async ( const containerName = `storagehub-bsp-${options.networkId}`; const dockerNetworkName = `datahaven-${options.networkId}`; const wsPort = 9946; // External port for BSP node - const aliceContainer = `datahaven-alice-${options.networkId}`; - - // Get bootnode address (empty for local dev with mDNS discovery) - const bootnodeAddr = await getBootnodeAddress(aliceContainer); const command: string[] = [ "docker", @@ -279,10 +246,10 @@ export const launchBspNode = async ( "-p", `${wsPort}:${DEFAULT_SUBSTRATE_WS_PORT}`, options.datahavenImageTag, - "--chain", - "dev", "--name", - "bsp-dave", + "bsp-dorothy", + "--chain", + "local", "--rpc-port", `${DEFAULT_SUBSTRATE_WS_PORT}`, "--rpc-external", @@ -303,19 +270,13 @@ export const launchBspNode = async ( "1073741824" // 1 GiB ]; - // Only add bootnodes if we have a valid address - if (bootnodeAddr) { - command.push("--bootnodes", bootnodeAddr); - } - logger.debug(`Executing: ${command.join(" ")}`); await $`sh -c "${command.join(" ")}"`.nothrow(); await waitForContainerToStart(containerName); - // Inject key (using Dave instead of Eve for BSP) - const seed = "bottom drive obey lake curtain smoke basket hold race lonely fit walk"; - await injectStorageHubKey(containerName, seed, "//Dave"); + // Inject key + await injectStorageHubKey(containerName, SUBSTRATE_FUNDED_ACCOUNTS.DOROTHY.privateKey); // Restart container to load key logger.info("🔄 Restarting BSP node to load key..."); @@ -358,10 +319,7 @@ export const launchIndexerNode = async ( const containerName = `storagehub-indexer-${options.networkId}`; const dockerNetworkName = `datahaven-${options.networkId}`; const wsPort = 9947; // External port for Indexer node - const aliceContainer = `datahaven-alice-${options.networkId}`; - // Get bootnode address (empty for local dev with mDNS discovery) and PostgreSQL URL - const bootnodeAddr = await getBootnodeAddress(aliceContainer); const postgresUrl = getPostgresUrl(options.networkId); const command: string[] = [ @@ -375,10 +333,10 @@ export const launchIndexerNode = async ( "-p", `${wsPort}:${DEFAULT_SUBSTRATE_WS_PORT}`, options.datahavenImageTag, - "--chain", - "dev", "--name", "indexer", + "--chain", + "local", "--rpc-port", `${DEFAULT_SUBSTRATE_WS_PORT}`, "--rpc-external", @@ -395,11 +353,6 @@ export const launchIndexerNode = async ( postgresUrl ]; - // Only add bootnodes if we have a valid address - if (bootnodeAddr) { - command.push("--bootnodes", bootnodeAddr); - } - logger.debug(`Executing: ${command.join(" ")}`); await $`sh -c "${command.join(" ")}"`.nothrow(); @@ -441,10 +394,7 @@ export const launchFishermanNode = async ( const containerName = `storagehub-fisherman-${options.networkId}`; const dockerNetworkName = `datahaven-${options.networkId}`; const wsPort = 9948; // External port for Fisherman node - const aliceContainer = `datahaven-alice-${options.networkId}`; - // Get bootnode address (empty for local dev with mDNS discovery) and PostgreSQL URL - const bootnodeAddr = await getBootnodeAddress(aliceContainer); const postgresUrl = getPostgresUrl(options.networkId); const command: string[] = [ @@ -459,7 +409,7 @@ export const launchFishermanNode = async ( `${wsPort}:${DEFAULT_SUBSTRATE_WS_PORT}`, options.datahavenImageTag, "--chain", - "dev", + "local", "--name", "fisherman", "--rpc-port", @@ -476,11 +426,6 @@ export const launchFishermanNode = async ( postgresUrl ]; - // Only add bootnodes if we have a valid address - if (bootnodeAddr) { - command.push("--bootnodes", bootnodeAddr); - } - logger.debug(`Executing: ${command.join(" ")}`); await $`sh -c "${command.join(" ")}"`.nothrow(); @@ -507,6 +452,63 @@ export const launchFishermanNode = async ( logger.success(`Fisherman node started on port ${wsPort}`); }; +/** + * Launches a StorageHub Backend container. + * + * @param options - Configuration options for launching the network + * @param launchedNetwork - The launched network instance to track the node + */ +export const launchBackend = async ( + options: DataHavenOptions, + launchedNetwork: LaunchedNetwork +): Promise => { + logger.info("🚀 Launching StorageHub Backend..."); + + const backendImage = "moonsonglabs/storage-hub-msp-backend:latest"; + const containerName = `storagehub-backend-${options.networkId}`; + const dockerNetworkName = `datahaven-${options.networkId}`; + const containerNameMSP = `storagehub-msp-${options.networkId}`; + const postgresUrl = getPostgresUrl(options.networkId); + const apiPort = 8080; + + const command: string[] = [ + "docker", + "run", + "-d", + "--name", + containerName, + "--network", + dockerNetworkName, + "-p", + `${apiPort}:8080`, + "-e", + "RUST_LOG=info", + backendImage, + "--chain", + "local", + "--log-format", + "text", + "--database-url", + postgresUrl, + "--rpc-url", + `ws://${containerNameMSP}:${DEFAULT_SUBSTRATE_WS_PORT}`, + "--msp-callback-url", + `http://${containerName}:8080`, + "--msp-trusted-file-transfer-server-url", + `http://${containerNameMSP}:7070` + ]; + + logger.debug(`Executing: ${command.join(" ")}`); + await $`sh -c "${command.join(" ")}"`.nothrow(); + + await waitForContainerToStart(containerName); + + // Register in launched network + launchedNetwork.addContainer(containerName, { http: apiPort }, { http: apiPort }); + + logger.success(`StorageHub Backend container started on port ${apiPort}`); +}; + /** * Stops and removes all StorageHub containers. * diff --git a/test/scripts/fund-providers.ts b/test/scripts/fund-providers.ts index 1487fd2e..098226ea 100644 --- a/test/scripts/fund-providers.ts +++ b/test/scripts/fund-providers.ts @@ -7,32 +7,6 @@ export interface FundProvidersOptions { launchedNetwork: LaunchedNetwork; } -/** - * Provider account information for MSP and BSP nodes. - * - * DataHaven uses AccountId20 (Ethereum-style 20-byte addresses). - * In dev chains, CHARLETH and DOROTHY are pre-funded development accounts - * that correspond to //Charlie and //Dave derivations. - * - * For StorageHub providers, we use: - * - CHARLETH (//Charlie equivalent) for MSP - * - DOROTHY (//Dave equivalent) for BSP (as //Eve might not have pre-funded AccountId20) - */ -const PROVIDER_ACCOUNTS = { - // MSP account (Charleth = Charlie in AccountId20 format) - msp: { - name: "Charleth", - address: SUBSTRATE_FUNDED_ACCOUNTS.CHARLETH.publicKey, // 20-byte address - derivation: "//Charlie" - }, - // BSP account (Dorothy = Dave in AccountId20 format, using instead of Eve) - bsp: { - name: "Dorothy", - address: SUBSTRATE_FUNDED_ACCOUNTS.DOROTHY.publicKey, // 20-byte address - derivation: "//Dave" // Using Dave instead of Eve for BSP - } -} as const; - /** * Minimum balance required for provider operations. * This includes: @@ -61,30 +35,34 @@ export async function fundProviders(options: FundProvidersOptions): Promise Date: Thu, 5 Feb 2026 11:21:02 +0100 Subject: [PATCH 2/7] ci: Remove unused Foundry cache steps (#431) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary - drop the Foundry library and build artifact cache restores from the e2e workflow - also remove the Foundry build cache from the dedicated Foundry tests workflow since it wasn’t providing value Testing - Not run (not requested) --- .github/workflows/task-e2e.yml | 17 ----------------- .github/workflows/task-foundry-tests.yml | 10 ---------- 2 files changed, 27 deletions(-) diff --git a/.github/workflows/task-e2e.yml b/.github/workflows/task-e2e.yml index 694b0906..dfd8cee6 100644 --- a/.github/workflows/task-e2e.yml +++ b/.github/workflows/task-e2e.yml @@ -118,23 +118,6 @@ jobs: key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lock') }} restore-keys: | ${{ runner.os }}-bun- - - name: Cache Foundry libraries - uses: actions/cache/restore@v4 - with: - path: ../contracts/lib - key: ${{ runner.os }}-foundry-libs-${{ hashFiles('.gitmodules') }} - restore-keys: | - ${{ runner.os }}-foundry-libs- - - - name: Cache Foundry build artifacts - uses: actions/cache/restore@v4 - with: - path: | - ../contracts/out - ../contracts/cache - key: ${{ runner.os }}-foundry-build-${{ hashFiles('contracts/foundry.toml', 'contracts/**/*.sol') }} - restore-keys: | - ${{ runner.os }}-foundry-build- - uses: docker/login-action@v3 with: registry: ghcr.io diff --git a/.github/workflows/task-foundry-tests.yml b/.github/workflows/task-foundry-tests.yml index c6bc6d81..81288ee6 100644 --- a/.github/workflows/task-foundry-tests.yml +++ b/.github/workflows/task-foundry-tests.yml @@ -38,16 +38,6 @@ jobs: with: version: v1.4.3 - - name: Cache Foundry build artifacts - uses: actions/cache@v4 - with: - path: | - contracts/out - contracts/cache - key: ${{ runner.os }}-foundry-build-${{ hashFiles('contracts/foundry.toml', 'contracts/**/*.sol') }} - restore-keys: | - ${{ runner.os }}-foundry-build- - - run: forge --version - run: forge fmt --check - run: forge build --sizes From da2847bbbfb4c27688c2eaa9525ad4a221ded259 Mon Sep 17 00:00:00 2001 From: Ahmad Kaouk <56095276+ahmadkaouk@users.noreply.github.com> Date: Thu, 5 Feb 2026 12:08:35 +0100 Subject: [PATCH 3/7] =?UTF-8?q?test:=20=E2=9C=A8=20Add=20storage=20layout?= =?UTF-8?q?=20checks=20for=20upgradeable=20contracts=20(#420)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Implements storage layout testing for the upgradeable `DataHavenServiceManager` contract to prevent state corruption during proxy upgrades. ## Changes ### New Files - **`contracts/storage-snapshots/DataHavenServiceManager.storage.json`** - Baseline storage layout snapshot - **`contracts/storage-snapshots/README.md`** - Documentation for updating snapshots and known limitations - **`contracts/scripts/check-storage-layout.sh`** - CI script that compares current layout against snapshot - **`contracts/test/storage/StorageLayout.t.sol`** - Upgrade simulation tests verifying state preservation - **`.github/workflows/task-storage-layout.yml`** - CI workflow for storage layout checks ### Modified Files - **`.github/workflows/CI.yml`** - Added `storage-layout` job to run in parallel with other checks ## How It Works **Two-pronged approach:** 1. **Snapshot Diff** - Compares current storage layout against committed snapshot using `forge inspect`. Catches unintended variable reordering, type changes, or gap modifications. 2. **Upgrade Simulation** - Foundry tests that populate state, perform a proxy upgrade, and verify all values survive: - `test_upgradePreservesState` - Verifies core state variables - `test_upgradePreservesValidatorMappings` - Verifies `validatorEthAddressToSolochainAddress` mapping - `test_upgradePreservesMultipleValidators` - Verifies `validatorsAllowlist` with multiple entries - `test_functionalityAfterUpgrade` - Verifies contract remains functional post-upgrade ## Normalization The snapshot comparison normalizes JSON to avoid false positives: - Removes `astId` (changes with compiler runs) - Removes `contract` (contains full file path) - Removes `.types` section (contains unstable AST IDs embedded in type keys) - Sorts by slot number ## Usage ```bash # Check storage layout against snapshot ./scripts/check-storage-layout.sh # Run upgrade simulation tests forge test --match-contract StorageLayoutTest -vvv # Update snapshot (when intentionally changing storage) forge inspect DataHavenServiceManager storage --json > storage-snapshots/DataHavenServiceManager.storage.json ``` ## Test Plan - ./scripts/check-storage-layout.sh passes - forge test --match-contract StorageLayoutTest -vvv passes (4 tests) - CI workflow runs successfully --- .github/workflows/CI.yml | 2 + .github/workflows/task-storage-layout.yml | 51 +++++ .../DataHavenServiceManagerBadLayout.sol | 31 ++++ .../scripts/check-storage-layout-negative.sh | 32 ++++ contracts/scripts/check-storage-layout.sh | 62 +++++++ .../DataHavenServiceManager.storage.json | 143 ++++++++++++++ contracts/storage-snapshots/README.md | 75 ++++++++ contracts/test/storage/StorageLayout.t.sol | 175 ++++++++++++++++++ 8 files changed, 571 insertions(+) create mode 100644 .github/workflows/task-storage-layout.yml create mode 100644 contracts/script/fixtures/DataHavenServiceManagerBadLayout.sol create mode 100755 contracts/scripts/check-storage-layout-negative.sh create mode 100755 contracts/scripts/check-storage-layout.sh create mode 100644 contracts/storage-snapshots/DataHavenServiceManager.storage.json create mode 100644 contracts/storage-snapshots/README.md create mode 100644 contracts/test/storage/StorageLayout.t.sol diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index d8d2ba06..63221122 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -44,6 +44,8 @@ jobs: uses: ./.github/workflows/task-rust-tests.yml contract-tests: uses: ./.github/workflows/task-foundry-tests.yml + storage-layout: + uses: ./.github/workflows/task-storage-layout.yml rust-lint: needs: [warm-sccache] uses: ./.github/workflows/task-rust-lint.yml diff --git a/.github/workflows/task-storage-layout.yml b/.github/workflows/task-storage-layout.yml new file mode 100644 index 00000000..2a1a78a5 --- /dev/null +++ b/.github/workflows/task-storage-layout.yml @@ -0,0 +1,51 @@ +# Storage Layout Check: Validates storage layout for upgradeable contracts +# +# Overview: +# 1. Compares current storage layout against committed snapshot +# 2. Runs upgrade simulation tests to verify state preservation + +name: Storage Layout Check + +on: + workflow_dispatch: + workflow_call: + +# Explicit minimal permissions +permissions: + contents: read + +env: + FOUNDRY_PROFILE: ci + +jobs: + check: + name: Storage Layout + runs-on: ubuntu-latest + defaults: + run: + working-directory: contracts + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + with: + version: v1.4.3 + + - name: Build contracts + run: forge build --extra-output storageLayout + + - name: Negative check storage layout (should fail) + run: | + chmod +x scripts/check-storage-layout-negative.sh + ./scripts/check-storage-layout-negative.sh + + - name: Check storage layout + run: | + chmod +x scripts/check-storage-layout.sh + ./scripts/check-storage-layout.sh + + - name: Run upgrade simulation tests + run: forge test --match-contract StorageLayoutTest -vvv diff --git a/contracts/script/fixtures/DataHavenServiceManagerBadLayout.sol b/contracts/script/fixtures/DataHavenServiceManagerBadLayout.sol new file mode 100644 index 00000000..919cc346 --- /dev/null +++ b/contracts/script/fixtures/DataHavenServiceManagerBadLayout.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.27; + +import {OwnableUpgradeable} from "@openzeppelin-upgrades/contracts/access/OwnableUpgradeable.sol"; + +import {IGatewayV2} from "snowbridge/src/v2/IGateway.sol"; + +/// @notice Test-only fixture contract with intentionally broken storage layout. +/// @dev This contract is used to validate the snapshot-diff storage layout check fails as expected. +contract DataHavenServiceManagerBadLayout is OwnableUpgradeable { + // Deliberate layout shift: inserted before all original state vars + uint256 public layoutBreaker; + + // Original variables (shifted by one slot) + address public rewardsInitiator; + mapping(address => bool) public validatorsAllowlist; + IGatewayV2 private _snowbridgeGateway; + mapping(address => address) public validatorEthAddressToSolochainAddress; + + // Keep the original gap size to mirror shape, despite the shift + uint256[46] private __GAP; + + // Keep a compatible constructor signature for upgrade tests. + constructor( + address, + address + ) { + _disableInitializers(); + } +} + diff --git a/contracts/scripts/check-storage-layout-negative.sh b/contracts/scripts/check-storage-layout-negative.sh new file mode 100755 index 00000000..18d842cf --- /dev/null +++ b/contracts/scripts/check-storage-layout-negative.sh @@ -0,0 +1,32 @@ +#!/bin/bash +set -euo pipefail + +# Negative check: ensure the snapshot-diff storage layout script fails when the layout is broken. + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "$SCRIPT_DIR/.." + +set +e +OUTPUT="$( + CONTRACT="DataHavenServiceManagerBadLayout" \ + SNAPSHOT="storage-snapshots/DataHavenServiceManager.storage.json" \ + ./scripts/check-storage-layout.sh 2>&1 +)" +EXIT_CODE=$? +set -e + +if [ "$EXIT_CODE" -eq 0 ]; then + echo "ERROR: Expected storage layout check to fail for DataHavenServiceManagerBadLayout, but it succeeded." + exit 1 +fi + +if ! printf '%s\n' "$OUTPUT" | grep -q "ERROR: Storage layout has changed!"; then + echo "ERROR: Storage layout check failed, but not for the expected reason." + echo "" + echo "Output:" + echo "$OUTPUT" + exit 1 +fi + +echo "Negative check OK: storage layout check failed as expected for DataHavenServiceManagerBadLayout." + diff --git a/contracts/scripts/check-storage-layout.sh b/contracts/scripts/check-storage-layout.sh new file mode 100755 index 00000000..8e2aeb09 --- /dev/null +++ b/contracts/scripts/check-storage-layout.sh @@ -0,0 +1,62 @@ +#!/bin/bash +set -e + +# Storage Layout Check Script +# Compares current storage layout against committed snapshot to detect unintended changes. + +CONTRACT="${CONTRACT:-DataHavenServiceManager}" +SNAPSHOT_DIR="${SNAPSHOT_DIR:-storage-snapshots}" +SNAPSHOT="${SNAPSHOT:-${SNAPSHOT_DIR}/${CONTRACT}.storage.json}" + +# Ensure we're in the contracts directory +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "$SCRIPT_DIR/.." + +# Check if snapshot exists +if [ ! -f "$SNAPSHOT" ]; then + echo "ERROR: Snapshot file not found: $SNAPSHOT" + echo "Generate it with: mkdir -p $SNAPSHOT_DIR && forge inspect $CONTRACT storage --json > $SNAPSHOT" + exit 1 +fi + +# Generate current layout +echo "Generating current storage layout for $CONTRACT..." +forge inspect "$CONTRACT" storage --json > /tmp/current_layout.json + +# Normalize both files for comparison: +# - Remove astId (changes with compiler runs) +# - Remove contract field (contains full path) +# - Remove types section (contains unstable AST IDs) +# - Sort by slot number +normalize_json() { + jq 'del(.types) + | .storage + | map( + del(.astId, .contract) + # Remove unstable AST ID suffixes from type strings (e.g., t_contract(IGatewayV2)12345) + | .type |= sub("\\)[0-9]+$"; ")") + ) + | sort_by(.slot | tonumber)' "$1" +} + +echo "Comparing storage layouts..." +normalize_json "$SNAPSHOT" > /tmp/snap_normalized.json +normalize_json /tmp/current_layout.json > /tmp/curr_normalized.json + +if ! diff -q /tmp/snap_normalized.json /tmp/curr_normalized.json > /dev/null 2>&1; then + echo "" + echo "==========================================" + echo "ERROR: Storage layout has changed!" + echo "==========================================" + echo "" + echo "Differences found:" + diff /tmp/snap_normalized.json /tmp/curr_normalized.json || true + echo "" + echo "If this change is intentional, update the snapshot:" + echo " forge inspect $CONTRACT storage --json > $SNAPSHOT" + echo "" + echo "WARNING: Unintended storage layout changes can corrupt state during upgrades!" + exit 1 +fi + +echo "Storage layout OK - no changes detected" diff --git a/contracts/storage-snapshots/DataHavenServiceManager.storage.json b/contracts/storage-snapshots/DataHavenServiceManager.storage.json new file mode 100644 index 00000000..37f6fa6d --- /dev/null +++ b/contracts/storage-snapshots/DataHavenServiceManager.storage.json @@ -0,0 +1,143 @@ +{ + "storage": [ + { + "astId": 138, + "contract": "src/DataHavenServiceManager.sol:DataHavenServiceManager", + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8" + }, + { + "astId": 141, + "contract": "src/DataHavenServiceManager.sol:DataHavenServiceManager", + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 671, + "contract": "src/DataHavenServiceManager.sol:DataHavenServiceManager", + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 10, + "contract": "src/DataHavenServiceManager.sol:DataHavenServiceManager", + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address" + }, + { + "astId": 130, + "contract": "src/DataHavenServiceManager.sol:DataHavenServiceManager", + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage" + }, + { + "astId": 23771, + "contract": "src/DataHavenServiceManager.sol:DataHavenServiceManager", + "label": "rewardsInitiator", + "offset": 0, + "slot": "101", + "type": "t_address" + }, + { + "astId": 23776, + "contract": "src/DataHavenServiceManager.sol:DataHavenServiceManager", + "label": "validatorsAllowlist", + "offset": 0, + "slot": "102", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 23780, + "contract": "src/DataHavenServiceManager.sol:DataHavenServiceManager", + "label": "_snowbridgeGateway", + "offset": 0, + "slot": "103", + "type": "t_contract(IGatewayV2)23481" + }, + { + "astId": 23785, + "contract": "src/DataHavenServiceManager.sol:DataHavenServiceManager", + "label": "validatorEthAddressToSolochainAddress", + "offset": 0, + "slot": "104", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 23790, + "contract": "src/DataHavenServiceManager.sol:DataHavenServiceManager", + "label": "__GAP", + "offset": 0, + "slot": "105", + "type": "t_array(t_uint256)46_storage" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)46_storage": { + "encoding": "inplace", + "label": "uint256[46]", + "numberOfBytes": "1472", + "base": "t_uint256" + }, + "t_array(t_uint256)49_storage": { + "encoding": "inplace", + "label": "uint256[49]", + "numberOfBytes": "1568", + "base": "t_uint256" + }, + "t_array(t_uint256)50_storage": { + "encoding": "inplace", + "label": "uint256[50]", + "numberOfBytes": "1600", + "base": "t_uint256" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IGatewayV2)23481": { + "encoding": "inplace", + "label": "contract IGatewayV2", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_address)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } +} diff --git a/contracts/storage-snapshots/README.md b/contracts/storage-snapshots/README.md new file mode 100644 index 00000000..bf708a11 --- /dev/null +++ b/contracts/storage-snapshots/README.md @@ -0,0 +1,75 @@ +# Storage Layout Snapshots + +This directory contains storage layout snapshots for upgradeable contracts. These snapshots are used to detect unintended storage layout changes that could corrupt state during proxy upgrades. + +## How It Works + +1. **Snapshot Comparison**: CI compares the current storage layout against committed snapshots +2. **Upgrade Simulation**: Foundry tests verify state preservation across upgrades + +## Updating Snapshots + +When you intentionally modify the storage layout of a contract (e.g., adding new state variables), you must update the snapshot: + +```bash +cd contracts +forge inspect DataHavenServiceManager storage --json > storage-snapshots/DataHavenServiceManager.storage.json +``` + +## Important Guidelines + +- **Never reorder existing variables** - This corrupts existing state +- **Never change types of existing variables** - This corrupts existing state +- **Always add new variables before the `__GAP`** - This preserves upgrade safety +- **Reduce gap size when adding variables** - Keep total slot count constant +- **Review snapshot diffs carefully** - Ensure changes are intentional + +## Current Contracts + +| Contract | Gap Size | Gap Slot | +|----------|----------|----------| +| DataHavenServiceManager | 46 | 105 | + +## Verification Commands + +```bash +# Check storage layout (CI script) +./scripts/check-storage-layout.sh + +# Negative check (proves detector fails on broken layout) +./scripts/check-storage-layout-negative.sh + +# Run upgrade simulation tests +forge test --match-contract StorageLayoutTest -vvv + +# View human-readable layout +forge inspect DataHavenServiceManager storage --pretty +``` + +## How Normalization Works + +The snapshot comparison normalizes both files to avoid false positives: + +- **Removes `astId`**: Changes with each compiler run +- **Removes `contract`**: Contains full file path +- **Removes `.types` section**: Contains unstable AST IDs that cause false diffs +- **Normalizes type IDs**: Strips unstable numeric suffixes from `type` (e.g., `t_contract(IGatewayV2)12345`) +- **Sorts by slot**: Ensures deterministic comparison + +This approach detects: +- Variable reordering or slot changes +- Top-level type changes (primitives, mappings, arrays) +- Gap size modifications + +## Note on Struct Storage + +If you add struct-typed storage variables in the future, be aware that **internal struct field changes may not be detected** by the snapshot diff. This is because: + +1. The `.types` section (which contains struct field definitions) is dropped to avoid unstable AST IDs +2. The storage slot assignment for a struct variable doesn't change when its internal fields change + +**However, this does not break upgrades** in the traditional sense. Struct field reordering or type changes within a struct would cause data misinterpretation (reading field A as field B), but the slot-level layout remains stable. + +**Mitigation**: If adding struct storage, ensure the upgrade simulation tests (`StorageLayoutTest`) explicitly verify struct field values survive upgrades. + +**Current status**: DataHavenServiceManager has no struct-typed storage variables, so this limitation does not apply. diff --git a/contracts/test/storage/StorageLayout.t.sol b/contracts/test/storage/StorageLayout.t.sol new file mode 100644 index 00000000..de81e0b9 --- /dev/null +++ b/contracts/test/storage/StorageLayout.t.sol @@ -0,0 +1,175 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.27; + +import {Test} from "forge-std/Test.sol"; +import { + ITransparentUpgradeableProxy +} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; + +import {AVSDeployer} from "../utils/AVSDeployer.sol"; +import {DataHavenServiceManager} from "../../src/DataHavenServiceManager.sol"; + +/// @title Storage Layout Tests for DataHavenServiceManager +/// @notice Verifies that proxy upgrades preserve state correctly +contract StorageLayoutTest is AVSDeployer { + function setUp() public { + _deployMockEigenLayerAndAVS(); + } + + /// @notice Proves state is preserved across proxy upgrade + function test_upgradePreservesState() public { + // 1. Populate state + address testValidator = address(0x1234); + address newRewardsInitiator = address(0x9999); + + vm.startPrank(avsOwner); + serviceManager.addValidatorToAllowlist(testValidator); + serviceManager.setRewardsInitiator(newRewardsInitiator); + vm.stopPrank(); + + // 2. Record state before upgrade + bool allowlistBefore = serviceManager.validatorsAllowlist(testValidator); + address rewardsInitiatorBefore = serviceManager.rewardsInitiator(); + address ownerBefore = serviceManager.owner(); + address gatewayBefore = serviceManager.snowbridgeGateway(); + + // 3. Deploy new implementation + DataHavenServiceManager newImpl = + new DataHavenServiceManager(rewardsCoordinator, allocationManager); + + // 4. Upgrade proxy + vm.prank(proxyAdminOwner); + proxyAdmin.upgrade(ITransparentUpgradeableProxy(address(serviceManager)), address(newImpl)); + + // 5. Verify state preserved + assertEq( + serviceManager.validatorsAllowlist(testValidator), + allowlistBefore, + "validatorsAllowlist should be preserved" + ); + assertEq( + serviceManager.rewardsInitiator(), + rewardsInitiatorBefore, + "rewardsInitiator should be preserved" + ); + assertEq(serviceManager.owner(), ownerBefore, "owner should be preserved"); + assertEq( + serviceManager.snowbridgeGateway(), + gatewayBefore, + "snowbridgeGateway should be preserved" + ); + } + + /// @notice Verifies validatorEthAddressToSolochainAddress mapping is preserved + function test_upgradePreservesValidatorMappings() public { + address testValidator = address(0xABCD); + address testSolochainAddress = address(0xDEF0); + + // Add validator to allowlist first + vm.prank(avsOwner); + serviceManager.addValidatorToAllowlist(testValidator); + + // Register operator via allocationManager to set the solochain address mapping + uint32[] memory operatorSetIds = new uint32[](1); + operatorSetIds[0] = 0; // VALIDATORS_SET_ID + + vm.prank(address(allocationManager)); + serviceManager.registerOperator( + testValidator, + address(serviceManager), + operatorSetIds, + abi.encodePacked(testSolochainAddress) + ); + + // Record state before upgrade + bool inAllowlistBefore = serviceManager.validatorsAllowlist(testValidator); + address solochainAddressBefore = + serviceManager.validatorEthAddressToSolochainAddress(testValidator); + + // Verify the mapping was set correctly before upgrade + assertEq(solochainAddressBefore, testSolochainAddress, "Solochain address should be set"); + + // Deploy new implementation and upgrade + DataHavenServiceManager newImpl = + new DataHavenServiceManager(rewardsCoordinator, allocationManager); + + vm.prank(proxyAdminOwner); + proxyAdmin.upgrade(ITransparentUpgradeableProxy(address(serviceManager)), address(newImpl)); + + // Verify both mappings preserved after upgrade + assertEq( + serviceManager.validatorsAllowlist(testValidator), + inAllowlistBefore, + "validatorsAllowlist mapping should be preserved after upgrade" + ); + assertEq( + serviceManager.validatorEthAddressToSolochainAddress(testValidator), + solochainAddressBefore, + "validatorEthAddressToSolochainAddress mapping should be preserved after upgrade" + ); + assertEq( + serviceManager.validatorEthAddressToSolochainAddress(testValidator), + testSolochainAddress, + "validatorEthAddressToSolochainAddress should have correct value after upgrade" + ); + } + + /// @notice Verifies multiple validators in allowlist are preserved + function test_upgradePreservesMultipleValidators() public { + address[] memory validators = new address[](3); + validators[0] = address(0x1111); + validators[1] = address(0x2222); + validators[2] = address(0x3333); + + // Add multiple validators + vm.startPrank(avsOwner); + for (uint256 i = 0; i < validators.length; i++) { + serviceManager.addValidatorToAllowlist(validators[i]); + } + vm.stopPrank(); + + // Deploy new implementation and upgrade + DataHavenServiceManager newImpl = + new DataHavenServiceManager(rewardsCoordinator, allocationManager); + + vm.prank(proxyAdminOwner); + proxyAdmin.upgrade(ITransparentUpgradeableProxy(address(serviceManager)), address(newImpl)); + + // Verify all validators still in allowlist + for (uint256 i = 0; i < validators.length; i++) { + assertTrue( + serviceManager.validatorsAllowlist(validators[i]), + "All validators should remain in allowlist after upgrade" + ); + } + } + + /// @notice Verifies that upgrade doesn't affect functionality + function test_functionalityAfterUpgrade() public { + // Deploy new implementation and upgrade + DataHavenServiceManager newImpl = + new DataHavenServiceManager(rewardsCoordinator, allocationManager); + + vm.prank(proxyAdminOwner); + proxyAdmin.upgrade(ITransparentUpgradeableProxy(address(serviceManager)), address(newImpl)); + + // Verify functionality still works + address newValidator = address(0xBEEF); + + vm.prank(avsOwner); + serviceManager.addValidatorToAllowlist(newValidator); + + assertTrue( + serviceManager.validatorsAllowlist(newValidator), + "Should be able to add validators after upgrade" + ); + + vm.prank(avsOwner); + serviceManager.removeValidatorFromAllowlist(newValidator); + + assertFalse( + serviceManager.validatorsAllowlist(newValidator), + "Should be able to remove validators after upgrade" + ); + } +} From 7e429de111231a15d1659162fa78f465eacd64ff Mon Sep 17 00:00:00 2001 From: Steve Degosserie <723552+stiiifff@users.noreply.github.com> Date: Thu, 5 Feb 2026 13:01:32 +0100 Subject: [PATCH 4/7] =?UTF-8?q?feat:=20=E2=9C=A8=20Bump=20client=20version?= =?UTF-8?q?=20to=20v0.23.0=20and=20runtime=20to=20RT1200=20(#432)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ahmad Kaouk <56095276+ahmadkaouk@users.noreply.github.com> --- operator/Cargo.lock | 120 +++++++++++++-------------- operator/Cargo.toml | 2 +- operator/runtime/mainnet/src/lib.rs | 2 +- operator/runtime/stagenet/src/lib.rs | 2 +- operator/runtime/testnet/src/lib.rs | 2 +- test/.papi/metadata/datahaven.scale | Bin 627696 -> 627696 bytes 6 files changed, 64 insertions(+), 64 deletions(-) diff --git a/operator/Cargo.lock b/operator/Cargo.lock index 1289c252..3aa769c4 100644 --- a/operator/Cargo.lock +++ b/operator/Cargo.lock @@ -1521,7 +1521,7 @@ dependencies = [ "pallet-message-queue", "parity-scale-codec", "scale-info", - "snowbridge-core 0.22.0", + "snowbridge-core 0.23.0", "sp-core", "sp-runtime", "sp-std", @@ -2607,7 +2607,7 @@ dependencies = [ [[package]] name = "datahaven-mainnet-runtime" -version = "0.22.0" +version = "0.23.0" dependencies = [ "alloy-core", "bridge-hub-common 0.13.1", @@ -2719,8 +2719,8 @@ dependencies = [ "shp-treasury-funding", "shp-tx-implicits-runtime-api", "smallvec", - "snowbridge-beacon-primitives 0.22.0", - "snowbridge-core 0.22.0", + "snowbridge-beacon-primitives 0.23.0", + "snowbridge-core 0.23.0", "snowbridge-inbound-queue-primitives", "snowbridge-merkle-tree", "snowbridge-outbound-queue-primitives", @@ -2763,7 +2763,7 @@ dependencies = [ [[package]] name = "datahaven-node" -version = "0.22.0" +version = "0.23.0" dependencies = [ "async-channel 1.9.0", "clap", @@ -2876,7 +2876,7 @@ dependencies = [ [[package]] name = "datahaven-runtime-common" -version = "0.22.0" +version = "0.23.0" dependencies = [ "alloy-core", "fp-account", @@ -2910,7 +2910,7 @@ dependencies = [ [[package]] name = "datahaven-stagenet-runtime" -version = "0.22.0" +version = "0.23.0" dependencies = [ "alloy-core", "bridge-hub-common 0.13.1", @@ -3022,8 +3022,8 @@ dependencies = [ "shp-treasury-funding", "shp-tx-implicits-runtime-api", "smallvec", - "snowbridge-beacon-primitives 0.22.0", - "snowbridge-core 0.22.0", + "snowbridge-beacon-primitives 0.23.0", + "snowbridge-core 0.23.0", "snowbridge-inbound-queue-primitives", "snowbridge-merkle-tree", "snowbridge-outbound-queue-primitives", @@ -3066,7 +3066,7 @@ dependencies = [ [[package]] name = "datahaven-testnet-runtime" -version = "0.22.0" +version = "0.23.0" dependencies = [ "alloy-core", "bridge-hub-common 0.13.1", @@ -3178,8 +3178,8 @@ dependencies = [ "shp-treasury-funding", "shp-tx-implicits-runtime-api", "smallvec", - "snowbridge-beacon-primitives 0.22.0", - "snowbridge-core 0.22.0", + "snowbridge-beacon-primitives 0.23.0", + "snowbridge-core 0.23.0", "snowbridge-inbound-queue-primitives", "snowbridge-merkle-tree", "snowbridge-outbound-queue-primitives", @@ -3371,7 +3371,7 @@ dependencies = [ [[package]] name = "dhp-bridge" -version = "0.22.0" +version = "0.23.0" dependencies = [ "frame-support", "frame-system", @@ -3379,7 +3379,7 @@ dependencies = [ "pallet-datahaven-native-transfer", "pallet-external-validators", "parity-scale-codec", - "snowbridge-core 0.22.0", + "snowbridge-core 0.23.0", "snowbridge-inbound-queue-primitives", "sp-core", "sp-std", @@ -8716,7 +8716,7 @@ dependencies = [ [[package]] name = "pallet-datahaven-native-transfer" -version = "0.22.0" +version = "0.23.0" dependencies = [ "frame-benchmarking", "frame-support", @@ -8724,7 +8724,7 @@ dependencies = [ "pallet-balances", "parity-scale-codec", "scale-info", - "snowbridge-core 0.22.0", + "snowbridge-core 0.23.0", "snowbridge-outbound-queue-primitives", "sp-core", "sp-io", @@ -8828,7 +8828,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-balances-erc20" -version = "0.22.0" +version = "0.23.0" dependencies = [ "fp-evm", "frame-support", @@ -8851,7 +8851,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-batch" -version = "0.22.0" +version = "0.23.0" dependencies = [ "evm", "fp-evm", @@ -8890,7 +8890,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-call-permit" -version = "0.22.0" +version = "0.23.0" dependencies = [ "evm", "fp-evm", @@ -8956,7 +8956,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-datahaven-native-transfer" -version = "0.22.0" +version = "0.23.0" dependencies = [ "evm", "fp-evm", @@ -8970,7 +8970,7 @@ dependencies = [ "parity-scale-codec", "precompile-utils", "scale-info", - "snowbridge-core 0.22.0", + "snowbridge-core 0.23.0", "snowbridge-outbound-queue-primitives", "sp-core", "sp-io", @@ -9049,7 +9049,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-proxy" -version = "0.22.0" +version = "0.23.0" dependencies = [ "evm", "fp-evm", @@ -9093,7 +9093,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-registry" -version = "0.22.0" +version = "0.23.0" dependencies = [ "fp-evm", "frame-support", @@ -9144,7 +9144,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "snowbridge-core 0.22.0", + "snowbridge-core 0.23.0", "snowbridge-outbound-queue-primitives", "sp-core", "sp-io", @@ -9154,7 +9154,7 @@ dependencies = [ [[package]] name = "pallet-external-validators" -version = "0.22.0" +version = "0.23.0" dependencies = [ "frame-benchmarking", "frame-support", @@ -9178,7 +9178,7 @@ dependencies = [ [[package]] name = "pallet-external-validators-rewards" -version = "0.22.0" +version = "0.23.0" dependencies = [ "frame-benchmarking", "frame-support", @@ -9191,7 +9191,7 @@ dependencies = [ "pallet-timestamp", "parity-scale-codec", "scale-info", - "snowbridge-core 0.22.0", + "snowbridge-core 0.23.0", "snowbridge-outbound-queue-primitives", "sp-core", "sp-io", @@ -9417,7 +9417,7 @@ dependencies = [ [[package]] name = "pallet-outbound-commitment-store" -version = "0.22.0" +version = "0.23.0" dependencies = [ "frame-support", "frame-system", @@ -9541,7 +9541,7 @@ dependencies = [ [[package]] name = "pallet-proxy-genesis-companion" -version = "0.22.0" +version = "0.23.0" dependencies = [ "frame-support", "frame-system", @@ -9652,7 +9652,7 @@ dependencies = [ [[package]] name = "pallet-session-benchmarking" -version = "0.22.0" +version = "0.23.0" dependencies = [ "frame-benchmarking", "frame-support", @@ -14800,7 +14800,7 @@ dependencies = [ [[package]] name = "snowbridge-beacon-primitives" -version = "0.22.0" +version = "0.23.0" dependencies = [ "byte-slice-cast", "frame-support", @@ -14845,7 +14845,7 @@ dependencies = [ [[package]] name = "snowbridge-core" -version = "0.22.0" +version = "0.23.0" dependencies = [ "bp-relayers", "ethabi-decode", @@ -14922,8 +14922,8 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "snowbridge-beacon-primitives 0.22.0", - "snowbridge-core 0.22.0", + "snowbridge-beacon-primitives 0.23.0", + "snowbridge-core 0.23.0", "snowbridge-verification-primitives", "sp-core", "sp-io", @@ -14936,7 +14936,7 @@ dependencies = [ [[package]] name = "snowbridge-merkle-tree" -version = "0.22.0" +version = "0.23.0" dependencies = [ "array-bytes", "hex", @@ -14977,7 +14977,7 @@ dependencies = [ [[package]] name = "snowbridge-outbound-queue-primitives" -version = "0.22.0" +version = "0.23.0" dependencies = [ "alloy-core", "ethabi-decode", @@ -14989,7 +14989,7 @@ dependencies = [ "parity-scale-codec", "polkadot-parachain-primitives", "scale-info", - "snowbridge-core 0.22.0", + "snowbridge-core 0.23.0", "snowbridge-verification-primitives", "sp-arithmetic", "sp-core", @@ -15003,12 +15003,12 @@ dependencies = [ [[package]] name = "snowbridge-outbound-queue-v2-runtime-api" -version = "0.22.0" +version = "0.23.0" dependencies = [ "frame-support", "parity-scale-codec", "scale-info", - "snowbridge-core 0.22.0", + "snowbridge-core 0.23.0", "snowbridge-merkle-tree", "snowbridge-outbound-queue-primitives", "sp-api", @@ -15018,7 +15018,7 @@ dependencies = [ [[package]] name = "snowbridge-pallet-ethereum-client" -version = "0.22.0" +version = "0.23.0" dependencies = [ "frame-benchmarking", "frame-support", @@ -15031,8 +15031,8 @@ dependencies = [ "scale-info", "serde", "serde_json", - "snowbridge-beacon-primitives 0.22.0", - "snowbridge-core 0.22.0", + "snowbridge-beacon-primitives 0.23.0", + "snowbridge-core 0.23.0", "snowbridge-ethereum 0.3.0", "snowbridge-inbound-queue-primitives", "snowbridge-pallet-ethereum-client-fixtures", @@ -15048,8 +15048,8 @@ name = "snowbridge-pallet-ethereum-client-fixtures" version = "0.9.0" dependencies = [ "hex-literal 0.3.4", - "snowbridge-beacon-primitives 0.22.0", - "snowbridge-core 0.22.0", + "snowbridge-beacon-primitives 0.23.0", + "snowbridge-core 0.23.0", "snowbridge-inbound-queue-primitives", "sp-core", "sp-std", @@ -15057,7 +15057,7 @@ dependencies = [ [[package]] name = "snowbridge-pallet-inbound-queue-v2" -version = "0.22.0" +version = "0.23.0" dependencies = [ "alloy-core", "bp-relayers", @@ -15071,8 +15071,8 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "snowbridge-beacon-primitives 0.22.0", - "snowbridge-core 0.22.0", + "snowbridge-beacon-primitives 0.23.0", + "snowbridge-core 0.23.0", "snowbridge-inbound-queue-primitives", "snowbridge-pallet-ethereum-client", "snowbridge-pallet-inbound-queue-v2-fixtures", @@ -15093,8 +15093,8 @@ name = "snowbridge-pallet-inbound-queue-v2-fixtures" version = "0.10.0" dependencies = [ "hex-literal 0.3.4", - "snowbridge-beacon-primitives 0.22.0", - "snowbridge-core 0.22.0", + "snowbridge-beacon-primitives 0.23.0", + "snowbridge-core 0.23.0", "snowbridge-inbound-queue-primitives", "sp-core", "sp-std", @@ -15124,7 +15124,7 @@ dependencies = [ [[package]] name = "snowbridge-pallet-outbound-queue-v2" -version = "0.22.0" +version = "0.23.0" dependencies = [ "alloy-core", "bp-relayers", @@ -15138,8 +15138,8 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "snowbridge-beacon-primitives 0.22.0", - "snowbridge-core 0.22.0", + "snowbridge-beacon-primitives 0.23.0", + "snowbridge-core 0.23.0", "snowbridge-inbound-queue-primitives", "snowbridge-merkle-tree", "snowbridge-outbound-queue-primitives", @@ -15170,7 +15170,7 @@ dependencies = [ "parity-scale-codec", "polkadot-primitives", "scale-info", - "snowbridge-core 0.22.0", + "snowbridge-core 0.23.0", "snowbridge-outbound-queue-primitives", "snowbridge-pallet-outbound-queue", "sp-core", @@ -15183,7 +15183,7 @@ dependencies = [ [[package]] name = "snowbridge-pallet-system-v2" -version = "0.22.0" +version = "0.23.0" dependencies = [ "frame-benchmarking", "frame-support", @@ -15195,7 +15195,7 @@ dependencies = [ "parity-scale-codec", "polkadot-primitives", "scale-info", - "snowbridge-core 0.22.0", + "snowbridge-core 0.23.0", "snowbridge-outbound-queue-primitives", "snowbridge-pallet-outbound-queue-v2", "snowbridge-pallet-system", @@ -15211,10 +15211,10 @@ dependencies = [ [[package]] name = "snowbridge-system-v2-runtime-api" -version = "0.22.0" +version = "0.23.0" dependencies = [ "parity-scale-codec", - "snowbridge-core 0.22.0", + "snowbridge-core 0.23.0", "sp-api", "sp-std", "staging-xcm", @@ -15222,7 +15222,7 @@ dependencies = [ [[package]] name = "snowbridge-test-utils" -version = "0.22.0" +version = "0.23.0" dependencies = [ "frame-benchmarking", "frame-support", @@ -15242,12 +15242,12 @@ dependencies = [ [[package]] name = "snowbridge-verification-primitives" -version = "0.22.0" +version = "0.23.0" dependencies = [ "frame-support", "parity-scale-codec", "scale-info", - "snowbridge-beacon-primitives 0.22.0", + "snowbridge-beacon-primitives 0.23.0", "sp-core", "sp-std", ] diff --git a/operator/Cargo.toml b/operator/Cargo.toml index 0299bb3b..7ebe6851 100644 --- a/operator/Cargo.toml +++ b/operator/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" homepage = "https://datahaven.xyz/" license = "GPL-3" repository = "https://github.com/datahavenxyz/datahaven" -version = "0.22.0" +version = "0.23.0" [workspace] members = [ diff --git a/operator/runtime/mainnet/src/lib.rs b/operator/runtime/mainnet/src/lib.rs index 7473be08..ade0d13a 100644 --- a/operator/runtime/mainnet/src/lib.rs +++ b/operator/runtime/mainnet/src/lib.rs @@ -142,7 +142,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // `spec_version`, and `authoring_version` are the same between Wasm and native. // This value is set to 200 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use // the compatible custom types. - spec_version: 1100, + spec_version: 1200, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, diff --git a/operator/runtime/stagenet/src/lib.rs b/operator/runtime/stagenet/src/lib.rs index 072d5a1b..d4bae772 100644 --- a/operator/runtime/stagenet/src/lib.rs +++ b/operator/runtime/stagenet/src/lib.rs @@ -145,7 +145,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // `spec_version`, and `authoring_version` are the same between Wasm and native. // This value is set to 200 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use // the compatible custom types. - spec_version: 1100, + spec_version: 1200, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, diff --git a/operator/runtime/testnet/src/lib.rs b/operator/runtime/testnet/src/lib.rs index ec43d783..0f53637a 100644 --- a/operator/runtime/testnet/src/lib.rs +++ b/operator/runtime/testnet/src/lib.rs @@ -142,7 +142,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // `spec_version`, and `authoring_version` are the same between Wasm and native. // This value is set to 200 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use // the compatible custom types. - spec_version: 1100, + spec_version: 1200, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, diff --git a/test/.papi/metadata/datahaven.scale b/test/.papi/metadata/datahaven.scale index fdcedc84d70ccc865ed894eb3d8c9e8155440ae4..edb59297e58d5a5d04e05e7e0d9e2392caf81074 100644 GIT binary patch delta 43 ucmeycTF7M3lnD>NB5w6D};1!6WJW(Q)9?JG4o-Ln9EaS#yz delta 43 ucmeycTF7M3lnD>NB>+E;3_0x=s9vjZ{5_LZ8P?pXkHbq}oo From 3ae7d2517e0747a07e17a9b29b880e01f1b0438d Mon Sep 17 00:00:00 2001 From: Ahmad Kaouk <56095276+ahmadkaouk@users.noreply.github.com> Date: Mon, 9 Feb 2026 14:28:34 +0100 Subject: [PATCH 5/7] refactor: clean old veto committee (#434) --- contracts/README.md | 4 ++-- contracts/config/anvil.json | 2 -- contracts/config/example.jsonc | 4 ---- contracts/config/mainnet-ethereum.json | 2 -- contracts/config/stagenet-hoodi.json | 2 -- contracts/config/testnet-hoodi.json | 2 -- contracts/script/deploy/Config.sol | 2 -- contracts/script/deploy/DeployParams.s.sol | 2 -- contracts/test/utils/AVSDeployer.sol | 5 ----- test/cli/handlers/contracts/status.ts | 3 +-- test/resources/datahaven-integration-test-flow.md | 1 - 11 files changed, 3 insertions(+), 26 deletions(-) diff --git a/contracts/README.md b/contracts/README.md index 9a737048..0d4042d2 100644 --- a/contracts/README.md +++ b/contracts/README.md @@ -1,6 +1,6 @@ # DataHaven AVS Smart Contracts -Implements the Actively Validated Service (AVS) logic for DataHaven, secured by EigenLayer. These contracts manage operator registration, handle cross-chain rewards via Snowbridge, and enforce slashing with a veto period. +Implements the Actively Validated Service (AVS) logic for DataHaven, secured by EigenLayer. These contracts manage operator registration, handle cross-chain rewards via Snowbridge, and enforce slashing. ## Project Structure @@ -65,6 +65,6 @@ Supported networks: `hoodi` (no mainnet config yet). Artifacts → `contracts/de 1. **Registration**: Validators register with EigenLayer via `DataHavenServiceManager`. 2. **Performance Tracking**: DataHaven computes reward points and sends a Merkle root to `RewardsRegistry` on Ethereum via Snowbridge. 3. **Rewards Claims**: Validators claim rewards on Ethereum from `RewardsRegistry` using Merkle proofs. -4. **Slashing**: Misbehavior triggers slashing (subject to veto period). +4. **Slashing**: Misbehavior triggers slashing. See `test/README.md` for full network integration tests. diff --git a/contracts/config/anvil.json b/contracts/config/anvil.json index ca1afec2..5b8cce9b 100644 --- a/contracts/config/anvil.json +++ b/contracts/config/anvil.json @@ -27,8 +27,6 @@ "avs": { "avsOwner": "0x976EA74026E726554dB657fA54763abd0C3a0aa9", "rewardsInitiator": "0x14dC79964da2C08b23698B3D3cc7Ca32193d9955", - "vetoCommitteeMember": "0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f", - "vetoWindowBlocks": 100, "validatorsStrategies": [ "0xbeaC0eeEeeeeEEeEeEEEEeeEEeEeeeEeeEEBEaC0" ] diff --git a/contracts/config/example.jsonc b/contracts/config/example.jsonc index 2550cb11..e57c1ec7 100644 --- a/contracts/config/example.jsonc +++ b/contracts/config/example.jsonc @@ -69,10 +69,6 @@ /// This is for the EigenLayer rewards distribution way, using the RewardsCoordinator. /// But for now, we're not using it, and instead sending the rewards directly. "rewardsInitiator": "0x14dC79964da2C08b23698B3D3cc7Ca32193d9955", - /// The address of the account that is a member of the Veto Committee for vetoing slashing. - "vetoCommitteeMember": "0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f", - /// The number of blocks that the Veto Committee will have to submit a veto. - "vetoWindowBlocks": 100, /// The EigenLayer strategy addresses for the Validators to stake into. /// The beaconChainETHStrategy is a virtual address representing native beacon chain ETH. /// All networks: diff --git a/contracts/config/mainnet-ethereum.json b/contracts/config/mainnet-ethereum.json index 6481710d..5a0e13fb 100644 --- a/contracts/config/mainnet-ethereum.json +++ b/contracts/config/mainnet-ethereum.json @@ -31,8 +31,6 @@ "avs": { "avsOwner": "0x0000000000000000000000000000000000000000", "rewardsInitiator": "0x0000000000000000000000000000000000000000", - "vetoCommitteeMember": "0x0000000000000000000000000000000000000000", - "vetoWindowBlocks": 7200, "validatorsStrategies": [ "0xbeaC0eeEeeeeEEeEeEEEEeeEEeEeeeEeeEEBEaC0", "0x93c4b944D05dfe6df7645A86cd2206016c51564D", diff --git a/contracts/config/stagenet-hoodi.json b/contracts/config/stagenet-hoodi.json index 0f8ed550..0dbd84c1 100644 --- a/contracts/config/stagenet-hoodi.json +++ b/contracts/config/stagenet-hoodi.json @@ -33,8 +33,6 @@ "avs": { "avsOwner": "0xe30a38ac89ffE5A86D5389Bfbf70C7EC766FbB6e", "rewardsInitiator": "0xe30a38ac89ffE5A86D5389Bfbf70C7EC766FbB6e", - "vetoCommitteeMember": "0xe30a38ac89ffE5A86D5389Bfbf70C7EC766FbB6e", - "vetoWindowBlocks": 100, "validatorsStrategies": [ "0xbeaC0eeEeeeeEEeEeEEEEeeEEeEeeeEeeEEBEaC0", "0xf8a1a66130d614c7360e868576d5e59203475fe0", diff --git a/contracts/config/testnet-hoodi.json b/contracts/config/testnet-hoodi.json index 784fba9d..1aa56fee 100644 --- a/contracts/config/testnet-hoodi.json +++ b/contracts/config/testnet-hoodi.json @@ -33,8 +33,6 @@ "avs": { "avsOwner": "0x0000000000000000000000000000000000000000", "rewardsInitiator": "0x0000000000000000000000000000000000000000", - "vetoCommitteeMember": "0x0000000000000000000000000000000000000000", - "vetoWindowBlocks": 100, "validatorsStrategies": [ "0xbeaC0eeEeeeeEEeEeEEEEeeEEeEeeeEeeEEBEaC0", "0xf8a1a66130d614c7360e868576d5e59203475fe0", diff --git a/contracts/script/deploy/Config.sol b/contracts/script/deploy/Config.sol index 5d731e95..ccb764b2 100644 --- a/contracts/script/deploy/Config.sol +++ b/contracts/script/deploy/Config.sol @@ -19,8 +19,6 @@ contract Config { struct AVSConfig { address avsOwner; address rewardsInitiator; - address vetoCommitteeMember; - uint32 vetoWindowBlocks; address[] validatorsStrategies; } diff --git a/contracts/script/deploy/DeployParams.s.sol b/contracts/script/deploy/DeployParams.s.sol index ca390006..1c21f32d 100644 --- a/contracts/script/deploy/DeployParams.s.sol +++ b/contracts/script/deploy/DeployParams.s.sol @@ -76,8 +76,6 @@ contract DeployParams is Script, Config { config.avsOwner = vm.parseJsonAddress(configJson, ".avs.avsOwner"); } config.rewardsInitiator = vm.parseJsonAddress(configJson, ".avs.rewardsInitiator"); - config.vetoCommitteeMember = vm.parseJsonAddress(configJson, ".avs.vetoCommitteeMember"); - config.vetoWindowBlocks = vm.parseJsonUint(configJson, ".avs.vetoWindowBlocks").toUint32(); config.validatorsStrategies = vm.parseJsonAddressArray(configJson, ".avs.validatorsStrategies"); diff --git a/contracts/test/utils/AVSDeployer.sol b/contracts/test/utils/AVSDeployer.sol index 13a4633d..a5fedb08 100644 --- a/contracts/test/utils/AVSDeployer.sol +++ b/contracts/test/utils/AVSDeployer.sol @@ -48,11 +48,6 @@ contract AVSDeployer is Test { DataHavenServiceManager public serviceManager; DataHavenServiceManager public serviceManagerImplementation; - // Truncation is intentional - deriving a deterministic mock address from hash - address public vetoCommitteeMember = - address(uint160(uint256(keccak256("vetoCommitteeMember")))); - uint32 public vetoWindowBlocks = 100; // 100 blocks veto window for tests - // EigenLayer contracts StrategyManager public strategyManager; StrategyManager public strategyManagerImplementation; diff --git a/test/cli/handlers/contracts/status.ts b/test/cli/handlers/contracts/status.ts index 76a86638..3c61e04b 100644 --- a/test/cli/handlers/contracts/status.ts +++ b/test/cli/handlers/contracts/status.ts @@ -24,8 +24,7 @@ export const showDeploymentPlanAndStatus = async (chain: string, environment?: s "Block Explorer": deploymentParams.blockExplorer, "Genesis Time": new Date(deploymentParams.genesisTime * 1000).toISOString(), "AVS Owner": `${config.avs.avsOwner.slice(0, 10)}...${config.avs.avsOwner.slice(-8)}`, - "Rewards Initiator": `${config.avs.rewardsInitiator.slice(0, 10)}...${config.avs.rewardsInitiator.slice(-8)}`, - "Veto Committee Member": `${config.avs.vetoCommitteeMember.slice(0, 10)}...${config.avs.vetoCommitteeMember.slice(-8)}` + "Rewards Initiator": `${config.avs.rewardsInitiator.slice(0, 10)}...${config.avs.rewardsInitiator.slice(-8)}` }; if (environment) { diff --git a/test/resources/datahaven-integration-test-flow.md b/test/resources/datahaven-integration-test-flow.md index 82b2a7f6..4dcc14ce 100644 --- a/test/resources/datahaven-integration-test-flow.md +++ b/test/resources/datahaven-integration-test-flow.md @@ -207,7 +207,6 @@ Another testing scenario is testing the operational aspects of the validator set 3. **Slashing Mechanisms** - Test slashing for various offenses - - Test veto committee mechanisms 4. **Operator Set Modifications** - Modify operator sets from Ethereum From ae5deb41e083f0f65ed6d7e2646a83db74920ba4 Mon Sep 17 00:00:00 2001 From: Steve Degosserie <723552+stiiifff@users.noreply.github.com> Date: Tue, 10 Feb 2026 10:12:16 +0100 Subject: [PATCH 6/7] feat(node): add Ethereum pub/sub RPC API (#435) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary - Wire the Frontier `EthPubSub` module into the node's RPC layer, enabling WebSocket-based `eth_subscribe`/`eth_unsubscribe` support for `newHeads`, `logs`, and `newPendingTransactions` - Use Ethereum-style hex (`0x`-prefixed) subscription IDs via `EthereumSubIdProvider` for client compatibility - Add Moonwall test suites (adapted from Moonbeam) covering block header subscriptions, log filtering (by address, topics, wildcards, conditional parameters), and pending transaction notifications ## Changes ### `operator/node/src/rpc.rs` - Import and merge `EthPubSub` / `EthPubSubApiServer` into the RPC module - Accept `subscription_task_executor` and `pubsub_notification_sinks` parameters in `create_full()` - Remove stale commented-out boilerplate ### `operator/node/src/service.rs` - Clone `pubsub_notification_sinks` and forward it (along with `subscription_executor`) into the RPC factory closure - Set `config.rpc.id_provider` to `EthereumSubIdProvider` for Ethereum-compatible subscription IDs ### `test/moonwall/suites/dev/stagenet/subscription/` - `test-subscription.ts` — `newHeads`: subscription ID format, block header field validation - `test-subscription-logs.ts` — `logs`: basic log notification on contract deployment - `test-subscription-logs2.ts` — `logs`: filtering by single/multiple addresses, topics, wildcards, conditional and combined parameters (8 cases) - `test-subscription-pending.ts` — `newPendingTransactions`: pending tx hash notification Co-authored-by: Claude Opus 4.6 Co-authored-by: Ahmad Kaouk <56095276+ahmadkaouk@users.noreply.github.com> --- operator/node/src/rpc.rs | 38 ++-- operator/node/src/service.rs | 76 ++++--- .../subscription/test-subscription-logs.ts | 43 ++++ .../subscription/test-subscription-logs2.ts | 195 ++++++++++++++++++ .../subscription/test-subscription-pending.ts | 30 +++ .../subscription/test-subscription.ts | 61 ++++++ 6 files changed, 396 insertions(+), 47 deletions(-) create mode 100644 test/moonwall/suites/dev/stagenet/subscription/test-subscription-logs.ts create mode 100644 test/moonwall/suites/dev/stagenet/subscription/test-subscription-logs2.ts create mode 100644 test/moonwall/suites/dev/stagenet/subscription/test-subscription-pending.ts create mode 100644 test/moonwall/suites/dev/stagenet/subscription/test-subscription.ts diff --git a/operator/node/src/rpc.rs b/operator/node/src/rpc.rs index 81d59467..25380cdb 100644 --- a/operator/node/src/rpc.rs +++ b/operator/node/src/rpc.rs @@ -24,10 +24,13 @@ use crate::consensus::BabeConsensusDataProvider; use crate::eth::DefaultEthConfig; use datahaven_runtime_common::{time::SLOT_DURATION, Block, BlockNumber, Hash}; -use fc_rpc::TxPool; use fc_rpc::{Eth, EthBlockDataCacheTask, EthFilter, Net, Web3}; +use fc_rpc::{EthPubSub, TxPool}; use fc_rpc_core::types::{FeeHistoryCache, FilterPool}; -use fc_rpc_core::{EthApiServer, EthFilterApiServer, NetApiServer, TxPoolApiServer, Web3ApiServer}; +use fc_rpc_core::{ + EthApiServer, EthFilterApiServer, EthPubSubApiServer, NetApiServer, TxPoolApiServer, + Web3ApiServer, +}; use fc_storage::StorageOverride; use fp_rpc::EthereumRuntimeRPCApi; use jsonrpsee::RpcModule; @@ -111,6 +114,12 @@ where /// Instantiate all full RPC extensions. pub fn create_full( deps: FullDeps, + subscription_task_executor: sc_rpc::SubscriptionTaskExecutor, + pubsub_notification_sinks: Arc< + fc_mapping_sync::EthereumBlockNotificationSinks< + fc_mapping_sync::EthereumBlockNotification, + >, + >, ) -> Result, Box> where P: TransactionPool + 'static, @@ -263,6 +272,17 @@ where )?; module.merge(Web3::new(Arc::clone(&client)).into_rpc())?; + module.merge( + EthPubSub::new( + pool, + Arc::clone(&client), + sync.clone(), + subscription_task_executor, + overrides, + pubsub_notification_sinks.clone(), + ) + .into_rpc(), + )?; if let Some(command_sink) = command_sink { module.merge( @@ -275,19 +295,5 @@ where let tx_pool = TxPool::new(client.clone(), graph.clone()); module.merge(tx_pool.into_rpc())?; - // module.merge(FrontierFinality::new(client.clone(), frontier_backend.clone()).into_rpc())?; - - // Extend this RPC with a custom API by using the following syntax. - // `YourRpcStruct` should have a reference to a client, which is needed - // to call into the runtime. - // `module.merge(YourRpcTrait::into_rpc(YourRpcStruct::new(ReferenceToClient, ...)))?;` - - // You probably want to enable the `rpc v2 chainSpec` API as well - // - // let chain_name = chain_spec.name().to_string(); - // let genesis_hash = client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"); - // let properties = chain_spec.properties(); - // module.merge(ChainSpec::new(chain_name, genesis_hash, properties).into_rpc())?; - Ok(module) } diff --git a/operator/node/src/service.rs b/operator/node/src/service.rs index 11c6a247..710d6e81 100644 --- a/operator/node/src/service.rs +++ b/operator/node/src/service.rs @@ -439,7 +439,7 @@ pub async fn new_full_impl< RuntimeApi, N: sc_network::NetworkBackend::Hash>, >( - config: Configuration, + mut config: Configuration, mut eth_config: EthConfiguration, role_options: Option, indexer_options: Option, @@ -673,7 +673,7 @@ where }, storage_override, sync: sync_service.clone(), - pubsub_notification_sinks, + pubsub_notification_sinks: pubsub_notification_sinks.clone(), }, ) .await; @@ -693,38 +693,52 @@ where let fee_history_limit = eth_config.fee_history_limit; let sync = sync_service.clone(); - Box::new(move |subscription_executor| { - let deps = crate::rpc::FullDeps { - client: client.clone(), - pool: pool.clone(), - graph: pool.pool().clone(), - beefy: BeefyDeps:: { - beefy_finality_proof_stream: beefy_rpc_links.from_voter_justif_stream.clone(), - beefy_best_block_stream: beefy_rpc_links.from_voter_best_beefy_stream.clone(), + Box::new( + move |subscription_executor: sc_rpc::SubscriptionTaskExecutor| { + let deps = crate::rpc::FullDeps { + client: client.clone(), + pool: pool.clone(), + graph: pool.pool().clone(), + beefy: BeefyDeps:: { + beefy_finality_proof_stream: beefy_rpc_links + .from_voter_justif_stream + .clone(), + beefy_best_block_stream: beefy_rpc_links + .from_voter_best_beefy_stream + .clone(), + subscription_executor: subscription_executor.clone(), + }, + max_past_logs, + fee_history_limit, + fee_history_cache: fee_history_cache.clone(), + network: Arc::new(network.clone()), + sync: sync.clone(), + filter_pool: filter_pool.clone(), + block_data_cache: block_data_cache.clone(), + overrides: overrides.clone(), + is_authority: is_authority.clone(), + command_sink: command_sink.clone(), + backend: backend.clone(), + frontier_backend: match &*frontier_backend { + fc_db::Backend::KeyValue(b) => b.clone(), + fc_db::Backend::Sql(b) => b.clone(), + }, + forced_parent_hashes: None, + maybe_storage_hub_client_config: maybe_storage_hub_client_rpc_config.clone(), + }; + crate::rpc::create_full( + deps, subscription_executor, - }, - max_past_logs, - fee_history_limit, - fee_history_cache: fee_history_cache.clone(), - network: Arc::new(network.clone()), - sync: sync.clone(), - filter_pool: filter_pool.clone(), - block_data_cache: block_data_cache.clone(), - overrides: overrides.clone(), - is_authority: is_authority.clone(), - command_sink: command_sink.clone(), - backend: backend.clone(), - frontier_backend: match &*frontier_backend { - fc_db::Backend::KeyValue(b) => b.clone(), - fc_db::Backend::Sql(b) => b.clone(), - }, - forced_parent_hashes: None, - maybe_storage_hub_client_config: maybe_storage_hub_client_rpc_config.clone(), - }; - crate::rpc::create_full(deps).map_err(Into::into) - }) + pubsub_notification_sinks.clone(), + ) + .map_err(Into::into) + }, + ) }; + // Use Ethereum-style hex subscription IDs (0x-prefixed) instead of jsonrpsee defaults. + config.rpc.id_provider = Some(Box::new(fc_rpc::EthereumSubIdProvider)); + let rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams { network: Arc::new(network.clone()), client: client.clone(), diff --git a/test/moonwall/suites/dev/stagenet/subscription/test-subscription-logs.ts b/test/moonwall/suites/dev/stagenet/subscription/test-subscription-logs.ts new file mode 100644 index 00000000..1f33aaa1 --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/subscription/test-subscription-logs.ts @@ -0,0 +1,43 @@ +import { describeSuite, expect } from "@moonwall/cli"; + +describeSuite({ + id: "D023501", + title: "Subscription - Logs", + foundationMethods: "dev", + testCases: ({ context, it, log }) => { + it({ + id: "T01", + title: "should send a notification on new transaction", + test: async function () { + const logs: any[] = []; + const sub = await context.web3().eth.subscribe("logs"); + + await new Promise(async (resolve, reject) => { + sub.once("data", async (event) => { + logs.push(event); + resolve("success"); + }); + + sub.once("error", (error) => { + console.error(error); + reject(error); + }); + + await context.deployContract!("EventEmitter"); + }); + + const block = await context.viem().getBlock(); + + expect(logs[0]).to.include({ + blockHash: block.hash, + blockNumber: block.number, + data: "0x", + logIndex: 0n, + removed: false, + transactionHash: block.transactions[0], + transactionIndex: 0n, + }); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/subscription/test-subscription-logs2.ts b/test/moonwall/suites/dev/stagenet/subscription/test-subscription-logs2.ts new file mode 100644 index 00000000..2b58d33b --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/subscription/test-subscription-logs2.ts @@ -0,0 +1,195 @@ +import { beforeAll, describeSuite, expect } from "@moonwall/cli"; +import { ALITH_CONTRACT_ADDRESSES } from "@moonwall/util"; +import type { Log } from "web3"; + +describeSuite({ + id: "D023502", + title: "Subscription - Logs", + foundationMethods: "dev", + testCases: ({ context, it, log }) => { + let deployedContract: `0x${string}`; + let deployHash: `0x${string}`; + + let subSingleAddPromise: Promise; + let subMultiAddPromise: Promise; + let subTopicPromise: Promise; + let subTopicWildcardPromise: Promise; + let subTopicListPromise: Promise; + let subTopicCondPromise: Promise; + let subTopicMultiCondPromise: Promise; + let subTopicWildAndCondPromise: Promise; + + beforeAll(async () => { + const openSub = async (filter?: object) => await context.web3().eth.subscribe("logs", filter); + + const onData = (logSub: any) => { + return new Promise((resolve) => { + logSub.once("data", resolve); + }); + }; + + const [ + singleSub, + multiSub, + subTopic, + subTopicWildcard, + subTopicList, + subTopicCond, + subTopicMultiCond, + subTopicWildAndCond, + ] = await Promise.all([ + openSub({ + address: ALITH_CONTRACT_ADDRESSES[0], + }), + openSub({ + address: [ + ALITH_CONTRACT_ADDRESSES[3], + ALITH_CONTRACT_ADDRESSES[2], + ALITH_CONTRACT_ADDRESSES[1], + ALITH_CONTRACT_ADDRESSES[0], + ], + }), + openSub({ + topics: ["0x0040d54d5e5b097202376b55bcbaaedd2ee468ce4496f1d30030c4e5308bf94d"], + }), + openSub({ + topics: [null, "0x000000000000000000000000f24ff3a9cf04c71dbc94d0b566f7a27b94566cac"], + }), + openSub({ + topics: [ + ["0x0040d54d5e5b097202376b55bcbaaedd2ee468ce4496f1d30030c4e5308bf94d"], + ["0x000000000000000000000000f24ff3a9cf04c71dbc94d0b566f7a27b94566cac"], + ], + }), + + openSub({ + topics: [ + "0x0040d54d5e5b097202376b55bcbaaedd2ee468ce4496f1d30030c4e5308bf94d", + ["0x000000000000000000000000f24ff3a9cf04c71dbc94d0b566f7a27b94566cac"], + ], + }), + + openSub({ + topics: [ + "0x0040d54d5e5b097202376b55bcbaaedd2ee468ce4496f1d30030c4e5308bf94d", + [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000f24ff3a9cf04c71dbc94d0b566f7a27b94566cac", + ], + ], + }), + openSub({ + topics: [ + null, + [ + "0x000000000000000000000000f24ff3a9cf04c71dbc94d0b566f7a27b94566cac", + "0x0000000000000000000000000000000000000000000000000000000000000000", + ], + null, + ], + }), + ]); + + subSingleAddPromise = onData(singleSub); + subMultiAddPromise = onData(multiSub); + subTopicPromise = onData(subTopic); + subTopicWildcardPromise = onData(subTopicWildcard); + subTopicListPromise = onData(subTopicList); + subTopicCondPromise = onData(subTopicCond); + subTopicMultiCondPromise = onData(subTopicMultiCond); + subTopicWildAndCondPromise = onData(subTopicWildAndCond); + + const { contractAddress, hash } = await context.deployContract!("EventEmitter"); + deployedContract = contractAddress; + deployHash = hash; + }); + + it({ + id: "T01", + title: "should be able to filter by address", + test: async function () { + const eventLog = await subSingleAddPromise; + expect(eventLog.blockNumber).toBe(1n); + expect(eventLog.address).toBe(deployedContract.toLowerCase()); + expect(eventLog.transactionHash).toBe(deployHash); + }, + }); + + it({ + id: "T02", + title: "should be able to filter by multiple addresses", + test: async function () { + const eventLog = await subMultiAddPromise; + expect(eventLog.blockNumber).toBe(1n); + expect(eventLog.address).toBe(deployedContract.toLowerCase()); + expect(eventLog.transactionHash).toBe(deployHash); + }, + }); + + it({ + id: "T03", + title: "should be able to filter by topic", + test: async function () { + const eventLog = await subTopicPromise; + expect(eventLog.blockNumber).toBe(1n); + expect(eventLog.address).toBe(deployedContract.toLowerCase()); + expect(eventLog.transactionHash).toBe(deployHash); + }, + }); + + it({ + id: "T04", + title: "should be able to filter by topic wildcards", + test: async function () { + const eventLog = await subTopicWildcardPromise; + expect(eventLog.blockNumber).toBe(1n); + expect(eventLog.address).toBe(deployedContract.toLowerCase()); + expect(eventLog.transactionHash).toBe(deployHash); + }, + }); + + it({ + id: "T05", + title: "should be able to filter by topic list", + test: async function () { + const eventLog = await subTopicListPromise; + expect(eventLog.blockNumber).toBe(1n); + expect(eventLog.address).toBe(deployedContract.toLowerCase()); + expect(eventLog.transactionHash).toBe(deployHash); + }, + }); + + it({ + id: "T06", + title: "should be able to filter by topic conditional parameters", + test: async function () { + const eventLog = await subTopicCondPromise; + expect(eventLog.blockNumber).toBe(1n); + expect(eventLog.address).toBe(deployedContract.toLowerCase()); + expect(eventLog.transactionHash).toBe(deployHash); + }, + }); + + it({ + id: "T07", + title: "should support multiple topic conditional parameters", + test: async function () { + const eventLog = await subTopicMultiCondPromise; + expect(eventLog.blockNumber).toBe(1n); + expect(eventLog.address).toBe(deployedContract.toLowerCase()); + expect(eventLog.transactionHash).toBe(deployHash); + }, + }); + + it({ + id: "T08", + title: "should combine topic wildcards and conditional parameters", + test: async function () { + const eventLog = await subTopicWildAndCondPromise; + expect(eventLog.blockNumber).toBe(1n); + expect(eventLog.address).toBe(deployedContract.toLowerCase()); + expect(eventLog.transactionHash).toBe(deployHash); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/subscription/test-subscription-pending.ts b/test/moonwall/suites/dev/stagenet/subscription/test-subscription-pending.ts new file mode 100644 index 00000000..d053667b --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/subscription/test-subscription-pending.ts @@ -0,0 +1,30 @@ +import { describeSuite, expect } from "@moonwall/cli"; +import { BALTATHAR_ADDRESS, GLMR, createRawTransfer, sendRawTransaction } from "@moonwall/util"; +import { setTimeout } from "node:timers/promises"; + +describeSuite({ + id: "D023504", + title: "Subscription - Pending transactions", + foundationMethods: "dev", + testCases: ({ context, it, log }) => { + it({ + id: "T01", + title: "should return a valid subscriptionId", + test: async function () { + let response: any; + const sub = await context.web3().eth.subscribe("newPendingTransactions"); + + sub.once("data", (data) => { + response = data; + }); + + const rawTx = await createRawTransfer(context, BALTATHAR_ADDRESS, GLMR); + const hash = await sendRawTransaction(context, rawTx); + await setTimeout(200); + + expect(response).not.toBeUndefined(); + expect(response).toBe(hash); + }, + }); + }, +}); diff --git a/test/moonwall/suites/dev/stagenet/subscription/test-subscription.ts b/test/moonwall/suites/dev/stagenet/subscription/test-subscription.ts new file mode 100644 index 00000000..ae853cfb --- /dev/null +++ b/test/moonwall/suites/dev/stagenet/subscription/test-subscription.ts @@ -0,0 +1,61 @@ +import { beforeAll, describeSuite, expect } from "@moonwall/cli"; +import { ALITH_ADDRESS, BALTATHAR_ADDRESS, createRawTransfer } from "@moonwall/util"; +import { type PublicClient, createPublicClient, webSocket } from "viem"; + +describeSuite({ + id: "D023505", + title: "Subscription - Block headers", + foundationMethods: "dev", + testCases: ({ context, it, log }) => { + let client: PublicClient; + + beforeAll(async () => { + const transport = webSocket(context.viem().transport.url.replace("http", "ws")); + client = createPublicClient({ + transport, + }); + }); + + it({ + id: "T01", + title: "should return a valid subscriptionId", + test: async function () { + const result = (await client.transport.request({ + method: "eth_subscribe", + params: ["newHeads"], + })) as any; + + expect(result.length).toBe(34); + }, + }); + + it({ + id: "T02", + title: "should send notification on new block", + test: async function () { + const blocks: any[] = []; + const unwatch = client.watchBlocks({ + onBlock: (block) => blocks.push(block), + }); + + await context.createBlock(createRawTransfer(context, BALTATHAR_ADDRESS, 0)); + unwatch(); + + const block = await context.viem().getBlock(); + + expect(blocks[0]).to.include({ + author: ALITH_ADDRESS.toLowerCase(), + difficulty: 0n, + extraData: "0x", + logsBloom: `0x${"0".repeat(512)}`, + miner: ALITH_ADDRESS.toLowerCase(), + sha3Uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + }); + expect(blocks[0].nonce).to.be.eq("0x0000000000000000"); + // Verify subscription roots match the block fetched via RPC + expect(blocks[0].receiptsRoot).toBe(block.receiptsRoot); + expect(blocks[0].transactionsRoot).toBe(block.transactionsRoot); + }, + }); + }, +}); From a2aec422548f451ac6a5558b835f38d3791a2845 Mon Sep 17 00:00:00 2001 From: Facundo Farall <37149322+ffarall@users.noreply.github.com> Date: Tue, 10 Feb 2026 07:02:35 -0300 Subject: [PATCH 7/7] build: :arrow_up: Upgrade to StorageHub v0.4.0 (#437) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR upgrades DataHaven to StorageHub version [0.4.0](https://github.com/Moonsong-Labs/storage-hub/releases/tag/v0.4.0). ## ⚠️ Breaking Changes ⚠️ This is a minor release, and as such, contains breaking changes detailed in the corresponding [StorageHub release](https://github.com/Moonsong-Labs/storage-hub/releases/tag/v0.4.0). --------- Co-authored-by: Steve Degosserie <723552+stiiifff@users.noreply.github.com> --- operator/Cargo.lock | 148 +++++++++--------- operator/Cargo.toml | 70 ++++----- operator/node/src/cli.rs | 19 ++- .../mainnet/src/configs/runtime_params.rs | 12 +- operator/runtime/mainnet/src/lib.rs | 3 + .../stagenet/src/configs/runtime_params.rs | 12 +- operator/runtime/stagenet/src/lib.rs | 3 + .../testnet/src/configs/runtime_params.rs | 12 +- operator/runtime/testnet/src/lib.rs | 3 + test/.papi/descriptors/package.json | 2 +- test/.papi/metadata/datahaven.scale | Bin 627696 -> 630941 bytes 11 files changed, 155 insertions(+), 129 deletions(-) diff --git a/operator/Cargo.lock b/operator/Cargo.lock index 3aa769c4..1f6d04ec 100644 --- a/operator/Cargo.lock +++ b/operator/Cargo.lock @@ -8639,8 +8639,8 @@ dependencies = [ [[package]] name = "pallet-bucket-nfts" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "frame-benchmarking", "frame-support", @@ -8696,8 +8696,8 @@ dependencies = [ [[package]] name = "pallet-cr-randomness" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "frame-support", "frame-system", @@ -8980,8 +8980,8 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-file-system" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "fp-account", "fp-evm", @@ -9220,8 +9220,8 @@ dependencies = [ [[package]] name = "pallet-file-system" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "frame-benchmarking", "frame-support", @@ -9249,8 +9249,8 @@ dependencies = [ [[package]] name = "pallet-file-system-runtime-api" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "parity-scale-codec", "scale-info", @@ -9445,8 +9445,8 @@ dependencies = [ [[package]] name = "pallet-payment-streams" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "frame-benchmarking", "frame-support", @@ -9465,8 +9465,8 @@ dependencies = [ [[package]] name = "pallet-payment-streams-runtime-api" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "parity-scale-codec", "scale-info", @@ -9493,8 +9493,8 @@ dependencies = [ [[package]] name = "pallet-proofs-dealer" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "frame-benchmarking", "frame-support", @@ -9519,8 +9519,8 @@ dependencies = [ [[package]] name = "pallet-proofs-dealer-runtime-api" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "parity-scale-codec", "scale-info", @@ -9558,8 +9558,8 @@ dependencies = [ [[package]] name = "pallet-randomness" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "frame-benchmarking", "frame-support", @@ -9696,8 +9696,8 @@ dependencies = [ [[package]] name = "pallet-storage-providers" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "frame-benchmarking", "frame-support", @@ -9718,8 +9718,8 @@ dependencies = [ [[package]] name = "pallet-storage-providers-runtime-api" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "parity-scale-codec", "scale-info", @@ -13881,8 +13881,8 @@ dependencies = [ [[package]] name = "shc-actors-derive" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "once_cell", "proc-macro2", @@ -13894,8 +13894,8 @@ dependencies = [ [[package]] name = "shc-actors-framework" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "anyhow", "bincode", @@ -13913,8 +13913,8 @@ dependencies = [ [[package]] name = "shc-blockchain-service" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "anyhow", "array-bytes", @@ -13969,8 +13969,8 @@ dependencies = [ [[package]] name = "shc-blockchain-service-db" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "chrono", "diesel", @@ -13993,8 +13993,8 @@ dependencies = [ [[package]] name = "shc-client" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "anyhow", "array-bytes", @@ -14067,8 +14067,8 @@ dependencies = [ [[package]] name = "shc-common" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "anyhow", "bigdecimal", @@ -14131,8 +14131,8 @@ dependencies = [ [[package]] name = "shc-file-manager" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "bincode", "hash-db", @@ -14155,8 +14155,8 @@ dependencies = [ [[package]] name = "shc-file-transfer-service" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "anyhow", "array-bytes", @@ -14184,8 +14184,8 @@ dependencies = [ [[package]] name = "shc-fisherman-service" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "async-trait", "diesel", @@ -14215,8 +14215,8 @@ dependencies = [ [[package]] name = "shc-forest-manager" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "anyhow", "async-trait", @@ -14241,8 +14241,8 @@ dependencies = [ [[package]] name = "shc-indexer-db" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "bigdecimal", "chrono", @@ -14269,8 +14269,8 @@ dependencies = [ [[package]] name = "shc-indexer-service" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "anyhow", "array-bytes", @@ -14320,8 +14320,8 @@ dependencies = [ [[package]] name = "shc-rpc" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "array-bytes", "async-trait", @@ -14366,8 +14366,8 @@ dependencies = [ [[package]] name = "shc-telemetry" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "log", "substrate-prometheus-endpoint", @@ -14383,8 +14383,8 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "shp-constants" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "sp-core", "sp-runtime", @@ -14392,8 +14392,8 @@ dependencies = [ [[package]] name = "shp-data-price-updater" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "frame-support", "parity-scale-codec", @@ -14407,8 +14407,8 @@ dependencies = [ [[package]] name = "shp-file-key-verifier" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "frame-support", "parity-scale-codec", @@ -14425,8 +14425,8 @@ dependencies = [ [[package]] name = "shp-file-metadata" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "hex", "num-bigint", @@ -14441,8 +14441,8 @@ dependencies = [ [[package]] name = "shp-forest-verifier" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "frame-support", "parity-scale-codec", @@ -14458,16 +14458,16 @@ dependencies = [ [[package]] name = "shp-opaque" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "sp-runtime", ] [[package]] name = "shp-session-keys" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "async-trait", "parity-scale-codec", @@ -14481,8 +14481,8 @@ dependencies = [ [[package]] name = "shp-traits" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "frame-support", "parity-scale-codec", @@ -14495,8 +14495,8 @@ dependencies = [ [[package]] name = "shp-treasury-funding" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "log", "shp-traits", @@ -14506,8 +14506,8 @@ dependencies = [ [[package]] name = "shp-tx-implicits-runtime-api" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "parity-scale-codec", "scale-info", @@ -14519,8 +14519,8 @@ dependencies = [ [[package]] name = "shp-types" -version = "0.3.5" -source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.3.5#e21f2316c07e9fc43fc67f20373e6c24a8f4d5ae" +version = "0.4.0" +source = "git+https://github.com/Moonsong-Labs/storage-hub.git?tag=v0.4.0#ea2611cb3b47e448fa2812082e130c697b66277a" dependencies = [ "sp-core", "sp-runtime", diff --git a/operator/Cargo.toml b/operator/Cargo.toml index 7ebe6851..ee2d6933 100644 --- a/operator/Cargo.toml +++ b/operator/Cargo.toml @@ -28,7 +28,6 @@ datahaven-stagenet-runtime = { path = "./runtime/stagenet", default-features = f datahaven-testnet-runtime = { path = "./runtime/testnet", default-features = false } dhp-bridge = { path = "./primitives/bridge", default-features = false } pallet-datahaven-native-transfer = { path = "./pallets/datahaven-native-transfer", default-features = false } -pallet-session-benchmarking = { path = "./pallets/session-benchmarking", default-features = false } pallet-evm-precompile-balances-erc20 = { path = "./precompiles/erc20-balances", default-features = false } pallet-evm-precompile-batch = { path = "./precompiles/batch", default-features = false } pallet-evm-precompile-call-permit = { path = "./precompiles/call-permit", default-features = false } @@ -45,6 +44,7 @@ pallet-external-validators = { path = "./pallets/external-validators", default-f pallet-external-validators-rewards = { path = "./pallets/external-validators-rewards", default-features = false } pallet-outbound-commitment-store = { path = "./pallets/outbound-commitment-store", default-features = false } pallet-proxy-genesis-companion = { path = "./pallets/proxy-genesis-companion", default-features = false } +pallet-session-benchmarking = { path = "./pallets/session-benchmarking", default-features = false } # Crates.io (wasm) alloy-core = { version = "0.8.15", default-features = false } @@ -272,42 +272,42 @@ fc-storage = { git = "https://github.com/polkadot-evm/frontier", branch = "stabl # StorageHub ## Runtime -pallet-bucket-nfts = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -pallet-cr-randomness = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -pallet-file-system = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -pallet-file-system-runtime-api = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -pallet-payment-streams = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -pallet-payment-streams-runtime-api = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -pallet-proofs-dealer = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -pallet-proofs-dealer-runtime-api = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -pallet-randomness = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -pallet-storage-providers = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -pallet-storage-providers-runtime-api = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shp-constants = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shp-data-price-updater = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shp-file-key-verifier = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shp-file-metadata = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shp-forest-verifier = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shp-traits = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shp-treasury-funding = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } +pallet-bucket-nfts = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.0", default-features = false } +pallet-cr-randomness = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.0", default-features = false } +pallet-file-system = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.0", default-features = false } +pallet-file-system-runtime-api = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.0", default-features = false } +pallet-payment-streams = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.0", default-features = false } +pallet-payment-streams-runtime-api = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.0", default-features = false } +pallet-proofs-dealer = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.0", default-features = false } +pallet-proofs-dealer-runtime-api = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.0", default-features = false } +pallet-randomness = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.0", default-features = false } +pallet-storage-providers = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.0", default-features = false } +pallet-storage-providers-runtime-api = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.0", default-features = false } +shp-constants = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.0", default-features = false } +shp-data-price-updater = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.0", default-features = false } +shp-file-key-verifier = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.0", default-features = false } +shp-file-metadata = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.0", default-features = false } +shp-forest-verifier = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.0", default-features = false } +shp-traits = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.0", default-features = false } +shp-treasury-funding = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.0", default-features = false } ## Client -shc-actors-derive = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shc-actors-framework = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shc-blockchain-service = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shc-client = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shc-common = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shc-file-manager = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shc-file-transfer-service = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shc-fisherman-service = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shc-forest-manager = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shc-indexer-db = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shc-indexer-service = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shc-rpc = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shp-opaque = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shp-tx-implicits-runtime-api = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } -shp-types = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } +shc-actors-derive = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.0", default-features = false } +shc-actors-framework = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.0", default-features = false } +shc-blockchain-service = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.0", default-features = false } +shc-client = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.0", default-features = false } +shc-common = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.0", default-features = false } +shc-file-manager = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.0", default-features = false } +shc-file-transfer-service = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.0", default-features = false } +shc-fisherman-service = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.0", default-features = false } +shc-forest-manager = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.0", default-features = false } +shc-indexer-db = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.0", default-features = false } +shc-indexer-service = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.0", default-features = false } +shc-rpc = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.0", default-features = false } +shp-opaque = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.0", default-features = false } +shp-tx-implicits-runtime-api = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.0", default-features = false } +shp-types = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.0", default-features = false } ## Precompiles -pallet-evm-precompile-file-system = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.3.5", default-features = false } +pallet-evm-precompile-file-system = { git = "https://github.com/Moonsong-Labs/storage-hub.git", tag = "v0.4.0", default-features = false } # Static linking diff --git a/operator/node/src/cli.rs b/operator/node/src/cli.rs index 1573aa77..51a881a4 100644 --- a/operator/node/src/cli.rs +++ b/operator/node/src/cli.rs @@ -741,9 +741,23 @@ pub struct FishermanConfigurations { pub fisherman_database_url: Option, /// Duration between batch deletion processing cycles (in seconds). - #[arg(long, default_value = "60", value_parser = clap::value_parser!(u64).range(1..))] + #[arg(long, default_value = "30", value_parser = clap::value_parser!(u64).range(1..))] pub fisherman_batch_interval_seconds: u64, + /// Cooldown between batch deletion attempts (in seconds). + /// + /// Set to `0` to disable cooldown. + #[arg(long, default_value = "1", value_parser = clap::value_parser!(u64).range(0..))] + pub fisherman_batch_cooldown_seconds: u64, + + /// Number of consecutive no-work batches required before switching to the slower idle polling interval. + /// + /// The minimum value is 2 because there are two kinds of work: User and Incomplete. + /// If we set the value to 1, a non-work batch in one kind of work will trigger the idle poll interval + /// on the other kind of work. + #[arg(long, default_value = "4", value_parser = clap::value_parser!(u8).range(1..))] + pub fisherman_consecutive_no_work_batches_threshold: u8, + /// Maximum number of files to process per batch deletion cycle. #[arg(long, default_value = "1000", value_parser = clap::value_parser!(u64).range(1..))] pub fisherman_batch_deletion_limit: u64, @@ -803,6 +817,9 @@ impl FishermanConfigurations { .expect("Fisherman database URL is required"), batch_interval_seconds: self.fisherman_batch_interval_seconds, batch_deletion_limit: self.fisherman_batch_deletion_limit, + batch_cooldown_seconds: self.fisherman_batch_cooldown_seconds, + consecutive_no_work_batches_threshold: self + .fisherman_consecutive_no_work_batches_threshold, maintenance_mode: false, // Skipping maintenance mode for now filtering, ordering, diff --git a/operator/runtime/mainnet/src/configs/runtime_params.rs b/operator/runtime/mainnet/src/configs/runtime_params.rs index d034192a..605c9f73 100644 --- a/operator/runtime/mainnet/src/configs/runtime_params.rs +++ b/operator/runtime/mainnet/src/configs/runtime_params.rs @@ -128,9 +128,9 @@ pub mod dynamic_params { /// /// [`MaxPrice`] = [`MostlyStablePrice`] + u * e ^ ( 1 - [`SystemUtilisationUpperThresholdPercentage`] ) /// - /// 500 = 50 + u * (e ^ (1 - 0.95) - 1) - /// u = (500 - 50) / (e ^ (1 - 0.95) - 1) ≈ 8777 - pub static UpperExponentFactor: u32 = 8777; + /// 500 GIGAWEI = 50 GIGAWEI + u * (e ^ (1 - 0.95) - 1) + /// u = (500 GIGAWEI - 50 GIGAWEI) / (e ^ (1 - 0.95) - 1) ≈ 8,776,874,921,880 + pub static UpperExponentFactor: Balance = 8_776_874_921_880; #[codec(index = 15)] #[allow(non_upper_case_globals)] @@ -139,9 +139,9 @@ pub mod dynamic_params { /// /// [`MinPrice`] = [`MostlyStablePrice`] - u * e ^ ( [`SystemUtilisationLowerThresholdPercentage`] - 0 ) /// - /// 10 = 50 - l * (e ^ (0.3 - 0) - 1) - /// l = (50 - 10) / (e ^ (0.3 - 0) - 1) ≈ 114 - pub static LowerExponentFactor: u32 = 114; + /// 10 GIGAWEI = 50 GIGAWEI - l * (e ^ (0.3 - 0) - 1) + /// l = (50 GIGAWEI - 10 GIGAWEI) / (e ^ (0.3 - 0) - 1) ≈ 114,331,836,540 + pub static LowerExponentFactor: Balance = 114_331_836_540; #[codec(index = 16)] #[allow(non_upper_case_globals)] diff --git a/operator/runtime/mainnet/src/lib.rs b/operator/runtime/mainnet/src/lib.rs index ade0d13a..ceb8f373 100644 --- a/operator/runtime/mainnet/src/lib.rs +++ b/operator/runtime/mainnet/src/lib.rs @@ -1264,6 +1264,9 @@ impl_runtime_apis! { ) -> Vec { FileSystem::query_pending_bsp_confirm_storage_requests(bsp_id, file_keys) } + fn get_max_batch_confirm_storage_requests() -> BlockNumber { + FileSystem::get_max_batch_confirm_storage_requests() + } } impl pallet_payment_streams_runtime_api::PaymentStreamsApi, Balance, AccountId> for Runtime { diff --git a/operator/runtime/stagenet/src/configs/runtime_params.rs b/operator/runtime/stagenet/src/configs/runtime_params.rs index 8b9a35ca..f05caff5 100644 --- a/operator/runtime/stagenet/src/configs/runtime_params.rs +++ b/operator/runtime/stagenet/src/configs/runtime_params.rs @@ -135,9 +135,9 @@ pub mod dynamic_params { /// /// [`MaxPrice`] = [`MostlyStablePrice`] + u * e ^ ( 1 - [`SystemUtilisationUpperThresholdPercentage`] ) /// - /// 500 = 50 + u * (e ^ (1 - 0.95) - 1) - /// u = (500 - 50) / (e ^ (1 - 0.95) - 1) ≈ 8777 - pub static UpperExponentFactor: u32 = 8777; + /// 500 GIGAWEI = 50 GIGAWEI + u * (e ^ (1 - 0.95) - 1) + /// u = (500 GIGAWEI - 50 GIGAWEI) / (e ^ (1 - 0.95) - 1) ≈ 8,776,874,921,880 + pub static UpperExponentFactor: Balance = 8_776_874_921_880; #[codec(index = 15)] #[allow(non_upper_case_globals)] @@ -146,9 +146,9 @@ pub mod dynamic_params { /// /// [`MinPrice`] = [`MostlyStablePrice`] - u * e ^ ( [`SystemUtilisationLowerThresholdPercentage`] - 0 ) /// - /// 10 = 50 - l * (e ^ (0.3 - 0) - 1) - /// l = (50 - 10) / (e ^ (0.3 - 0) - 1) ≈ 114 - pub static LowerExponentFactor: u32 = 114; + /// 10 GIGAWEI = 50 GIGAWEI - l * (e ^ (0.3 - 0) - 1) + /// l = (50 GIGAWEI - 10 GIGAWEI) / (e ^ (0.3 - 0) - 1) ≈ 114,331,836,540 + pub static LowerExponentFactor: Balance = 114_331_836_540; #[codec(index = 16)] #[allow(non_upper_case_globals)] diff --git a/operator/runtime/stagenet/src/lib.rs b/operator/runtime/stagenet/src/lib.rs index d4bae772..2bc4d60b 100644 --- a/operator/runtime/stagenet/src/lib.rs +++ b/operator/runtime/stagenet/src/lib.rs @@ -1267,6 +1267,9 @@ impl_runtime_apis! { ) -> Vec { FileSystem::query_pending_bsp_confirm_storage_requests(bsp_id, file_keys) } + fn get_max_batch_confirm_storage_requests() -> BlockNumber { + FileSystem::get_max_batch_confirm_storage_requests() + } } impl pallet_payment_streams_runtime_api::PaymentStreamsApi, Balance, AccountId> for Runtime { diff --git a/operator/runtime/testnet/src/configs/runtime_params.rs b/operator/runtime/testnet/src/configs/runtime_params.rs index c9a77d8c..bc218f6c 100644 --- a/operator/runtime/testnet/src/configs/runtime_params.rs +++ b/operator/runtime/testnet/src/configs/runtime_params.rs @@ -133,9 +133,9 @@ pub mod dynamic_params { /// /// [`MaxPrice`] = [`MostlyStablePrice`] + u * e ^ ( 1 - [`SystemUtilisationUpperThresholdPercentage`] ) /// - /// 500 = 50 + u * (e ^ (1 - 0.95) - 1) - /// u = (500 - 50) / (e ^ (1 - 0.95) - 1) ≈ 8777 - pub static UpperExponentFactor: u32 = 8777; + /// 500 GIGAWEI = 50 GIGAWEI + u * (e ^ (1 - 0.95) - 1) + /// u = (500 GIGAWEI - 50 GIGAWEI) / (e ^ (1 - 0.95) - 1) ≈ 8,776,874,921,880 + pub static UpperExponentFactor: Balance = 8_776_874_921_880; #[codec(index = 15)] #[allow(non_upper_case_globals)] @@ -144,9 +144,9 @@ pub mod dynamic_params { /// /// [`MinPrice`] = [`MostlyStablePrice`] - u * e ^ ( [`SystemUtilisationLowerThresholdPercentage`] - 0 ) /// - /// 10 = 50 - l * (e ^ (0.3 - 0) - 1) - /// l = (50 - 10) / (e ^ (0.3 - 0) - 1) ≈ 114 - pub static LowerExponentFactor: u32 = 114; + /// 10 GIGAWEI = 50 GIGAWEI - l * (e ^ (0.3 - 0) - 1) + /// l = (50 GIGAWEI - 10 GIGAWEI) / (e ^ (0.3 - 0) - 1) ≈ 114,331,836,540 + pub static LowerExponentFactor: Balance = 114_331_836_540; #[codec(index = 16)] #[allow(non_upper_case_globals)] diff --git a/operator/runtime/testnet/src/lib.rs b/operator/runtime/testnet/src/lib.rs index 0f53637a..88ef82eb 100644 --- a/operator/runtime/testnet/src/lib.rs +++ b/operator/runtime/testnet/src/lib.rs @@ -1264,6 +1264,9 @@ impl_runtime_apis! { ) -> Vec { FileSystem::query_pending_bsp_confirm_storage_requests(bsp_id, file_keys) } + fn get_max_batch_confirm_storage_requests() -> BlockNumber { + FileSystem::get_max_batch_confirm_storage_requests() + } } impl pallet_payment_streams_runtime_api::PaymentStreamsApi, Balance, AccountId> for Runtime { diff --git a/test/.papi/descriptors/package.json b/test/.papi/descriptors/package.json index 8ece9265..b7060c4b 100644 --- a/test/.papi/descriptors/package.json +++ b/test/.papi/descriptors/package.json @@ -1,5 +1,5 @@ { - "version": "0.1.0-autogenerated.14314240478086326730", + "version": "0.1.0-autogenerated.17981369281038341211", "name": "@polkadot-api/descriptors", "files": [ "dist" diff --git a/test/.papi/metadata/datahaven.scale b/test/.papi/metadata/datahaven.scale index edb59297e58d5a5d04e05e7e0d9e2392caf81074..7f390905fafa57c798c2baadf955d19e40869bd2 100644 GIT binary patch delta 3989 zcmeH~&1(}u6u`ULwQ02A2c>9j;e|qJ4p#jGdPsFIqD31O8j*B%_cdL*nN4SAo5V|O zKm%e0NntBeFe-R0TDrZI>P3)V>_zbAy_ep4bxcC((ZhN%IXsxJH*emL$9r!MK8&n= z8ChR3PM%i=Cx}C+iM6x(h2zttKJ@8_kv#O@O)Gu1b9%o&o>ne4XA}BBwUSn(M1o3M zeL7ekd_D~NB2oc5HC@Z5*~{0lIe?TPhV9s*)KyZFjsw^@w@8>xsNmpn1T5wq+q4DD z3_p-sXpY*{!Xk{rWa8lr2p5oYk0Ee*mxGYHmb|IUwU#NX+_E)8Oy+V9%%j52A$a*L zBNpkqhdu31_fF`s8+@;;Pa^HkH5EG7S5g1v zM=f64hgk6Ty}EL`gE;KOuom@~wzZ)K;^hr>L+Kz68*x4AC%ax80-l zA9P~nZEdSn!`e4o!~dOq^A|pAeO0=nNjV{EVwGC5}*aR4PN{x*s3%W`|nVSzL#eL^{$jqqYUr>^npJxM4j4n4YrHTX8z7Go%J5GB2y{* z^o^@nT(&P-%52XxUEn%Uy}?T61N{0V+O^$&7xNuPkS*J@_A;M49nRv(2zG2yQGOAs zV@ooM^2>qFMsce`Nxnj6URr)pu0m;XDo{saQhsTPLOIBj zwS93H%T3wo%?d0^+fT1#>E(wom+xY^&qEuFk8)3U+{G-r{mTiKnT*o~*;teqPfm9{ t&muCtPnns!{m*F@AZ7((HXvr-{^vAD*=a_d?ZwkMQ<%0h&f=WI1^`(^!o>gp