Merge branch 'main' into fix/operator-dockerfile

This commit is contained in:
undercover-cactus 2026-02-10 16:07:28 +01:00 committed by GitHub
commit 22f0924033
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
42 changed files with 1283 additions and 412 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -27,8 +27,6 @@
"avs": {
"avsOwner": "0x976EA74026E726554dB657fA54763abd0C3a0aa9",
"rewardsInitiator": "0x14dC79964da2C08b23698B3D3cc7Ca32193d9955",
"vetoCommitteeMember": "0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f",
"vetoWindowBlocks": 100,
"validatorsStrategies": [
"0xbeaC0eeEeeeeEEeEeEEEEeeEEeEeeeEeeEEBEaC0"
]

View file

@ -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:

View file

@ -31,8 +31,6 @@
"avs": {
"avsOwner": "0x0000000000000000000000000000000000000000",
"rewardsInitiator": "0x0000000000000000000000000000000000000000",
"vetoCommitteeMember": "0x0000000000000000000000000000000000000000",
"vetoWindowBlocks": 7200,
"validatorsStrategies": [
"0xbeaC0eeEeeeeEEeEeEEEEeeEEeEeeeEeeEEBEaC0",
"0x93c4b944D05dfe6df7645A86cd2206016c51564D",

View file

@ -33,8 +33,6 @@
"avs": {
"avsOwner": "0xe30a38ac89ffE5A86D5389Bfbf70C7EC766FbB6e",
"rewardsInitiator": "0xe30a38ac89ffE5A86D5389Bfbf70C7EC766FbB6e",
"vetoCommitteeMember": "0xe30a38ac89ffE5A86D5389Bfbf70C7EC766FbB6e",
"vetoWindowBlocks": 100,
"validatorsStrategies": [
"0xbeaC0eeEeeeeEEeEeEEEEeeEEeEeeeEeeEEBEaC0",
"0xf8a1a66130d614c7360e868576d5e59203475fe0",

View file

@ -33,8 +33,6 @@
"avs": {
"avsOwner": "0x0000000000000000000000000000000000000000",
"rewardsInitiator": "0x0000000000000000000000000000000000000000",
"vetoCommitteeMember": "0x0000000000000000000000000000000000000000",
"vetoWindowBlocks": 100,
"validatorsStrategies": [
"0xbeaC0eeEeeeeEEeEeEEEEeeEEeEeeeEeeEEBEaC0",
"0xf8a1a66130d614c7360e868576d5e59203475fe0",

View file

@ -19,8 +19,6 @@ contract Config {
struct AVSConfig {
address avsOwner;
address rewardsInitiator;
address vetoCommitteeMember;
uint32 vetoWindowBlocks;
address[] validatorsStrategies;
}

View file

@ -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");

View file

@ -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();
}
}

View file

@ -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."

View file

@ -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"

View file

@ -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"
}
}
}

View file

@ -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.

View file

@ -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"
);
}
}

View file

@ -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;

268
operator/Cargo.lock generated
View file

