From ef5e07b0fe0ec2fa278b5913a7b72e365ea0830b Mon Sep 17 00:00:00 2001 From: Dappnodedev Date: Fri, 16 Aug 2024 08:28:23 +0000 Subject: [PATCH 01/15] Remove logic related to beacon-validator service --- packages/installer/src/ethClient/apiUrl.ts | 9 +- packages/stakers/src/consensus.ts | 111 +++++++-------------- packages/utils/src/index.ts | 2 +- packages/utils/src/stakerUtils.ts | 64 +++--------- 4 files changed, 54 insertions(+), 132 deletions(-) diff --git a/packages/installer/src/ethClient/apiUrl.ts b/packages/installer/src/ethClient/apiUrl.ts index 2034abff5..bb4f4f212 100644 --- a/packages/installer/src/ethClient/apiUrl.ts +++ b/packages/installer/src/ethClient/apiUrl.ts @@ -1,4 +1,4 @@ -import { buildNetworkAlias, getBeaconServiceName } from "@dappnode/utils"; +import { buildNetworkAlias } from "@dappnode/utils"; import { listPackageNoThrow } from "@dappnode/dockerapi"; /** @@ -38,14 +38,9 @@ export async function getEthConsClientApiUrl(dnpName: string): Promise { isMainOrMonoservice: false }); } else { - // Lighthouse, Teku and Prysm use 3500 - // Nimbus uses 4500 because it is a monoservice and the validator API is using that port - if (dnpName.includes("nimbus")) { - port = 4500; - } domain = buildNetworkAlias({ dnpName: dnpName, - serviceName: getBeaconServiceName(dnpName), + serviceName: "beacon-chain", isMainOrMonoservice: false }); } diff --git a/packages/stakers/src/consensus.ts b/packages/stakers/src/consensus.ts index 79c948d59..8586ed30d 100644 --- a/packages/stakers/src/consensus.ts +++ b/packages/stakers/src/consensus.ts @@ -110,7 +110,7 @@ export class Consensus extends StakerComponent { userSettings: newConsensusDnpName ? this.getUserSettings( newConsensusDnpName, - !(await listPackageNoThrow({ dnpName: newConsensusDnpName })), + !Boolean(await listPackageNoThrow({ dnpName: newConsensusDnpName })), network ) : {}, @@ -120,39 +120,28 @@ export class Consensus extends StakerComponent { if (newConsensusDnpName !== prevConsClientDnpName) await this.DbHandlers[network].set(newConsensusDnpName); } - private getUserSettings(newConsensusDnpName: string, shouldSetEnvironment: boolean, network: Network): UserSettings { - const validatorServiceName = this.getValidatorServiceName(newConsensusDnpName); - const beaconServiceName = this.getBeaconServiceName(newConsensusDnpName); + private getUserSettings(shouldSetEnvironment: boolean, network: Network): UserSettings { + const validatorServiceName = "validator"; + const beaconServiceName = "beacon-chain"; const defaultDappnodeGraffiti = "validating_from_DAppNode"; const defaultFeeRecipient = "0x0000000000000000000000000000000000000000"; return { environment: shouldSetEnvironment - ? beaconServiceName === validatorServiceName - ? { - [validatorServiceName]: { - // Fee recipient is set as global env, keep this for backwards compatibility - ["FEE_RECIPIENT_ADDRESS"]: defaultFeeRecipient, // TODO: consider setting the MEV fee recipient as the default - // Graffiti is a mandatory value - ["GRAFFITI"]: defaultDappnodeGraffiti, - // Checkpoint sync is an optional value - ["CHECKPOINT_SYNC_URL"]: Consensus.DefaultCheckpointSync[network] - } - } - : { - [validatorServiceName]: { - // Fee recipient is set as global env, keep this for backwards compatibility - ["FEE_RECIPIENT_ADDRESS"]: defaultFeeRecipient, - // Graffiti is a mandatory value - ["GRAFFITI"]: defaultDappnodeGraffiti - }, + ? { + [validatorServiceName]: { + // Fee recipient is set as global env, keep this for backwards compatibility + ["FEE_RECIPIENT_ADDRESS"]: defaultFeeRecipient, + // Graffiti is a mandatory value + ["GRAFFITI"]: defaultDappnodeGraffiti + }, - [beaconServiceName]: { - // Fee recipient is set as global env, keep this for backwards compatibility - ["FEE_RECIPIENT_ADDRESS"]: defaultFeeRecipient, - // Checkpoint sync is an optional value - ["CHECKPOINT_SYNC_URL"]: Consensus.DefaultCheckpointSync[network] - } + [beaconServiceName]: { + // Fee recipient is set as global env, keep this for backwards compatibility + ["FEE_RECIPIENT_ADDRESS"]: defaultFeeRecipient, + // Checkpoint sync is an optional value + ["CHECKPOINT_SYNC_URL"]: Consensus.DefaultCheckpointSync[network] } + } : {}, networks: { rootNetworks: { @@ -163,55 +152,25 @@ export class Consensus extends StakerComponent { external: true } }, - serviceNetworks: - beaconServiceName === validatorServiceName - ? { - "beacon-validator": { - [params.DOCKER_STAKER_NETWORKS[network]]: { - aliases: [`beacon-chain.${network}.staker.dappnode`, `validator.${network}.staker.dappnode`] - }, - [params.DOCKER_PRIVATE_NETWORK_NAME]: { - aliases: [`beacon-chain.${network}.dncore.dappnode`, `validator.${network}.dncore.dappnode`] - } - } - } - : { - "beacon-chain": { - [params.DOCKER_STAKER_NETWORKS[network]]: { - aliases: [`beacon-chain.${network}.staker.dappnode`] - }, - [params.DOCKER_PRIVATE_NETWORK_NAME]: { - aliases: [`beacon-chain.${network}.dncore.dappnode`] - } - }, - validator: { - [params.DOCKER_STAKER_NETWORKS[network]]: { - aliases: [`validator.${network}.staker.dappnode`] - }, - [params.DOCKER_PRIVATE_NETWORK_NAME]: { - aliases: [`validator.${network}.dncore.dappnode`] - } - } - } + serviceNetworks: { + "beacon-chain": { + [params.DOCKER_STAKER_NETWORKS[network]]: { + aliases: [`beacon-chain.${network}.staker.dappnode`] + }, + [params.DOCKER_PRIVATE_NETWORK_NAME]: { + aliases: [`beacon-chain.${network}.dncore.dappnode`] + } + }, + validator: { + [params.DOCKER_STAKER_NETWORKS[network]]: { + aliases: [`validator.${network}.staker.dappnode`] + }, + [params.DOCKER_PRIVATE_NETWORK_NAME]: { + aliases: [`validator.${network}.dncore.dappnode`] + } + } + } } }; } - - /** - * Get the validator service name. - * - Nimbus package is monoservice (beacon-validator) - * - Prysm, Teku, Lighthouse, and Lodestar are multiservice (beacon, validator) - */ - private getValidatorServiceName(newConsensusDnpName: string | null): string { - return newConsensusDnpName ? (newConsensusDnpName.includes("nimbus") ? "beacon-validator" : "validator") : ""; - } - - /** - * Get the beacon service name - * - Nimbus package is monoservice (beacon-validator) - * - Prysm, Teku, Lighthouse, and Lodestar are multiservice (beacon, validator) - */ - private getBeaconServiceName(newConsensusDnpName: string | null): string { - return newConsensusDnpName ? (newConsensusDnpName.includes("nimbus") ? "beacon-validator" : "beacon-chain") : ""; - } } diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index 989320ea7..704239c8c 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -27,7 +27,7 @@ export * from "./asyncFlows.js"; export * from "./pid.js"; export { urlJoin } from "./urlJoin.js"; export { prettyDnpName } from "./prettyDnpName.js"; -export { getBeaconServiceName, getConsensusUserSettings } from "./stakerUtils.js"; +export { getConsensusUserSettings } from "./stakerUtils.js"; export * from "./ethers.js"; export { shellSafe } from "./shellSafe.js"; export { getIsInstalled } from "./getIsInstalled.js"; diff --git a/packages/utils/src/stakerUtils.ts b/packages/utils/src/stakerUtils.ts index f346f8c05..6a3aa270d 100644 --- a/packages/utils/src/stakerUtils.ts +++ b/packages/utils/src/stakerUtils.ts @@ -1,25 +1,5 @@ import { UserSettingsAllDnps, Network } from "@dappnode/types"; -// TODO: remove these utils - -/** - * Get the validator service name. - * - Nimbus package is monoservice (beacon-validator) - * - Prysm, Teku, Lighthouse, and Lodestar are multiservice (beacon, validator) - */ -function getValidatorServiceName(dnpName: string): string { - return dnpName.includes("nimbus") ? "beacon-validator" : "validator"; -} - -/** - * Get the beacon service name - * - Nimbus package is monoservice (beacon-validator) - * - Prysm, Teku, Lighthouse, and Lodestar are multiservice (beacon, validator) - */ -export function getBeaconServiceName(dnpName: string): string { - return dnpName.includes("nimbus") ? "beacon-validator" : "beacon-chain"; -} - /** * Get the user settings for the consensus client. * It may be different depending if it is multiservice or monoservice and all the envs are @@ -32,39 +12,27 @@ export function getConsensusUserSettings({ dnpName: string; network: Network; }): UserSettingsAllDnps { - const validatorServiceName = getValidatorServiceName(dnpName); - const beaconServiceName = getBeaconServiceName(dnpName); + const validatorServiceName = "validator"; + const beaconServiceName = "beacon-chain"; const defaultDappnodeGraffiti = "validating_from_DAppNode"; const defaultFeeRecipient = "0x0000000000000000000000000000000000000000"; return { [dnpName]: { - environment: - beaconServiceName === validatorServiceName - ? { - [validatorServiceName]: { - // Fee recipient is set as global env, keep this for backwards compatibility - ["FEE_RECIPIENT_ADDRESS"]: defaultFeeRecipient, // TODO: consider setting the MEV fee recipient as the default - // Graffiti is a mandatory value - ["GRAFFITI"]: defaultDappnodeGraffiti, - // Checkpoint sync is an optional value - ["CHECKPOINT_SYNC_URL"]: getDefaultCheckpointSync(network) - } - } - : { - [validatorServiceName]: { - // Fee recipient is set as global env, keep this for backwards compatibility - ["FEE_RECIPIENT_ADDRESS"]: defaultFeeRecipient, - // Graffiti is a mandatory value - ["GRAFFITI"]: defaultDappnodeGraffiti - }, + environment: { + [validatorServiceName]: { + // Fee recipient is set as global env, keep this for backwards compatibility + ["FEE_RECIPIENT_ADDRESS"]: defaultFeeRecipient, + // Graffiti is a mandatory value + ["GRAFFITI"]: defaultDappnodeGraffiti + }, - [beaconServiceName]: { - // Fee recipient is set as global env, keep this for backwards compatibility - ["FEE_RECIPIENT_ADDRESS"]: defaultFeeRecipient, - // Checkpoint sync is an optional value - ["CHECKPOINT_SYNC_URL"]: getDefaultCheckpointSync(network) - } - } + [beaconServiceName]: { + // Fee recipient is set as global env, keep this for backwards compatibility + ["FEE_RECIPIENT_ADDRESS"]: defaultFeeRecipient, + // Checkpoint sync is an optional value + ["CHECKPOINT_SYNC_URL"]: getDefaultCheckpointSync(network) + } + } } }; } From 613f974c48756156407eec55ad2e4d0d7ad4343a Mon Sep 17 00:00:00 2001 From: Dappnodedev Date: Wed, 4 Sep 2024 08:17:37 +0000 Subject: [PATCH 02/15] Clean getEthConsClientApiUrl --- packages/installer/src/ethClient/apiUrl.ts | 34 +++++++++++++--------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/packages/installer/src/ethClient/apiUrl.ts b/packages/installer/src/ethClient/apiUrl.ts index bb4f4f212..ca9cc118a 100644 --- a/packages/installer/src/ethClient/apiUrl.ts +++ b/packages/installer/src/ethClient/apiUrl.ts @@ -27,22 +27,28 @@ export function getEthExecClientApiUrl(dnpName: string, port = 8545): string { * @param dnpName */ export async function getEthConsClientApiUrl(dnpName: string): Promise { - let port = 3500; - let domain = ""; + const defaultPort = 3500; + const defaultServiceName = "beacon-chain"; + const dnp = await listPackageNoThrow({ dnpName }); - if (dnp && typeof dnp.chain === "object" && dnp.chain.portNumber && dnp.chain.serviceName) { - port = dnp.chain.portNumber; - domain = buildNetworkAlias({ - dnpName: dnpName, - serviceName: dnp.chain.serviceName, - isMainOrMonoservice: false - }); - } else { - domain = buildNetworkAlias({ - dnpName: dnpName, - serviceName: "beacon-chain", + + if (!dnp || typeof dnp.chain !== "object") { + const domain = buildNetworkAlias({ + dnpName, + serviceName: defaultServiceName, isMainOrMonoservice: false }); + + return `http://${domain}:${defaultPort}`; } - return `http://${domain}:${port}`; + + const { chain: { portNumber = defaultPort, serviceName = defaultServiceName } = {} } = dnp; + + const domain = buildNetworkAlias({ + dnpName, + serviceName, + isMainOrMonoservice: false + }); + + return `http://${domain}:${portNumber}`; } From c4cc4d6f4057c04eb3c9393d42112834f415ffd0 Mon Sep 17 00:00:00 2001 From: Dappnodedev Date: Wed, 4 Sep 2024 08:37:22 +0000 Subject: [PATCH 03/15] Remove unused arg --- packages/stakers/src/consensus.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/stakers/src/consensus.ts b/packages/stakers/src/consensus.ts index 8586ed30d..97de0b958 100644 --- a/packages/stakers/src/consensus.ts +++ b/packages/stakers/src/consensus.ts @@ -94,7 +94,7 @@ export class Consensus extends StakerComponent { } await this.persistSelectedIfInstalled({ dnpName: currentConsensusDnpName, - userSettings: this.getUserSettings(currentConsensusDnpName, isInstalled, network) + userSettings: this.getUserSettings(isInstalled, network) }); await this.DbHandlers[network].set(currentConsensusDnpName); } @@ -108,11 +108,7 @@ export class Consensus extends StakerComponent { dockerNetworkName: params.DOCKER_STAKER_NETWORKS[network], compatibleClients: Consensus.CompatibleConsensus[network], userSettings: newConsensusDnpName - ? this.getUserSettings( - newConsensusDnpName, - !Boolean(await listPackageNoThrow({ dnpName: newConsensusDnpName })), - network - ) + ? this.getUserSettings(!Boolean(await listPackageNoThrow({ dnpName: newConsensusDnpName })), network) : {}, prevClient: prevConsClientDnpName }); From dce5ad9316d42e3ad8c56d904120b3e257c6210a Mon Sep 17 00:00:00 2001 From: Dappnodedev Date: Wed, 4 Sep 2024 08:43:04 +0000 Subject: [PATCH 04/15] Remove unneeded boolean --- packages/stakers/src/consensus.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/stakers/src/consensus.ts b/packages/stakers/src/consensus.ts index 97de0b958..897130b5d 100644 --- a/packages/stakers/src/consensus.ts +++ b/packages/stakers/src/consensus.ts @@ -108,7 +108,7 @@ export class Consensus extends StakerComponent { dockerNetworkName: params.DOCKER_STAKER_NETWORKS[network], compatibleClients: Consensus.CompatibleConsensus[network], userSettings: newConsensusDnpName - ? this.getUserSettings(!Boolean(await listPackageNoThrow({ dnpName: newConsensusDnpName })), network) + ? this.getUserSettings(!(await listPackageNoThrow({ dnpName: newConsensusDnpName })), network) : {}, prevClient: prevConsClientDnpName }); From fa63497317d3b790cd7acaea8f4ce832ede105b7 Mon Sep 17 00:00:00 2001 From: Dappnodedev Date: Wed, 4 Sep 2024 12:00:03 +0000 Subject: [PATCH 05/15] Remove consensus settings code duplication --- .../installer/src/ethClient/ethereumClient.ts | 10 ++-- packages/stakers/src/consensus.ts | 50 ++++++------------- packages/utils/src/stakerUtils.ts | 47 +++++++++-------- 3 files changed, 46 insertions(+), 61 deletions(-) diff --git a/packages/installer/src/ethClient/ethereumClient.ts b/packages/installer/src/ethClient/ethereumClient.ts index c003d419c..da1378d6b 100644 --- a/packages/installer/src/ethClient/ethereumClient.ts +++ b/packages/installer/src/ethClient/ethereumClient.ts @@ -317,10 +317,12 @@ export class EthereumClient { }); if (!consClientPkg) { // Get default cons client user settings and install cons client - const userSettings = getConsensusUserSettings({ - dnpName: consClient, - network: Network.Mainnet - }); + const userSettings = { + [consClient]: getConsensusUserSettings({ + network: Network.Mainnet + }) + }; + await packageInstall(dappnodeInstaller, { name: consClient, userSettings diff --git a/packages/stakers/src/consensus.ts b/packages/stakers/src/consensus.ts index 897130b5d..e8c306d8e 100644 --- a/packages/stakers/src/consensus.ts +++ b/packages/stakers/src/consensus.ts @@ -13,6 +13,7 @@ import { DappnodeInstaller } from "@dappnode/installer"; import * as db from "@dappnode/db"; import { listPackageNoThrow } from "@dappnode/dockerapi"; import { params } from "@dappnode/params"; +import { getConsensusUserSettings } from "@dappnode/utils"; // TODO: move ethereumClient logic here @@ -30,13 +31,6 @@ export class Consensus extends StakerComponent { [Network.Holesky]: db.consensusClientHolesky, [Network.Lukso]: db.consensusClientLukso }; - protected static readonly DefaultCheckpointSync: Record = { - [Network.Mainnet]: "https://checkpoint-sync.dappnode.io", - [Network.Prater]: "https://checkpoint-sync-prater.dappnode.io", - [Network.Gnosis]: "https://checkpoint-sync-gnosis.dappnode.io", - [Network.Holesky]: "https://checkpoint-sync-holesky.dappnode.io", - [Network.Lukso]: "https://checkpoints.mainnet.lukso.network" - }; protected static readonly CompatibleConsensus: Record = { [Network.Mainnet]: [ { dnpName: ConsensusClientMainnet.Prysm, minVersion: "3.0.4" }, @@ -103,13 +97,14 @@ export class Consensus extends StakerComponent { async setNewConsensus(network: Network, newConsensusDnpName: string | null) { const prevConsClientDnpName = this.DbHandlers[network].get(); + const mustInstallPkg = !!newConsensusDnpName && !(await listPackageNoThrow({ dnpName: newConsensusDnpName })); + const userSettings = newConsensusDnpName ? this.getUserSettings(mustInstallPkg, network) : {}; + await super.setNew({ newStakerDnpName: newConsensusDnpName, dockerNetworkName: params.DOCKER_STAKER_NETWORKS[network], compatibleClients: Consensus.CompatibleConsensus[network], - userSettings: newConsensusDnpName - ? this.getUserSettings(!(await listPackageNoThrow({ dnpName: newConsensusDnpName })), network) - : {}, + userSettings, prevClient: prevConsClientDnpName }); // persist on db @@ -119,26 +114,11 @@ export class Consensus extends StakerComponent { private getUserSettings(shouldSetEnvironment: boolean, network: Network): UserSettings { const validatorServiceName = "validator"; const beaconServiceName = "beacon-chain"; - const defaultDappnodeGraffiti = "validating_from_DAppNode"; - const defaultFeeRecipient = "0x0000000000000000000000000000000000000000"; - return { - environment: shouldSetEnvironment - ? { - [validatorServiceName]: { - // Fee recipient is set as global env, keep this for backwards compatibility - ["FEE_RECIPIENT_ADDRESS"]: defaultFeeRecipient, - // Graffiti is a mandatory value - ["GRAFFITI"]: defaultDappnodeGraffiti - }, - [beaconServiceName]: { - // Fee recipient is set as global env, keep this for backwards compatibility - ["FEE_RECIPIENT_ADDRESS"]: defaultFeeRecipient, - // Checkpoint sync is an optional value - ["CHECKPOINT_SYNC_URL"]: Consensus.DefaultCheckpointSync[network] - } - } - : {}, + const consensusDefaultUserSettings = getConsensusUserSettings({ network }); + + return { + environment: shouldSetEnvironment ? consensusDefaultUserSettings.environment : {}, networks: { rootNetworks: { [params.DOCKER_STAKER_NETWORKS[network]]: { @@ -149,20 +129,20 @@ export class Consensus extends StakerComponent { } }, serviceNetworks: { - "beacon-chain": { + [beaconServiceName]: { [params.DOCKER_STAKER_NETWORKS[network]]: { - aliases: [`beacon-chain.${network}.staker.dappnode`] + aliases: [`${beaconServiceName}.${network}.staker.dappnode`] }, [params.DOCKER_PRIVATE_NETWORK_NAME]: { - aliases: [`beacon-chain.${network}.dncore.dappnode`] + aliases: [`${beaconServiceName}.${network}.dncore.dappnode`] } }, - validator: { + [validatorServiceName]: { [params.DOCKER_STAKER_NETWORKS[network]]: { - aliases: [`validator.${network}.staker.dappnode`] + aliases: [`${validatorServiceName}.${network}.staker.dappnode`] }, [params.DOCKER_PRIVATE_NETWORK_NAME]: { - aliases: [`validator.${network}.dncore.dappnode`] + aliases: [`${validatorServiceName}.${network}.dncore.dappnode`] } } } diff --git a/packages/utils/src/stakerUtils.ts b/packages/utils/src/stakerUtils.ts index 6a3aa270d..c43b4715b 100644 --- a/packages/utils/src/stakerUtils.ts +++ b/packages/utils/src/stakerUtils.ts @@ -1,37 +1,40 @@ -import { UserSettingsAllDnps, Network } from "@dappnode/types"; +import { UserSettings, Network } from "@dappnode/types"; /** * Get the user settings for the consensus client. * It may be different depending if it is multiservice or monoservice and all the envs are * set in the same service */ -export function getConsensusUserSettings({ - dnpName, - network -}: { - dnpName: string; - network: Network; -}): UserSettingsAllDnps { +export function getConsensusUserSettings({ network }: { network: Network }): UserSettings { const validatorServiceName = "validator"; const beaconServiceName = "beacon-chain"; + const beaconValidatorServiceName = "beacon-validator"; const defaultDappnodeGraffiti = "validating_from_DAppNode"; const defaultFeeRecipient = "0x0000000000000000000000000000000000000000"; return { - [dnpName]: { - environment: { - [validatorServiceName]: { - // Fee recipient is set as global env, keep this for backwards compatibility - ["FEE_RECIPIENT_ADDRESS"]: defaultFeeRecipient, - // Graffiti is a mandatory value - ["GRAFFITI"]: defaultDappnodeGraffiti - }, + environment: { + // TODO: Remove once Nimbus is split into 2 services + [beaconValidatorServiceName]: { + // Fee recipient is set as global env, keep this for backwards compatibility + ["FEE_RECIPIENT_ADDRESS"]: defaultFeeRecipient, // TODO: consider setting the MEV fee recipient as the default + // Graffiti is a mandatory value + ["GRAFFITI"]: defaultDappnodeGraffiti, + // Checkpoint sync is an optional value + ["CHECKPOINT_SYNC_URL"]: getDefaultCheckpointSync(network) + }, - [beaconServiceName]: { - // Fee recipient is set as global env, keep this for backwards compatibility - ["FEE_RECIPIENT_ADDRESS"]: defaultFeeRecipient, - // Checkpoint sync is an optional value - ["CHECKPOINT_SYNC_URL"]: getDefaultCheckpointSync(network) - } + [validatorServiceName]: { + // Fee recipient is set as global env, keep this for backwards compatibility + ["FEE_RECIPIENT_ADDRESS"]: defaultFeeRecipient, + // Graffiti is a mandatory value + ["GRAFFITI"]: defaultDappnodeGraffiti + }, + + [beaconServiceName]: { + // Fee recipient is set as global env, keep this for backwards compatibility + ["FEE_RECIPIENT_ADDRESS"]: defaultFeeRecipient, + // Checkpoint sync is an optional value + ["CHECKPOINT_SYNC_URL"]: getDefaultCheckpointSync(network) } } }; From b33ac49e98b4e4909479613e867d02ea839cf5b9 Mon Sep 17 00:00:00 2001 From: Dappnodedev Date: Wed, 4 Sep 2024 12:05:49 +0000 Subject: [PATCH 06/15] Use new user settings --- packages/daemons/src/ethMultiClient/index.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/daemons/src/ethMultiClient/index.ts b/packages/daemons/src/ethMultiClient/index.ts index d03cfb208..6e9d3bac9 100644 --- a/packages/daemons/src/ethMultiClient/index.ts +++ b/packages/daemons/src/ethMultiClient/index.ts @@ -70,10 +70,11 @@ export async function runEthClientInstaller( if (isConsensusClientMainnet(target)) await packageInstall(dappnodeInstaller, { name: target, - userSettings: getConsensusUserSettings({ - dnpName: target, - network: Network.Mainnet - }) + userSettings: { + [target]: getConsensusUserSettings({ + network: Network.Mainnet + }) + } }); else await packageInstall(dappnodeInstaller, { name: target }); } catch (e) { From 6734a7f03a956b5b56917f5d45f958e27b3408b1 Mon Sep 17 00:00:00 2001 From: Dappnodedev Date: Wed, 4 Sep 2024 13:48:39 +0000 Subject: [PATCH 07/15] Add TODOs --- packages/installer/src/ethClient/apiUrl.ts | 2 ++ packages/utils/src/stakerUtils.ts | 2 ++ 2 files changed, 4 insertions(+) diff --git a/packages/installer/src/ethClient/apiUrl.ts b/packages/installer/src/ethClient/apiUrl.ts index ca9cc118a..246e9d67a 100644 --- a/packages/installer/src/ethClient/apiUrl.ts +++ b/packages/installer/src/ethClient/apiUrl.ts @@ -30,6 +30,8 @@ export async function getEthConsClientApiUrl(dnpName: string): Promise { const defaultPort = 3500; const defaultServiceName = "beacon-chain"; + // TODO: Use beacon-chain..dncore.dappnode + const dnp = await listPackageNoThrow({ dnpName }); if (!dnp || typeof dnp.chain !== "object") { diff --git a/packages/utils/src/stakerUtils.ts b/packages/utils/src/stakerUtils.ts index c43b4715b..fef9b429c 100644 --- a/packages/utils/src/stakerUtils.ts +++ b/packages/utils/src/stakerUtils.ts @@ -1,5 +1,7 @@ import { UserSettings, Network } from "@dappnode/types"; +// TODO: The code in this file should be included in the stakers module + /** * Get the user settings for the consensus client. * It may be different depending if it is multiservice or monoservice and all the envs are From 5a7554d49485f5e4f0e4f9f0c76083fcf3aa3f79 Mon Sep 17 00:00:00 2001 From: Dappnodedev Date: Wed, 4 Sep 2024 14:49:38 +0000 Subject: [PATCH 08/15] Force recreate on network set --- packages/stakers/src/stakerComponent.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/stakers/src/stakerComponent.ts b/packages/stakers/src/stakerComponent.ts index e2d897036..077b63907 100644 --- a/packages/stakers/src/stakerComponent.ts +++ b/packages/stakers/src/stakerComponent.ts @@ -151,7 +151,7 @@ export class StakerComponent { } // start all containers - await dockerComposeUpPackage({ dnpName }, true); + await dockerComposeUpPackage({ dnpName }, true, undefined, { forceRecreate: true }); } /** From 075b00fbac6f25b6b8bf640ae86bfe5b08cba7f1 Mon Sep 17 00:00:00 2001 From: Dappnodedev Date: Thu, 5 Sep 2024 11:20:30 +0000 Subject: [PATCH 09/15] Ensure nimbus connection --- .../dappmanager/src/calls/packageInstall.ts | 42 +++++++++++- packages/stakers/src/consensus.ts | 64 +++++++++++-------- packages/utils/src/index.ts | 2 +- packages/utils/src/stakerUtils.ts | 2 +- 4 files changed, 81 insertions(+), 29 deletions(-) diff --git a/packages/dappmanager/src/calls/packageInstall.ts b/packages/dappmanager/src/calls/packageInstall.ts index e938c19d2..5059aa91e 100644 --- a/packages/dappmanager/src/calls/packageInstall.ts +++ b/packages/dappmanager/src/calls/packageInstall.ts @@ -1,6 +1,8 @@ -import { Routes } from "@dappnode/types"; +import { Network, Routes } from "@dappnode/types"; import { packageInstall as pkgInstall } from "@dappnode/installer"; import { dappnodeInstaller } from "../index.js"; +import { Consensus } from "@dappnode/stakers"; +import { logs } from "@dappnode/logger"; /** * Installs a DAppNode Package. @@ -26,4 +28,42 @@ export async function packageInstall({ userSettings, options }); + + ensureNimbusConnection(reqName); +} + +/** + * Nimbus package will be migrated from a monoservice to a multiservice package. + * beacon-validator will be split into beacon-chain and validator services. + * + * This function ensures both services are properly connected to the staker network + * after installing the new version. + * + * TODO: Remove this once all Nimbus packages are multiservice + */ +function ensureNimbusConnection(dnpName: string): void { + if (!dnpName.includes("nimbus")) { + logs.debug("Not a Nimbus package, skipping network reconnection"); + } + + logs.info("Ensuring Nimbus services are connected to the staker network"); + + const consensus: Consensus = new Consensus(dappnodeInstaller); + + const nimbusNetwork: Record = { + "nimbus.dnp.dappnode.eth": Network.Mainnet, + "nimbus-prater.dnp.dappnode.eth": Network.Prater, + "nimbus-gnosis.dnp.dappnode.eth": Network.Gnosis, + "nimbus-holesky.dnp.dappnode.eth": Network.Holesky + }; + + const network = nimbusNetwork[dnpName]; + + if (!network) { + logs.error("Could not determine the network for the Nimbus package"); + return; + } + + // Not awaited + consensus.persistSelectedConsensusIfInstalled(network); } diff --git a/packages/stakers/src/consensus.ts b/packages/stakers/src/consensus.ts index e8c306d8e..7fede2769 100644 --- a/packages/stakers/src/consensus.ts +++ b/packages/stakers/src/consensus.ts @@ -86,9 +86,16 @@ export class Consensus extends StakerComponent { this.DbHandlers[network].set(undefined); return; } + + const userSettings = { + // No need to add default environment if the package is already installed + environment: isInstalled ? {} : getConsensusUserSettings({ network }).environment, + networks: this.getStakerNetworkSettings(network) + }; + await this.persistSelectedIfInstalled({ dnpName: currentConsensusDnpName, - userSettings: this.getUserSettings(isInstalled, network) + userSettings }); await this.DbHandlers[network].set(currentConsensusDnpName); } @@ -97,8 +104,7 @@ export class Consensus extends StakerComponent { async setNewConsensus(network: Network, newConsensusDnpName: string | null) { const prevConsClientDnpName = this.DbHandlers[network].get(); - const mustInstallPkg = !!newConsensusDnpName && !(await listPackageNoThrow({ dnpName: newConsensusDnpName })); - const userSettings = newConsensusDnpName ? this.getUserSettings(mustInstallPkg, network) : {}; + const userSettings = await this.getUserSettings(network, newConsensusDnpName); await super.setNew({ newStakerDnpName: newConsensusDnpName, @@ -111,39 +117,45 @@ export class Consensus extends StakerComponent { if (newConsensusDnpName !== prevConsClientDnpName) await this.DbHandlers[network].set(newConsensusDnpName); } - private getUserSettings(shouldSetEnvironment: boolean, network: Network): UserSettings { + private async getUserSettings(network: Network, newConsensusDnpName: string | null): Promise { + const mustInstallPkg = !!newConsensusDnpName && !(await listPackageNoThrow({ dnpName: newConsensusDnpName })); + + const userSettings = { + environment: mustInstallPkg ? getConsensusUserSettings({ network }).environment : {}, + networks: this.getStakerNetworkSettings(network) + }; + + return userSettings; + } + + private getStakerNetworkSettings(network: Network): UserSettings["networks"] { const validatorServiceName = "validator"; const beaconServiceName = "beacon-chain"; - const consensusDefaultUserSettings = getConsensusUserSettings({ network }); - return { - environment: shouldSetEnvironment ? consensusDefaultUserSettings.environment : {}, - networks: { - rootNetworks: { + rootNetworks: { + [params.DOCKER_STAKER_NETWORKS[network]]: { + external: true + }, + [params.DOCKER_PRIVATE_NETWORK_NAME]: { + external: true + } + }, + serviceNetworks: { + [beaconServiceName]: { [params.DOCKER_STAKER_NETWORKS[network]]: { - external: true + aliases: [`${beaconServiceName}.${network}.staker.dappnode`] }, [params.DOCKER_PRIVATE_NETWORK_NAME]: { - external: true + aliases: [`${beaconServiceName}.${network}.dncore.dappnode`] } }, - serviceNetworks: { - [beaconServiceName]: { - [params.DOCKER_STAKER_NETWORKS[network]]: { - aliases: [`${beaconServiceName}.${network}.staker.dappnode`] - }, - [params.DOCKER_PRIVATE_NETWORK_NAME]: { - aliases: [`${beaconServiceName}.${network}.dncore.dappnode`] - } + [validatorServiceName]: { + [params.DOCKER_STAKER_NETWORKS[network]]: { + aliases: [`${validatorServiceName}.${network}.staker.dappnode`] }, - [validatorServiceName]: { - [params.DOCKER_STAKER_NETWORKS[network]]: { - aliases: [`${validatorServiceName}.${network}.staker.dappnode`] - }, - [params.DOCKER_PRIVATE_NETWORK_NAME]: { - aliases: [`${validatorServiceName}.${network}.dncore.dappnode`] - } + [params.DOCKER_PRIVATE_NETWORK_NAME]: { + aliases: [`${validatorServiceName}.${network}.dncore.dappnode`] } } } diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index 704239c8c..a10a06531 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -27,7 +27,7 @@ export * from "./asyncFlows.js"; export * from "./pid.js"; export { urlJoin } from "./urlJoin.js"; export { prettyDnpName } from "./prettyDnpName.js"; -export { getConsensusUserSettings } from "./stakerUtils.js"; +export { getDefaultConsensusUserSettings as getConsensusUserSettings } from "./stakerUtils.js"; export * from "./ethers.js"; export { shellSafe } from "./shellSafe.js"; export { getIsInstalled } from "./getIsInstalled.js"; diff --git a/packages/utils/src/stakerUtils.ts b/packages/utils/src/stakerUtils.ts index fef9b429c..866aa4bc9 100644 --- a/packages/utils/src/stakerUtils.ts +++ b/packages/utils/src/stakerUtils.ts @@ -7,7 +7,7 @@ import { UserSettings, Network } from "@dappnode/types"; * It may be different depending if it is multiservice or monoservice and all the envs are * set in the same service */ -export function getConsensusUserSettings({ network }: { network: Network }): UserSettings { +export function getDefaultConsensusUserSettings({ network }: { network: Network }): UserSettings { const validatorServiceName = "validator"; const beaconServiceName = "beacon-chain"; const beaconValidatorServiceName = "beacon-validator"; From dbc92065feaad3a89d8cec7bba86254c221fa8b5 Mon Sep 17 00:00:00 2001 From: Dappnodedev Date: Thu, 5 Sep 2024 12:25:22 +0000 Subject: [PATCH 10/15] Clean staker user settings --- packages/stakers/src/consensus.ts | 27 +++++---------- packages/stakers/src/execution.ts | 21 ++++-------- packages/stakers/src/mevBoost.ts | 44 ++++++++++++++----------- packages/stakers/src/signer.ts | 9 +---- packages/stakers/src/stakerComponent.ts | 23 ++++++++++++- packages/utils/src/index.ts | 2 +- 6 files changed, 64 insertions(+), 62 deletions(-) diff --git a/packages/stakers/src/consensus.ts b/packages/stakers/src/consensus.ts index 7fede2769..8f0bf28bd 100644 --- a/packages/stakers/src/consensus.ts +++ b/packages/stakers/src/consensus.ts @@ -11,9 +11,8 @@ import { import { StakerComponent } from "./stakerComponent.js"; import { DappnodeInstaller } from "@dappnode/installer"; import * as db from "@dappnode/db"; -import { listPackageNoThrow } from "@dappnode/dockerapi"; import { params } from "@dappnode/params"; -import { getConsensusUserSettings } from "@dappnode/utils"; +import { getDefaultConsensusUserSettings } from "@dappnode/utils"; // TODO: move ethereumClient logic here @@ -79,7 +78,7 @@ export class Consensus extends StakerComponent { async persistSelectedConsensusIfInstalled(network: Network): Promise { const currentConsensusDnpName = this.DbHandlers[network].get(); if (currentConsensusDnpName) { - const isInstalled = Boolean(await listPackageNoThrow({ dnpName: currentConsensusDnpName })); + const isInstalled = await this.isPackageInstalled(currentConsensusDnpName); if (!isInstalled) { // update status in db @@ -87,11 +86,7 @@ export class Consensus extends StakerComponent { return; } - const userSettings = { - // No need to add default environment if the package is already installed - environment: isInstalled ? {} : getConsensusUserSettings({ network }).environment, - networks: this.getStakerNetworkSettings(network) - }; + const userSettings = await this.getUserSettings(network, currentConsensusDnpName); await this.persistSelectedIfInstalled({ dnpName: currentConsensusDnpName, @@ -118,10 +113,13 @@ export class Consensus extends StakerComponent { } private async getUserSettings(network: Network, newConsensusDnpName: string | null): Promise { - const mustInstallPkg = !!newConsensusDnpName && !(await listPackageNoThrow({ dnpName: newConsensusDnpName })); + if (!newConsensusDnpName) return {}; + + const isPkgInstalled = await this.isPackageInstalled(newConsensusDnpName); const userSettings = { - environment: mustInstallPkg ? getConsensusUserSettings({ network }).environment : {}, + // If the package is not installed, we use the default environment + environment: isPkgInstalled ? {} : getDefaultConsensusUserSettings({ network }).environment, networks: this.getStakerNetworkSettings(network) }; @@ -133,14 +131,7 @@ export class Consensus extends StakerComponent { const beaconServiceName = "beacon-chain"; return { - rootNetworks: { - [params.DOCKER_STAKER_NETWORKS[network]]: { - external: true - }, - [params.DOCKER_PRIVATE_NETWORK_NAME]: { - external: true - } - }, + rootNetworks: this.getComposeRootNetworks(network), serviceNetworks: { [beaconServiceName]: { [params.DOCKER_STAKER_NETWORKS[network]]: { diff --git a/packages/stakers/src/execution.ts b/packages/stakers/src/execution.ts index 0bc8a3d2d..6bba262b2 100644 --- a/packages/stakers/src/execution.ts +++ b/packages/stakers/src/execution.ts @@ -11,7 +11,6 @@ import { import { StakerComponent } from "./stakerComponent.js"; import { DappnodeInstaller, ethereumClient } from "@dappnode/installer"; import * as db from "@dappnode/db"; -import { listPackageNoThrow } from "@dappnode/dockerapi"; import { params } from "@dappnode/params"; // TODO: move ethereumClient logic here @@ -72,15 +71,14 @@ export class Execution extends StakerComponent { async persistSelectedExecutionIfInstalled(network: Network): Promise { const currentExecutionDnpName = this.DbHandlers[network].get(); if (currentExecutionDnpName) { - const isInstalled = await listPackageNoThrow({ - dnpName: currentExecutionDnpName - }); + const isInstalled = await this.isPackageInstalled(currentExecutionDnpName); if (!isInstalled) { // update status in db this.DbHandlers[network].set(undefined); return; } + await this.persistSelectedIfInstalled({ dnpName: currentExecutionDnpName, userSettings: this.getUserSettings(network, currentExecutionDnpName) @@ -96,7 +94,7 @@ export class Execution extends StakerComponent { newStakerDnpName: newExecutionDnpName, dockerNetworkName: params.DOCKER_STAKER_NETWORKS[network], compatibleClients: Execution.CompatibleExecutions[network], - userSettings: newExecutionDnpName ? this.getUserSettings(network, newExecutionDnpName) : {}, + userSettings: this.getUserSettings(network, newExecutionDnpName), prevClient: prevExecClientDnpName }); @@ -112,17 +110,12 @@ export class Execution extends StakerComponent { } } - private getUserSettings(network: Network, dnpName: string): UserSettings { + private getUserSettings(network: Network, dnpName: string | null): UserSettings { + if (!dnpName) return {}; + return { networks: { - rootNetworks: { - [params.DOCKER_STAKER_NETWORKS[network]]: { - external: true - }, - [params.DOCKER_PRIVATE_NETWORK_NAME]: { - external: true - } - }, + rootNetworks: this.getComposeRootNetworks(network), serviceNetworks: { [this.getExecutionServiceName(dnpName)]: { [params.DOCKER_STAKER_NETWORKS[network]]: { diff --git a/packages/stakers/src/mevBoost.ts b/packages/stakers/src/mevBoost.ts index ae3a651c8..853542d86 100644 --- a/packages/stakers/src/mevBoost.ts +++ b/packages/stakers/src/mevBoost.ts @@ -70,7 +70,7 @@ export class MevBoost extends StakerComponent { } await this.persistSelectedIfInstalled({ dnpName: currentMevBoostDnpName, - userSettings: this.getUserSettings([], false, network) + userSettings: this.getUserSettings(network, null) }); this.DbHandlers[network].set(true); } @@ -82,7 +82,7 @@ export class MevBoost extends StakerComponent { newStakerDnpName: newMevBoostDnpName, dockerNetworkName: params.DOCKER_STAKER_NETWORKS[network], compatibleClients: compatibleMevBoost ? [compatibleMevBoost] : null, - userSettings: newMevBoostDnpName ? this.getUserSettings(newRelays, true, network) : {}, + userSettings: newMevBoostDnpName ? this.getUserSettings(network, newRelays) : {}, prevClient: compatibleMevBoost ? compatibleMevBoost.dnpName : null }); // persist on db @@ -90,11 +90,14 @@ export class MevBoost extends StakerComponent { await this.DbHandlers[network].set(newMevBoostDnpName ? true : false); } - private getUserSettings(newRelays: string[], shouldSetEnvironment: boolean, network: Network): UserSettings { - return { - environment: shouldSetEnvironment + private getUserSettings(network: Network, newRelays: string[] | null): UserSettings { + const mevBoostServiceName = "mev-boost"; + + const userSettings: UserSettings = { + // If the package is not installed, we use the default environment + environment: newRelays ? { - "mev-boost": { + [mevBoostServiceName]: { ["RELAYS"]: newRelays .join(",") @@ -103,23 +106,24 @@ export class MevBoost extends StakerComponent { } } : {}, - networks: { - rootNetworks: { + networks: this.getStakerNetworkSettings(network) + }; + + return userSettings; + } + + private getStakerNetworkSettings(network: Network): UserSettings["networks"] { + const mevBoostServiceName = "mev-boost"; + + return { + rootNetworks: this.getComposeRootNetworks(network), + serviceNetworks: { + [mevBoostServiceName]: { [params.DOCKER_STAKER_NETWORKS[network]]: { - external: true + aliases: [`${mevBoostServiceName}.${network}.staker.dappnode`] }, [params.DOCKER_PRIVATE_NETWORK_NAME]: { - external: true - } - }, - serviceNetworks: { - ["mev-boost"]: { - [params.DOCKER_STAKER_NETWORKS[network]]: { - aliases: [`mev-boost.${network}.staker.dappnode`] - }, - [params.DOCKER_PRIVATE_NETWORK_NAME]: { - aliases: [`mev-boost.${network}.dncore.dappnode`] - } + aliases: [`${mevBoostServiceName}.${network}.dncore.dappnode`] } } } diff --git a/packages/stakers/src/signer.ts b/packages/stakers/src/signer.ts index e18e0c373..ff78d11a0 100644 --- a/packages/stakers/src/signer.ts +++ b/packages/stakers/src/signer.ts @@ -77,14 +77,7 @@ export class Signer extends StakerComponent { private getUserSettings(network: Network): UserSettings { return { networks: { - rootNetworks: { - [params.DOCKER_STAKER_NETWORKS[network]]: { - external: true - }, - [params.DOCKER_PRIVATE_NETWORK_NAME]: { - external: true - } - }, + rootNetworks: this.getComposeRootNetworks(network), serviceNetworks: { web3signer: { [params.DOCKER_STAKER_NETWORKS[network]]: { diff --git a/packages/stakers/src/stakerComponent.ts b/packages/stakers/src/stakerComponent.ts index 077b63907..d2e5666b1 100644 --- a/packages/stakers/src/stakerComponent.ts +++ b/packages/stakers/src/stakerComponent.ts @@ -14,11 +14,13 @@ import { UserSettingsAllDnps, PackageContainer, StakerItem, - UserSettings + UserSettings, + Network } from "@dappnode/types"; import { getIsInstalled, getIsUpdated, getIsRunning, fileToGatewayUrl } from "@dappnode/utils"; import { lt } from "semver"; import { isMatch } from "lodash-es"; +import { params } from "@dappnode/params"; export class StakerComponent { protected dappnodeInstaller: DappnodeInstaller; @@ -118,6 +120,25 @@ export class StakerComponent { }); } + protected async isPackageInstalled(dnpName: string): Promise { + const dnp = await listPackageNoThrow({ dnpName }); + + return Boolean(dnp); + } + + protected getComposeRootNetworks(network: Network): NonNullable["rootNetworks"] { + return { + rootNetworks: { + [params.DOCKER_STAKER_NETWORKS[network]]: { + external: true + }, + [params.DOCKER_PRIVATE_NETWORK_NAME]: { + external: true + } + } + }; + } + /** * Set the staker pkg: * - ensures the staker pkg is installed diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index a10a06531..b2625f759 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -27,7 +27,7 @@ export * from "./asyncFlows.js"; export * from "./pid.js"; export { urlJoin } from "./urlJoin.js"; export { prettyDnpName } from "./prettyDnpName.js"; -export { getDefaultConsensusUserSettings as getConsensusUserSettings } from "./stakerUtils.js"; +export { getDefaultConsensusUserSettings } from "./stakerUtils.js"; export * from "./ethers.js"; export { shellSafe } from "./shellSafe.js"; export { getIsInstalled } from "./getIsInstalled.js"; From 73cec025f02dcac0941a3679f01db0daa7e89ce3 Mon Sep 17 00:00:00 2001 From: Dappnodedev Date: Thu, 5 Sep 2024 12:29:15 +0000 Subject: [PATCH 11/15] Fix import --- packages/daemons/src/ethMultiClient/index.ts | 4 ++-- packages/installer/src/ethClient/ethereumClient.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/daemons/src/ethMultiClient/index.ts b/packages/daemons/src/ethMultiClient/index.ts index 6e9d3bac9..3645e193d 100644 --- a/packages/daemons/src/ethMultiClient/index.ts +++ b/packages/daemons/src/ethMultiClient/index.ts @@ -1,7 +1,7 @@ import * as db from "@dappnode/db"; import { eventBus } from "@dappnode/eventbus"; import { params } from "@dappnode/params"; -import { runAtMostEvery, runOnlyOneSequentially, getConsensusUserSettings } from "@dappnode/utils"; +import { runAtMostEvery, runOnlyOneSequentially, getDefaultConsensusUserSettings } from "@dappnode/utils"; import { logs } from "@dappnode/logger"; import { EthClientRemote, @@ -71,7 +71,7 @@ export async function runEthClientInstaller( await packageInstall(dappnodeInstaller, { name: target, userSettings: { - [target]: getConsensusUserSettings({ + [target]: getDefaultConsensusUserSettings({ network: Network.Mainnet }) } diff --git a/packages/installer/src/ethClient/ethereumClient.ts b/packages/installer/src/ethClient/ethereumClient.ts index da1378d6b..f8520bff7 100644 --- a/packages/installer/src/ethClient/ethereumClient.ts +++ b/packages/installer/src/ethClient/ethereumClient.ts @@ -3,7 +3,7 @@ import { Eth2ClientTarget, EthClientRemote, InstalledPackageDetailData } from "@ import * as db from "@dappnode/db"; import { eventBus } from "@dappnode/eventbus"; import { logs } from "@dappnode/logger"; -import { getConsensusUserSettings } from "@dappnode/utils"; +import { getDefaultConsensusUserSettings } from "@dappnode/utils"; import { packageInstall, packageGet, packageRemove } from "../calls/index.js"; import { ComposeFileEditor, parseServiceNetworks } from "@dappnode/dockercompose"; import { params } from "@dappnode/params"; @@ -318,7 +318,7 @@ export class EthereumClient { if (!consClientPkg) { // Get default cons client user settings and install cons client const userSettings = { - [consClient]: getConsensusUserSettings({ + [consClient]: getDefaultConsensusUserSettings({ network: Network.Mainnet }) }; From 01dcea0317bdd8e89ff6d511494604e677a32550 Mon Sep 17 00:00:00 2001 From: Dappnodedev Date: Thu, 5 Sep 2024 15:05:52 +0000 Subject: [PATCH 12/15] Fix root networks --- packages/stakers/src/stakerComponent.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/stakers/src/stakerComponent.ts b/packages/stakers/src/stakerComponent.ts index d2e5666b1..995415629 100644 --- a/packages/stakers/src/stakerComponent.ts +++ b/packages/stakers/src/stakerComponent.ts @@ -128,13 +128,11 @@ export class StakerComponent { protected getComposeRootNetworks(network: Network): NonNullable["rootNetworks"] { return { - rootNetworks: { - [params.DOCKER_STAKER_NETWORKS[network]]: { - external: true - }, - [params.DOCKER_PRIVATE_NETWORK_NAME]: { - external: true - } + [params.DOCKER_STAKER_NETWORKS[network]]: { + external: true + }, + [params.DOCKER_PRIVATE_NETWORK_NAME]: { + external: true } }; } From 511270870a6a17232305e1e0487d822439bb5127 Mon Sep 17 00:00:00 2001 From: Dappnodedev Date: Thu, 5 Sep 2024 15:33:30 +0000 Subject: [PATCH 13/15] Fix error on disconnecting restarting container --- packages/stakers/src/stakerComponent.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/stakers/src/stakerComponent.ts b/packages/stakers/src/stakerComponent.ts index 995415629..b6dd3efd1 100644 --- a/packages/stakers/src/stakerComponent.ts +++ b/packages/stakers/src/stakerComponent.ts @@ -193,7 +193,11 @@ export class StakerComponent { const connectedContainers = pkgContainers .filter((container) => container.networks.some((network) => network.name === networkName)) .map((container) => container.containerName); - for (const container of connectedContainers) await dockerNetworkDisconnect(networkName, container); + for (const container of connectedContainers) + await dockerNetworkDisconnect(networkName, container).catch((e) => + // TODO: What if the restarting container is started again? Will it reconnect to the docker network? + logs.error(`Could not disconnect container from ${networkName}: ${e.message}`) + ); } private removeStakerNetworkFromCompose(dnpName: string, dockerNetworkName: string): void { From 7b9b8cd474e58937067d7083741922f129fbd876 Mon Sep 17 00:00:00 2001 From: Dappnodedev Date: Fri, 6 Sep 2024 14:41:33 +0000 Subject: [PATCH 14/15] Fix docker container disconnect --- .../src/dockerRecreatePackageContainers.ts | 22 ++++++++++ packages/dockerApi/src/index.ts | 1 + packages/stakers/src/stakerComponent.ts | 43 ++----------------- 3 files changed, 27 insertions(+), 39 deletions(-) create mode 100644 packages/dockerApi/src/dockerRecreatePackageContainers.ts diff --git a/packages/dockerApi/src/dockerRecreatePackageContainers.ts b/packages/dockerApi/src/dockerRecreatePackageContainers.ts new file mode 100644 index 000000000..df6177a5d --- /dev/null +++ b/packages/dockerApi/src/dockerRecreatePackageContainers.ts @@ -0,0 +1,22 @@ +import fs from "fs"; +import { getDockerComposePathSmart } from "@dappnode/utils"; +import { dockerComposeDown, dockerComposeUp } from "./compose/cli.js"; + +/** + * Recreates the containers of a package. They are stopped and removed, then created again. + * + * The package containers will be shown as stopped after this operation. + * + * @param dnpName + */ +export async function dockerRecreatePackageContainers(dnpName: string): Promise { + const composePath = getDockerComposePathSmart(dnpName); + + if (!fs.existsSync(composePath)) { + throw Error(`No docker-compose found for ${dnpName} at ${composePath}`); + } + + await dockerComposeDown(composePath); + + await dockerComposeUp(composePath, { noStart: true }); +} diff --git a/packages/dockerApi/src/index.ts b/packages/dockerApi/src/index.ts index 9c1b8543e..4c3cfd8ca 100644 --- a/packages/dockerApi/src/index.ts +++ b/packages/dockerApi/src/index.ts @@ -10,4 +10,5 @@ export * from "./cleanOldImages.js"; export * from "./list/index.js"; export * from "./compose/index.js"; export * from "./api/index.js"; +export * from "./dockerRecreatePackageContainers.js"; export { getDappmanagerImage } from "./getDappmanagerImage.js"; diff --git a/packages/stakers/src/stakerComponent.ts b/packages/stakers/src/stakerComponent.ts index b6dd3efd1..7fb3f922e 100644 --- a/packages/stakers/src/stakerComponent.ts +++ b/packages/stakers/src/stakerComponent.ts @@ -1,22 +1,13 @@ import { dockerComposeUpPackage, - dockerContainerStop, - dockerNetworkDisconnect, + dockerRecreatePackageContainers, listPackageNoThrow, listPackages } from "@dappnode/dockerapi"; import { ComposeFileEditor } from "@dappnode/dockercompose"; import { DappnodeInstaller, packageGetData, packageInstall } from "@dappnode/installer"; import { logs } from "@dappnode/logger"; -import { - InstalledPackageDataApiReturn, - InstalledPackageData, - UserSettingsAllDnps, - PackageContainer, - StakerItem, - UserSettings, - Network -} from "@dappnode/types"; +import { InstalledPackageData, UserSettingsAllDnps, StakerItem, UserSettings, Network } from "@dappnode/types"; import { getIsInstalled, getIsUpdated, getIsRunning, fileToGatewayUrl } from "@dappnode/utils"; import { lt } from "semver"; import { isMatch } from "lodash-es"; @@ -180,24 +171,10 @@ export class StakerComponent { * - removes the staker network from the docker-compose file */ private async unsetStakerPkgConfig(pkg: InstalledPackageData, dockerNetworkName: string): Promise { - // disconnect pkg from staker network - await this.disconnectPkgFromStakerNetwork(dockerNetworkName, pkg.containers); - - // stop all containers - await this.stopAllPkgContainers(pkg); - // remove staker network from the compose file this.removeStakerNetworkFromCompose(pkg.dnpName, dockerNetworkName); - } - private async disconnectPkgFromStakerNetwork(networkName: string, pkgContainers: PackageContainer[]): Promise { - const connectedContainers = pkgContainers - .filter((container) => container.networks.some((network) => network.name === networkName)) - .map((container) => container.containerName); - for (const container of connectedContainers) - await dockerNetworkDisconnect(networkName, container).catch((e) => - // TODO: What if the restarting container is started again? Will it reconnect to the docker network? - logs.error(`Could not disconnect container from ${networkName}: ${e.message}`) - ); + // Check if we can lose info not included in the package volumes + await dockerRecreatePackageContainers(pkg.dnpName); } private removeStakerNetworkFromCompose(dnpName: string, dockerNetworkName: string): void { @@ -244,16 +221,4 @@ export class StakerComponent { ); } } - - /** - * Stop all the containers from a given package dnpName - */ - // TODO: Move this to where packages and containers are started/stopped - private async stopAllPkgContainers(pkg: InstalledPackageDataApiReturn | InstalledPackageData): Promise { - await Promise.all( - pkg.containers - .filter((c) => c.running) - .map(async (c) => dockerContainerStop(c.containerName, { timeout: c.dockerTimeout })) - ).catch((e) => logs.error(e.message)); - } } From d920205e1d955d9b681c7f5256c94626afc37703 Mon Sep 17 00:00:00 2001 From: Dappnodedev Date: Mon, 9 Sep 2024 09:47:20 +0000 Subject: [PATCH 15/15] Remove recreate containers function --- .../src/dockerRecreatePackageContainers.ts | 22 ------------------- packages/dockerApi/src/index.ts | 1 - packages/stakers/src/stakerComponent.ts | 12 ++++------ 3 files changed, 4 insertions(+), 31 deletions(-) delete mode 100644 packages/dockerApi/src/dockerRecreatePackageContainers.ts diff --git a/packages/dockerApi/src/dockerRecreatePackageContainers.ts b/packages/dockerApi/src/dockerRecreatePackageContainers.ts deleted file mode 100644 index df6177a5d..000000000 --- a/packages/dockerApi/src/dockerRecreatePackageContainers.ts +++ /dev/null @@ -1,22 +0,0 @@ -import fs from "fs"; -import { getDockerComposePathSmart } from "@dappnode/utils"; -import { dockerComposeDown, dockerComposeUp } from "./compose/cli.js"; - -/** - * Recreates the containers of a package. They are stopped and removed, then created again. - * - * The package containers will be shown as stopped after this operation. - * - * @param dnpName - */ -export async function dockerRecreatePackageContainers(dnpName: string): Promise { - const composePath = getDockerComposePathSmart(dnpName); - - if (!fs.existsSync(composePath)) { - throw Error(`No docker-compose found for ${dnpName} at ${composePath}`); - } - - await dockerComposeDown(composePath); - - await dockerComposeUp(composePath, { noStart: true }); -} diff --git a/packages/dockerApi/src/index.ts b/packages/dockerApi/src/index.ts index 4c3cfd8ca..9c1b8543e 100644 --- a/packages/dockerApi/src/index.ts +++ b/packages/dockerApi/src/index.ts @@ -10,5 +10,4 @@ export * from "./cleanOldImages.js"; export * from "./list/index.js"; export * from "./compose/index.js"; export * from "./api/index.js"; -export * from "./dockerRecreatePackageContainers.js"; export { getDappmanagerImage } from "./getDappmanagerImage.js"; diff --git a/packages/stakers/src/stakerComponent.ts b/packages/stakers/src/stakerComponent.ts index 7fb3f922e..045b48687 100644 --- a/packages/stakers/src/stakerComponent.ts +++ b/packages/stakers/src/stakerComponent.ts @@ -1,9 +1,4 @@ -import { - dockerComposeUpPackage, - dockerRecreatePackageContainers, - listPackageNoThrow, - listPackages -} from "@dappnode/dockerapi"; +import { dockerComposeUpPackage, listPackageNoThrow, listPackages } from "@dappnode/dockerapi"; import { ComposeFileEditor } from "@dappnode/dockercompose"; import { DappnodeInstaller, packageGetData, packageInstall } from "@dappnode/installer"; import { logs } from "@dappnode/logger"; @@ -173,8 +168,9 @@ export class StakerComponent { private async unsetStakerPkgConfig(pkg: InstalledPackageData, dockerNetworkName: string): Promise { this.removeStakerNetworkFromCompose(pkg.dnpName, dockerNetworkName); - // Check if we can lose info not included in the package volumes - await dockerRecreatePackageContainers(pkg.dnpName); + // This recreates the package containers so that they include the recently added configuration + // The flag --no-start is added so that the containers remain stopped after recreation + await dockerComposeUpPackage({ dnpName: pkg.dnpName }, false, undefined, { forceRecreate: true, noStart: true }); } private removeStakerNetworkFromCompose(dnpName: string, dockerNetworkName: string): void {