mirror of
https://github.com/datahaven-xyz/datahaven
synced 2026-05-24 09:50:01 +00:00
fix: 🔌 CLI connection issues (#119)
### Problem Introducing `--network` should make easy to container nodes to find each other. But this change was made half-way for the relayers, and it was using the external port to find the first datahaven node (usually Alice). So: - In cli launch, Alice node port mapping was left to random port `-p 9944` instead of `-p 9944:9944`. - Relayers couldn't connect to DataHaven nodes because they were using the external WS port (now random) instead of hitting the internal port (which for a cli launch we actually fix it to 9944). ### Solution - [x] **Fixed Docker port mapping**: Explicit `-p 9944:9944` for Alice node under network `cli-launch` - [x] **Enhanced container spec**: Added `internalPorts` tracking to `LaunchedNetwork` - [x] **Fixed relayer connections**: Use internal ports for container communication
This commit is contained in:
parent
9b311e00ef
commit
10362d3361
7 changed files with 74 additions and 21 deletions
|
|
@ -2,14 +2,13 @@ import path from "node:path";
|
|||
import { $ } from "bun";
|
||||
import invariant from "tiny-invariant";
|
||||
import { logger, printDivider, printHeader } from "utils";
|
||||
import { DEFAULT_SUBSTRATE_WS_PORT } from "utils/constants";
|
||||
import { waitFor } from "utils/waits";
|
||||
import { isNetworkReady, setupDataHavenValidatorConfig } from "../../../launcher/datahaven";
|
||||
import type { LaunchedNetwork } from "../../../launcher/types/launchedNetwork";
|
||||
import { forwardPort } from "../common/kubernetes";
|
||||
import type { DeployOptions } from ".";
|
||||
|
||||
const DEFAULT_PUBLIC_WS_PORT = 9944;
|
||||
|
||||
/**
|
||||
* Deploys a DataHaven solochain network in a Kubernetes namespace.
|
||||
*
|
||||
|
|
@ -27,8 +26,8 @@ export const deployDataHavenSolochain = async (
|
|||
// Forward port from validator to localhost, to interact with the network.
|
||||
const { cleanup: validatorPortForwardCleanup } = await forwardPort(
|
||||
"dh-validator-0",
|
||||
DEFAULT_PUBLIC_WS_PORT,
|
||||
DEFAULT_PUBLIC_WS_PORT,
|
||||
DEFAULT_SUBSTRATE_WS_PORT,
|
||||
DEFAULT_SUBSTRATE_WS_PORT,
|
||||
launchedNetwork
|
||||
);
|
||||
|
||||
|
|
@ -92,8 +91,8 @@ export const deployDataHavenSolochain = async (
|
|||
// Forward port from validator to localhost, to interact with the network.
|
||||
const { cleanup: validatorPortForwardCleanup } = await forwardPort(
|
||||
"dh-validator-0",
|
||||
DEFAULT_PUBLIC_WS_PORT,
|
||||
DEFAULT_PUBLIC_WS_PORT,
|
||||
DEFAULT_SUBSTRATE_WS_PORT,
|
||||
DEFAULT_SUBSTRATE_WS_PORT,
|
||||
launchedNetwork
|
||||
);
|
||||
|
||||
|
|
@ -104,7 +103,7 @@ export const deployDataHavenSolochain = async (
|
|||
await waitFor({
|
||||
lambda: async () => {
|
||||
logger.info(`📡 Checking if DataHaven is ready (timeout: ${timeoutMs / 1000}s)...`);
|
||||
const isReady = await isNetworkReady(DEFAULT_PUBLIC_WS_PORT, timeoutMs);
|
||||
const isReady = await isNetworkReady(DEFAULT_SUBSTRATE_WS_PORT, timeoutMs);
|
||||
if (!isReady) {
|
||||
logger.info(`⌛️ Node not ready, waiting ${delayMs / 1000}s to check again...`);
|
||||
}
|
||||
|
|
@ -116,7 +115,7 @@ export const deployDataHavenSolochain = async (
|
|||
});
|
||||
|
||||
logger.success(
|
||||
`DataHaven network started, primary node accessible on port ${DEFAULT_PUBLIC_WS_PORT}`
|
||||
`DataHaven network started, primary node accessible on port ${DEFAULT_SUBSTRATE_WS_PORT}`
|
||||
);
|
||||
|
||||
await registerNodes(launchedNetwork);
|
||||
|
|
@ -174,7 +173,7 @@ const checkOrCreateKubernetesNamespace = async (namespace: string) => {
|
|||
const registerNodes = async (launchedNetwork: LaunchedNetwork) => {
|
||||
// Register the validator node, using the standard host WS port that we just forwarded.
|
||||
launchedNetwork.addContainer("dh-validator-0", {
|
||||
ws: DEFAULT_PUBLIC_WS_PORT
|
||||
ws: DEFAULT_SUBSTRATE_WS_PORT
|
||||
});
|
||||
logger.info("📝 Node dh-validator-0 successfully registered in launchedNetwork.");
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
import { setDataHavenParameters } from "scripts/set-datahaven-parameters";
|
||||
import { logger, printDivider, printHeader } from "utils";
|
||||
import { DEFAULT_SUBSTRATE_WS_PORT } from "utils/constants";
|
||||
import type { ParameterCollection } from "utils/parameters";
|
||||
|
||||
// Standard ports for the substrate network
|
||||
const DEFAULT_SUBSTRATE_WS_PORT = 9944;
|
||||
|
||||
/**
|
||||
* A helper function to set DataHaven parameters from a ParameterCollection
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import type { Command } from "@commander-js/extra-typings";
|
||||
import { logger } from "utils";
|
||||
import { DEFAULT_SUBSTRATE_WS_PORT } from "utils/constants";
|
||||
import { createParameterCollection } from "utils/parameters";
|
||||
import { getBlockscoutUrl } from "../../../launcher/kurtosis";
|
||||
import { LaunchedNetwork } from "../../../launcher/types/launchedNetwork";
|
||||
|
|
@ -14,6 +15,16 @@ import { performValidatorOperations, performValidatorSetUpdate } from "./validat
|
|||
|
||||
export const NETWORK_ID = "cli-launch";
|
||||
|
||||
export interface NetworkOptions {
|
||||
networkId: string;
|
||||
dhInternalPort?: number;
|
||||
}
|
||||
|
||||
export const CLI_NETWORK_OPTIONS: NetworkOptions = {
|
||||
networkId: NETWORK_ID,
|
||||
dhInternalPort: DEFAULT_SUBSTRATE_WS_PORT
|
||||
};
|
||||
|
||||
// Non-optional properties should have default values set by the CLI
|
||||
export interface LaunchOptions {
|
||||
all?: boolean;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import {
|
|||
logger,
|
||||
waitForContainerToStart
|
||||
} from "utils";
|
||||
import { DEFAULT_SUBSTRATE_WS_PORT } from "utils/constants";
|
||||
import { waitFor } from "utils/waits";
|
||||
import { type Hex, keccak256, toHex } from "viem";
|
||||
import { publicKeyToAddress } from "viem/accounts";
|
||||
|
|
@ -29,6 +30,30 @@ export interface DataHavenOptions {
|
|||
datahavenBuildExtraArgs?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the port mapping for a DataHaven node based on the network type.
|
||||
*
|
||||
* For CLI-launch networks (networkId === "cli-launch"), only the alice node gets
|
||||
* a fixed port mapping (9944:9944). For other networks, only the internal port is exposed
|
||||
* and Docker assigns a random external port.
|
||||
*
|
||||
* @param nodeId - The node identifier (e.g., "alice", "bob")
|
||||
* @param networkId - The network identifier
|
||||
* @returns Array of port mapping arguments for Docker run command
|
||||
*/
|
||||
export const getPortMappingForNode = (nodeId: string, networkId: string): string[] => {
|
||||
const isCliLaunch = networkId === "cli-launch";
|
||||
|
||||
if (isCliLaunch && nodeId === "alice") {
|
||||
// For CLI-launch networks, only alice gets the fixed port mapping
|
||||
return ["-p", `${DEFAULT_SUBSTRATE_WS_PORT}:${DEFAULT_SUBSTRATE_WS_PORT}`];
|
||||
}
|
||||
|
||||
// For other networks or non-alice nodes, only expose internal port
|
||||
// Docker will assign a random external port
|
||||
return ["-p", `${DEFAULT_SUBSTRATE_WS_PORT}`];
|
||||
};
|
||||
|
||||
/**
|
||||
* Launches a local DataHaven solochain network for testing.
|
||||
*
|
||||
|
|
@ -103,7 +128,7 @@ export const launchLocalDataHavenSolochain = async (
|
|||
containerName,
|
||||
"--network",
|
||||
dockerNetworkName,
|
||||
...(id === "alice" ? ["-p", "9944"] : []),
|
||||
...getPortMappingForNode(id, options.networkId),
|
||||
options.datahavenImageTag,
|
||||
`--${id}`,
|
||||
...COMMON_LAUNCH_ARGS
|
||||
|
|
@ -485,11 +510,15 @@ export const registerNodes = async (networkId: string, launchedNetwork: Launched
|
|||
}
|
||||
|
||||
// Query the dynamic port and register
|
||||
const dynamicPort = await getPublicPort(targetContainerName, 9944);
|
||||
const dynamicPort = await getPublicPort(targetContainerName, DEFAULT_SUBSTRATE_WS_PORT);
|
||||
logger.debug(
|
||||
`Docker container ${targetContainerName} is running. Registering with dynamic port ${dynamicPort}.`
|
||||
);
|
||||
launchedNetwork.addContainer(targetContainerName, { ws: dynamicPort });
|
||||
launchedNetwork.addContainer(
|
||||
targetContainerName,
|
||||
{ ws: dynamicPort },
|
||||
{ ws: DEFAULT_SUBSTRATE_WS_PORT }
|
||||
);
|
||||
logger.info(
|
||||
`📝 Node ${targetContainerName} successfully registered in ${networkId} as datahaven-alice`
|
||||
);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { getWsProvider } from "polkadot-api/ws-provider/web";
|
|||
import invariant from "tiny-invariant";
|
||||
import {
|
||||
ANVIL_FUNDED_ACCOUNTS,
|
||||
DEFAULT_SUBSTRATE_WS_PORT,
|
||||
getEvmEcdsaSigner,
|
||||
getPortFromKurtosis,
|
||||
killExistingContainers,
|
||||
|
|
@ -409,17 +410,20 @@ export const launchRelayers = async (
|
|||
container.name.includes("datahaven")
|
||||
);
|
||||
let substrateWsPort: number;
|
||||
let substrateWsInternalPort: number;
|
||||
let substrateNodeId: string;
|
||||
|
||||
if (dhNodes.length === 0) {
|
||||
logger.warn(
|
||||
"⚠️ No DataHaven nodes found in launchedNetwork. Assuming DataHaven is running and defaulting to port 9944 for relayers."
|
||||
`⚠️ No DataHaven nodes found in launchedNetwork. Assuming DataHaven is running and defaulting to ${DEFAULT_SUBSTRATE_WS_PORT} for relayers.`
|
||||
);
|
||||
substrateWsPort = 9944;
|
||||
substrateWsPort = DEFAULT_SUBSTRATE_WS_PORT;
|
||||
substrateWsInternalPort = DEFAULT_SUBSTRATE_WS_PORT;
|
||||
substrateNodeId = "default (assumed)";
|
||||
} else {
|
||||
const firstDhNode = dhNodes[0];
|
||||
substrateWsPort = firstDhNode.publicPorts.ws;
|
||||
substrateWsInternalPort = firstDhNode.internalPorts.ws;
|
||||
substrateNodeId = firstDhNode.name;
|
||||
logger.info(
|
||||
`🔌 Using DataHaven node ${substrateNodeId} on port ${substrateWsPort} for relayers and BEEFY check.`
|
||||
|
|
@ -449,7 +453,9 @@ export const launchRelayers = async (
|
|||
|
||||
const ethElRpcEndpoint = `ws://host.docker.internal:${ethWsPort}`;
|
||||
const ethClEndpoint = `http://host.docker.internal:${ethHttpPort}`;
|
||||
const substrateWsEndpoint = `ws://${substrateNodeId}:${substrateWsPort}`;
|
||||
|
||||
const substrateWsEndpoint = `ws://${substrateNodeId}:${substrateWsInternalPort}`;
|
||||
logger.info(`🔗 Substrate endpoint for relayers: ${substrateWsEndpoint}`);
|
||||
|
||||
const relayersToStart: RelayerSpec[] = [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,7 +1,11 @@
|
|||
import invariant from "tiny-invariant";
|
||||
import { logger, type RelayerType } from "utils";
|
||||
|
||||
type ContainerSpec = { name: string; publicPorts: Record<string, number> };
|
||||
type ContainerSpec = {
|
||||
name: string;
|
||||
publicPorts: Record<string, number>;
|
||||
internalPorts: Record<string, number>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents the state and associated resources of a launched network environment,
|
||||
|
|
@ -63,8 +67,12 @@ export class LaunchedNetwork {
|
|||
return container.publicPorts.ws ?? -1;
|
||||
}
|
||||
|
||||
addContainer(containerName: string, publicPorts: Record<string, number> = {}) {
|
||||
this._containers.push({ name: containerName, publicPorts });
|
||||
addContainer(
|
||||
containerName: string,
|
||||
publicPorts: Record<string, number> = {},
|
||||
internalPorts: Record<string, number> = {}
|
||||
) {
|
||||
this._containers.push({ name: containerName, publicPorts, internalPorts });
|
||||
}
|
||||
|
||||
public getPublicWsPort(): number {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
export const DEFAULT_SUBSTRATE_WS_PORT = 9944;
|
||||
|
||||
export const ANVIL_FUNDED_ACCOUNTS = {
|
||||
0: {
|
||||
publicKey: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
|
||||
|
|
|
|||
Loading…
Reference in a new issue