Skip to content

Commit

Permalink
REFACTOR: implement ssv dkg v3 support
Browse files Browse the repository at this point in the history
  • Loading branch information
daverolo committed Feb 17, 2025
1 parent 63a22d4 commit 7389ca3
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 43 deletions.
2 changes: 1 addition & 1 deletion launcher/src/backend/OneClickInstall.js
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ export class OneClickInstall {
if (constellation.includes("SSVDKGService")) {
let SSVDKGService = this.serviceManager.getService("SSVDKGService", {
...args,
consensusClients: [this.beaconService],
executionClients: [this.executionClient],
otherServices: this.validatorService === "SSVNetworkService" ? [this.validatorService] : [],
});
this.extraServices.push(SSVDKGService);
Expand Down
64 changes: 35 additions & 29 deletions launcher/src/backend/ServiceManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,7 @@ export class ServiceManager {

for (let task of tasks) {
let ssvConfig;
let ssvDkgConfig;
let service = services.find((s) => s.id === task.service.config.serviceID);
let dependencies = task.data.executionClients.concat(task.data.consensusClients, task.data.otherServices).map((s) =>
services.find((e) => {
Expand Down Expand Up @@ -387,14 +388,22 @@ export class ServiceManager {
let result = await this.nodeConnection.readSSVNetworkConfig(service.id);
ssvConfig = YAML.parse(result);
}
if (service.service === "SSVDKGService") {
let result = await this.nodeConnection.readSSVDKGConfig(service.id);
ssvDkgConfig = YAML.parse(result);
}

if (task.data.port) {
service = this.changePort(service, task.data.port);
}
let updated = this.addDependencies(service, dependencies, ssvConfig);
let updated = this.addDependencies(service, dependencies, ssvConfig, ssvDkgConfig);
if (service.service === "SSVNetworkService") {
await this.nodeConnection.writeSSVNetworkConfig(service.id, YAML.stringify(ssvConfig));
}
if (service.service === "SSVDKGService") {
await this.nodeConnection.writeSSVDKGConfig(service.id, YAML.stringify(ssvDkgConfig));
}

if (!Array.isArray(updated)) updated = [updated];
updated.forEach((dep) => {
let index = modifiedServices.findIndex((s) => s.id === dep.id);
Expand All @@ -413,7 +422,7 @@ export class ServiceManager {
);
}

addDependencies(service, dependencies, ssvConfig) {
addDependencies(service, dependencies, ssvConfig, ssvDkgConfig) {
let command = "";
let filter;
let keyValuePairs = [];
Expand Down Expand Up @@ -492,6 +501,8 @@ export class ServiceManager {
});
case "SSVNetwork":
return this.addSSVNetworkConnection(service, dependencies, ssvConfig);
case "SSVDKG":
return this.addSSVDKGConnection(service, dependencies, ssvDkgConfig);
case "LidoObolExit":
return this.addLidoObolExitConnection(service, dependencies);
case "Ejector":
Expand Down Expand Up @@ -625,6 +636,13 @@ export class ServiceManager {
return service;
}

addSSVDKGConnection(service, dependencies, ssvDkgConfig) {
const executionClient = dependencies.filter((d) => typeof d.buildExecutionClientWsEndpointUrl === "function")[0];
ssvDkgConfig.ethEndpointURL = `${executionClient ? executionClient.buildExecutionClientHttpEndpointUrl() : "http://ethnode:8545"}`;
service.dependencies.executionClients = executionClient ? [executionClient] : [];
return service;
}

addLidoObolExitConnection(service, dependencies) {
// handle beacon node command dependency
const consensusClient = dependencies.filter(
Expand Down Expand Up @@ -1089,13 +1107,7 @@ export class ServiceManager {
);
case "SSVDKGService":
ports = [new ServicePort(null, 3030, 3030, servicePortProtocol.udp), new ServicePort(null, 3030, 3030, servicePortProtocol.tcp)];
return SSVDKGService.buildByUserInput(
args.network,
ports,
args.installDir + "/ssvdkg",
args.consensusClients, // TOOD: remove later!
args.otherServices
);
return SSVDKGService.buildByUserInput(args.network, ports, args.installDir + "/ssvdkg", args.executionClients, args.otherServices);

case "LCOMService":
ports = [new ServicePort("127.0.0.1", 8000, 8000, servicePortProtocol.tcp)];
Expand Down Expand Up @@ -1216,7 +1228,7 @@ export class ServiceManager {
if (config.ssv_sk) {
replacementString = "OperatorPrivateKey: " + config.ssv_sk;
} else {
replacementString = "KeyStore:\n PrivateKeyFile: /secrets/encrypted_private_key.json\n PasswordFile: /secrets/password";
replacementString = "KeyStore:\n PrivateKeyFile: ./secrets/encrypted_private_key.json\n PasswordFile: ./secrets/password";
}

// prepare service's config file
Expand Down Expand Up @@ -1441,12 +1453,8 @@ export class ServiceManager {

// Prepares the SSVDKGService on installation
async prepareSSVDKG(service) {
console.log("prepareSSVDKG", service);
log.debug("prepareSSVDKG", service);
if (!service) return;
// Prepare service's config file
//const ssvDkgServiceConfig = await this.nodeConnection.readServiceConfiguration(service.id);
let ssvDkgConfig = service.getServiceConfiguration(0);
let ssvDkgConfig = service.getServiceConfiguration(0, service.dependencies.executionClients);
const dataDir = service.volumes.find((vol) => vol.servicePath === "/data").destinationPath;
const escapedConfigFile = StringUtils.escapeStringForShell(ssvDkgConfig);
this.nodeConnection.sshService.exec(`mkdir -p ${dataDir} && echo ${escapedConfigFile} > ${dataDir}/config.yaml`);
Expand Down Expand Up @@ -1562,39 +1570,37 @@ export class ServiceManager {
// Set dataDir and secretsDir that is *currently* added to SSVDKGService
const dataDir = SSVDKGService.volumes.find((vol) => vol.servicePath === "/data").destinationPath;
const secretsDir = SSVDKGService.volumes.find((vol) => vol.servicePath === "/secrets").destinationPath;
const secretsDir2 = SSVDKGService.volumes.find((vol) => vol.servicePath === "/ssv-dkg/secrets").destinationPath;
// Set local secretsDir that that is added to SSVDKGService by default on installation
const workingDir = path.dirname(dataDir);
const localSecretsDir = workingDir + "/secrets";
const localSecretsVolume = new ServiceVolume(localSecretsDir, "/secrets");
const localSecretsVolume2 = new ServiceVolume(localSecretsDir, "/ssv-dkg/secrets");
if (ssvTotalConfig) {
// Change local (SSVDKGService) secrets volume with shared (SSVNetworkService) secrets volume
if (!secretsDir.includes(SSVNetworkService.id)) {
if (!secretsDir.includes(SSVNetworkService.id) || !secretsDir2.includes(SSVNetworkService.id)) {
log.silly("SSVNetworkService exists");
log.info("Add shared secrets volume to DKG container");
const index = SSVDKGService.volumes.findIndex((vol) => vol.servicePath === "/secrets");
if (index !== -1) {
SSVDKGService.volumes.splice(index, 1);
}
log.info("Add shared secrets volumes to DKG container");
SSVDKGService.volumes = SSVDKGService.volumes.filter((vol) => !vol.servicePath.endsWith("/secrets"));
SSVDKGService.volumes.push(new ServiceVolume(ssvTotalConfig.ssvSecretsDir, "/secrets"));
SSVDKGService.volumes.push(new ServiceVolume(ssvTotalConfig.ssvSecretsDir, "/ssv-dkg/secrets"));
await this.nodeConnection.writeServiceConfiguration(SSVDKGService.buildConfiguration());
changes = true;
} else {
log.silly("Shared secrets volume already added to DKG container");
log.silly("Shared secrets volumes already added to DKG container");
}
} else {
// Change shared (SSVNetworkService) secrets volume with local (SSVDKGService) secrets volume
if (!secretsDir.includes(SSVDKGService.id)) {
if (!secretsDir.includes(SSVDKGService.id) || !secretsDir2.includes(SSVDKGService.id)) {
log.silly("SSVNetworkService does not exist");
log.info("Add local secrets volume to DKG container");
const index = SSVDKGService.volumes.findIndex((vol) => vol.servicePath === "/secrets");
if (index !== -1) {
SSVDKGService.volumes.splice(index, 1);
}
log.info("Add local secrets volumes to DKG container");
SSVDKGService.volumes = SSVDKGService.volumes.filter((vol) => !vol.servicePath.endsWith("/secrets"));
SSVDKGService.volumes.push(localSecretsVolume);
SSVDKGService.volumes.push(localSecretsVolume2);
await this.nodeConnection.writeServiceConfiguration(SSVDKGService.buildConfiguration());
changes = true;
} else {
log.silly("Local secrets volume already added to DKG container");
log.silly("Local secrets volumes already added to DKG container");
}
}

Expand Down
28 changes: 18 additions & 10 deletions launcher/src/backend/ethereum-services/SSVDKGService.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,37 @@ import { ServicePortDefinition } from "./SerivcePortDefinition.js";
import { ServiceVolume } from "./ServiceVolume.js";

export class SSVDKGService extends NodeService {
getServiceConfiguration(operatorID = 0) {
getServiceConfiguration(operatorID = 0, executionClients) {
if (!operatorID) operatorID = 0;
return `privKey: /secrets/encrypted_private_key.json
privKeyPassword: /secrets/password
let ethEndpointURL = executionClients && executionClients.length > 0 ? executionClients[0].buildExecutionClientHttpEndpointUrl() : null;
if (!ethEndpointURL) ethEndpointURL = "http://ethnode:8545";
return `privKey: ./secrets/encrypted_private_key.json
privKeyPassword: ./secrets/password
operatorID: ${operatorID}
port: 3030
logLevel: info
logFormat: json
logLevelFormat: capitalColor
logFilePath: /data/debug.log
outputPath: /data/output`;
logFilePath: ./data/debug.log
outputPath: ./data/output
ethEndpointURL: ${ethEndpointURL} #HTTP Address of Execution Node`;
}

static buildByUserInput(network, ports, dir, consensusClients, otherServices) {
static buildByUserInput(network, ports, dir, executionClients, otherServices) {
const service = new SSVDKGService();
service.setId();
const workingDir = service.buildWorkingDir(dir);

const image = "bloxstaking/ssv-dkg";
const image = "ssvlabs/ssv-dkg";

// Note that local secrets volume will be replaced with
// shared volume from SSVNetworkService later on...
const volumes = [new ServiceVolume(workingDir + "/data", "/data"), new ServiceVolume(workingDir + "/secrets", "/secrets")];
const volumes = [
new ServiceVolume(workingDir + "/data", "/data"),
new ServiceVolume(workingDir + "/data", "/ssv-dkg/data"),
new ServiceVolume(workingDir + "/secrets", "/secrets"),
new ServiceVolume(workingDir + "/secrets", "/ssv-dkg/secrets"),
];

console.log("-------> TTT :: otherServices", otherServices);

Expand All @@ -36,14 +44,14 @@ outputPath: /data/output`;
1, //configVersion
image, //image
"v2.1.0", //imageVersion
["start-operator", "--configPath=/data/config.yaml"], //command
["start-operator", "--configPath=./data/config.yaml"], //command
["/entry-point.sh"], // entrypoint
null, // env
ports, //ports
volumes, //volumes
"root", //user
network, //network
null, //executionClients
executionClients, //executionClients
null, //consensusClients
null, //mevboost
otherServices
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,9 @@ const getConnectionOptions = () => {
if (props.client.service === "KeysAPIService") {
return manageStore.newConfiguration.filter((e) => /consensus|execution/.test(e.category));
}
if (props.client.service === "SSVDKGService") {
return manageStore.newConfiguration.filter((e) => /execution/.test(e.category));
}
break;
default:
return [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ const getConfirmText = computed(() => {
} else if (
props.client.category === "consensus" ||
(props.client.category === "validator" && !/Web3Signer/.test(props.client.service)) ||
/LidoObolExit|ValidatorEjector|KeysAPI/.test(props.client.service)
/LidoObolExit|ValidatorEjector|KeysAPI|SSVDKG/.test(props.client.service)
) {
text = "next";
} else if (props.client.category === "service" && props.client.service !== "FlashbotsMevBoostService") {
Expand Down Expand Up @@ -118,7 +118,7 @@ const confirmInstall = () => {
} else if (
(props.client.category === "consensus" && getConfirmText.value === "next") ||
(props.client.category === "validator" && getConfirmText.value === "next") ||
/LidoObolExit|ValidatorEjector|KeysAPI/.test(props.client.service)
/LidoObolExit|ValidatorEjector|KeysAPI|SSVDKG/.test(props.client.service)
) {
isAddPanelActivated.value = false;
isModifyActivated.value = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,9 @@ const getConnectionOptions = () => {
if (props.client.service === "KeysAPIService") {
return manageStore.newConfiguration.filter((e) => /consensus|execution/.test(e.category));
}
if (props.client.service === "SSVDKGService") {
return manageStore.newConfiguration.filter((e) => /execution/.test(e.category));
}
break;
default:
return [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
<div class="w-full h-full grid grid-cols-2 items-center">
<div
v-if="
/FlashbotsMevBoostService|LidoObolExitService|ValidatorEjectorService|KeysAPIService/.test(item.service) &&
/FlashbotsMevBoostService|LidoObolExitService|ValidatorEjectorService|KeysAPIService|SSVDKGService/.test(item.service) &&
!item.isRemoveProcessing
"
class="w-8 h-8 col-start-1 col-span-1 self-center justify-self-center flex justify-center items-center border border-gray-500 bg-gray-700 rounded-md cursor-pointer p-1 transform active:scale-75 duration-200 hover:border-gray-300"
Expand Down

0 comments on commit 7389ca3

Please sign in to comment.