mirror of
https://github.com/datahaven-xyz/datahaven
synced 2026-05-24 09:50:01 +00:00
## Summary This PR adds comprehensive Kubernetes deployment infrastructure for StorageHub components, enabling deployment of the full StorageHub network stack (MSP, BSP, Indexer, and Fisherman nodes) alongside DataHaven nodes in both local and stagenet environments. ### What's Added **1. New Helm Chart: StorageHub MSP Backend API** (`deploy/charts/backend/`) - REST API service for StorageHub operations - Connects to PostgreSQL database for indexed blockchain data - Connects to RPC nodes for real-time blockchain queries - Configurable via TOML configuration file - Supports environment-specific overrides - Includes comprehensive documentation **2. StorageHub Node Deployment Charts** (`deploy/charts/node/storagehub/`) - **MSP Node** (`sh-mspnode`): Main Service Provider nodes with charging capabilities - **BSP Node** (`sh-bspnode`): Backup Service Provider nodes for redundancy - **Indexer Node** (`sh-idxnode`): Full indexing node with PostgreSQL integration - **Fisherman Node** (`sh-fisherman`): Network monitoring and verification node **3. Environment Configurations** - **Local environment** (`deploy/environments/local/`): Development setup with hostpath storage - **Stagenet environment** (`deploy/environments/stagenet/`): Production-like setup with AWS EBS - PostgreSQL database configurations for Indexer and Fisherman nodes - Proper service discovery and network configuration **4. Enhanced CLI Tooling** (`test/cli/`) - New `deploy storagehub` command for deploying StorageHub components - Updated `launch storagehub` command for local testing - Interactive deployment with environment selection - Automatic database provisioning via Bitnami PostgreSQL charts **5. Node Configuration Improvements** - Fork-aware transaction pool for DH boot & validator nodes - Unsafe RPC methods exposed on MSP nodes (for provider operations) - JWT secret support for MSP Backend authentication - ECDSA key scheme for StorageHub BCSV keys (DataHaven compatibility) ### Architecture ``` StorageHub Stack: ├── MSP Nodes (2 replicas) → Storage providers with charging ├── BSP Nodes (2 replicas) → Backup storage providers ├── Indexer Node → Database indexing + PostgreSQL ├── Fisherman Node → Monitoring + PostgreSQL (shared with Indexer) └── MSP Backend API → REST API for StorageHub operations ``` ### Testing **Local Testing**: ```bash cd test bun cli launch storagehub # Interactive launcher # or bun cli deploy storagehub # Deploy via Helm ``` **Stagenet Deployment**: ```bash cd deploy helm install sh-mspnode ./charts/node \ -f ./charts/node/storagehub/sh-mspnode.yaml \ -f ./environments/stagenet/sh-mspnode.yaml \ -n datahaven-stagenet ``` ### Breaking Changes None - This is purely additive infrastructure. ### Migration Notes For existing deployments: 1. DataHaven nodes now use `--pool-type fork-aware` flag 2. Bootnode and validator node configs updated accordingly 3. No action required for existing DataHaven-only deployments
121 lines
4.3 KiB
TypeScript
121 lines
4.3 KiB
TypeScript
import type { Command } from "node_modules/@commander-js/extra-typings";
|
|
import { type DeployEnvironment, logger } from "utils";
|
|
import { createParameterCollection } from "utils/parameters";
|
|
import { LaunchedNetwork } from "../../../launcher/types/launchedNetwork";
|
|
import { checkBaseDependencies, deploymentChecks } from "../common/checks";
|
|
import { cleanup } from "./cleanup";
|
|
import { deployContracts } from "./contracts";
|
|
import { deployDataHavenSolochain } from "./datahaven";
|
|
import { deployKurtosis } from "./kurtosis";
|
|
import { setParametersFromCollection } from "./parameters";
|
|
import { deployRelayers } from "./relayer";
|
|
import { deployStorageHubComponents } from "./storagehub";
|
|
import { performValidatorOperations } from "./validator";
|
|
|
|
// Non-optional properties determined by having default values
|
|
export interface DeployOptions {
|
|
environment: DeployEnvironment;
|
|
isPrivateNetwork?: boolean;
|
|
kubeNamespace?: string;
|
|
kurtosisEnclaveName: string;
|
|
slotTime: number;
|
|
kurtosisNetworkArgs?: string;
|
|
verified?: boolean;
|
|
blockscout?: boolean;
|
|
datahavenImageTag: string;
|
|
elRpcUrl?: string;
|
|
clEndpoint?: string;
|
|
relayerImageTag: string;
|
|
// TODO: This shouldn't be necessary once the repo is public
|
|
dockerUsername?: string;
|
|
// TODO: This shouldn't be necessary once the repo is public
|
|
dockerPassword?: string;
|
|
// TODO: This shouldn't be necessary once the repo is public
|
|
dockerEmail?: string;
|
|
chainspec?: string;
|
|
skipCleanup: boolean;
|
|
skipKurtosis: boolean;
|
|
skipDatahavenSolochain: boolean;
|
|
skipContracts: boolean;
|
|
skipValidatorOperations: boolean;
|
|
skipSetParameters: boolean;
|
|
skipRelayers: boolean;
|
|
skipStorageHub: boolean;
|
|
}
|
|
|
|
const deployFunction = async (options: DeployOptions, launchedNetwork: LaunchedNetwork) => {
|
|
logger.debug("Running with options:");
|
|
logger.debug(options);
|
|
|
|
const timeStart = performance.now();
|
|
|
|
await checkBaseDependencies();
|
|
await deploymentChecks(options, launchedNetwork);
|
|
|
|
await cleanup(options, launchedNetwork);
|
|
|
|
// Create parameter collection to be used throughout the launch process
|
|
const parameterCollection = await createParameterCollection();
|
|
|
|
await deployKurtosis(options, launchedNetwork);
|
|
|
|
// Inside the deployDataHavenSolochain function, it will forward the port from the validator to the local machine.
|
|
// This is to allow the rest of the script to interact with the network.
|
|
// The cleanup function is returned to allow the script to clean up the port forwarding.
|
|
const validatorPortForwardCleanup = await deployDataHavenSolochain(options, launchedNetwork);
|
|
|
|
// TODO: Handle Blockscout and verifier parameters to verify contracts if that is the intention.
|
|
const blockscoutBackendUrl = undefined;
|
|
|
|
await deployContracts({
|
|
rpcUrl: launchedNetwork.elRpcUrl,
|
|
verified: options.verified,
|
|
blockscoutBackendUrl,
|
|
parameterCollection,
|
|
skipContracts: options.skipContracts
|
|
});
|
|
|
|
await performValidatorOperations(options, launchedNetwork.elRpcUrl);
|
|
|
|
await setParametersFromCollection({
|
|
collection: parameterCollection,
|
|
skipSetParameters: options.skipSetParameters
|
|
});
|
|
|
|
await deployRelayers(options, launchedNetwork);
|
|
|
|
await deployStorageHubComponents(options, launchedNetwork);
|
|
|
|
// Cleaning up the port forwarding for the validator.
|
|
await validatorPortForwardCleanup();
|
|
|
|
const fullEnd = performance.now();
|
|
const fullMinutes = ((fullEnd - timeStart) / (1000 * 60)).toFixed(1);
|
|
logger.success(`Deploy function completed successfully in ${fullMinutes} minutes`);
|
|
};
|
|
|
|
export const deploy = async (options: DeployOptions) => {
|
|
const run = new LaunchedNetwork();
|
|
await deployFunction(options, run);
|
|
};
|
|
|
|
export const deployPreActionHook = (
|
|
thisCmd: Command<[], DeployOptions & { [key: string]: any }>
|
|
) => {
|
|
const opts = thisCmd.opts();
|
|
if (opts.verified && !opts.blockscout) {
|
|
thisCmd.error("--verified requires --blockscout to be set");
|
|
}
|
|
|
|
opts.isPrivateNetwork = opts.environment === "local" || opts.environment === "stagenet";
|
|
|
|
if (opts.isPrivateNetwork && opts.kubeNamespace !== undefined) {
|
|
logger.warn(
|
|
"⚠️ --kube-namespace is not allowed in private networks (local and stagenet). The Kurtosis namespace will be used instead."
|
|
);
|
|
}
|
|
|
|
if (!opts.isPrivateNetwork && opts.elRpcUrl === undefined) {
|
|
thisCmd.error("--eth-rpc-url is required in public networks (testnet and mainnet)");
|
|
}
|
|
};
|