@ -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",
@ -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",
@ -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",
@ -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",
@ -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",
@ -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",
@ -9417,7 +9417,7 @@ dependencies = [
[[package]]
name = "pallet-outbound-commitment-store"
version = "0.22.0"
version = "0.23.0"
dependencies = [
"frame-support",
"frame-system",
@ -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",
@ -9541,7 +9541,7 @@ dependencies = [
[[package]]
name = "pallet-proxy-genesis-companion"
version = "0.22.0"
version = "0.23.0"
dependencies = [
"frame-support",
"frame-system",
@ -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",
@ -9652,7 +9652,7 @@ dependencies = [
[[package]]
name = "pallet-session-benchmarking"
version = "0.22.0"
version = "0.23.0"
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",
@ -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",
]

View file

@ -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 = [
@ -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

View file

@ -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 }

View file

@ -741,9 +741,23 @@ pub struct FishermanConfigurations {
pub fisherman_database_url: Option<String>,
/// 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,

View file

@ -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<P, BE, AuthorityId, A, FL, FSH, Runtime>(
deps: FullDeps<P, BE, AuthorityId, A, FL, FSH, Runtime>,
subscription_task_executor: sc_rpc::SubscriptionTaskExecutor,
pubsub_notification_sinks: Arc<
fc_mapping_sync::EthereumBlockNotificationSinks<
fc_mapping_sync::EthereumBlockNotification<Block>,
>,
>,
) -> Result<RpcModule<()>, Box<dyn std::error::Error + Send + Sync>>
where
P: TransactionPool<Block = Block> + '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)
}

View file

@ -439,7 +439,7 @@ pub async fn new_full_impl<
RuntimeApi,
N: sc_network::NetworkBackend<Block, <Block as sp_runtime::traits::Block>::Hash>,
>(
config: Configuration,
mut config: Configuration,
mut eth_config: EthConfiguration,
role_options: Option<RoleOptions>,
indexer_options: Option<IndexerOptions>,
@ -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::<BeefyId> {
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::<BeefyId> {
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(),

View file

@ -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)]

View file

@ -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,
@ -1264,6 +1264,9 @@ impl_runtime_apis! {
) -> Vec<H256> {
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<Block, ProviderIdFor<Runtime>, Balance, AccountId> for Runtime {

View file

@ -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)]

View file

@ -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,
@ -1267,6 +1267,9 @@ impl_runtime_apis! {
) -> Vec<H256> {
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<Block, ProviderIdFor<Runtime>, Balance, AccountId> for Runtime {

View file

@ -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)]

View file

@ -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,
@ -1264,6 +1264,9 @@ impl_runtime_apis! {
) -> Vec<H256> {
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<Block, ProviderIdFor<Runtime>, Balance, AccountId> for Runtime {

View file

@ -1,5 +1,5 @@
{
"version": "0.1.0-autogenerated.14314240478086326730",
"version": "0.1.0-autogenerated.17981369281038341211",
"name": "@polkadot-api/descriptors",
"files": [
"dist"

Binary file not shown.

View file

@ -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) {

View file

@ -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");
}

View file

@ -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<void> => {
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 --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<string> => {
// 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<void> => {
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.
*

View file

@ -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,
});
},
});
},
});

View file

@ -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<Log>;
let subMultiAddPromise: Promise<Log>;
let subTopicPromise: Promise<Log>;
let subTopicWildcardPromise: Promise<Log>;
let subTopicListPromise: Promise<Log>;
let subTopicCondPromise: Promise<Log>;
let subTopicMultiCondPromise: Promise<Log>;
let subTopicWildAndCondPromise: Promise<Log>;
beforeAll(async () => {
const openSub = async (filter?: object) => await context.web3().eth.subscribe("logs", filter);
const onData = (logSub: any) => {
return new Promise<Log>((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);
},
});
},
});

View file

@ -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);
},
});
},
});

View file

@ -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);
},
});
},
});

View file

@ -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

View file

@ -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<void
try {
// Check MSP account balance
logger.info(`Checking MSP account (${PROVIDER_ACCOUNTS.msp.name})...`);
const mspAccount = await typedApi.query.System.Account.getValue(PROVIDER_ACCOUNTS.msp.address);
logger.info("Checking MSP account...");
const mspAccount = await typedApi.query.System.Account.getValue(
SUBSTRATE_FUNDED_ACCOUNTS.CHARLETH.publicKey
);
const mspBalance = mspAccount?.data?.free ?? BigInt(0);
logger.debug(`MSP balance: ${mspBalance.toString()}`);
if (mspBalance < MIN_PROVIDER_BALANCE) {
logger.warn(`MSP account has insufficient balance (${mspBalance} < ${MIN_PROVIDER_BALANCE})`);
logger.info(
"Note: In dev chains, //Charlie should be pre-funded. If balance is low, ensure the chain is properly initialized."
"Note: In dev chains, Charleth account should be pre-funded. If balance is low, ensure the chain is properly initialized."
);
} else {
logger.success(`MSP account has sufficient balance: ${mspBalance.toString()}`);
}
// Check BSP account balance
logger.info(`Checking BSP account (${PROVIDER_ACCOUNTS.bsp.name})...`);
const bspAccount = await typedApi.query.System.Account.getValue(PROVIDER_ACCOUNTS.bsp.address);
logger.info("Checking BSP account...");
const bspAccount = await typedApi.query.System.Account.getValue(
SUBSTRATE_FUNDED_ACCOUNTS.DOROTHY.publicKey
);
const bspBalance = bspAccount?.data?.free ?? BigInt(0);
logger.debug(`BSP balance: ${bspBalance.toString()}`);
if (bspBalance < MIN_PROVIDER_BALANCE) {
logger.warn(`BSP account has insufficient balance (${bspBalance} < ${MIN_PROVIDER_BALANCE})`);
logger.info(
"Note: In dev chains, //Eve should be pre-funded. If balance is low, ensure the chain is properly initialized."
"Note: In dev chains, DOROTHY account should be pre-funded. If balance is low, ensure the chain is properly initialized."
);
} else {
logger.success(`BSP account has sufficient balance: ${bspBalance.toString()}`);
@ -98,12 +76,3 @@ export async function fundProviders(options: FundProvidersOptions): Promise<void
client.destroy();
}
}
/**
* Gets the provider account addresses.
*
* @returns Object containing MSP and BSP account information
*/
export function getProviderAccounts() {
return PROVIDER_ACCOUNTS;
}