1import * as _ from 'lodash-es' 20const nimbusDeploymentTmpl = ({ 21 name, dataPvcName, httpWeb3Prov, nimbusNodePort, execEngProv, ethNetwork, ethRewardAddr, 22 p2pHostIp, cpSyncApiUrl, trustedBlockRoot, trustedStateRoot, nimbusV, enableValidator, 23 validatorsSecName, secretsSecName, validatorPubkeys, podResources, 25 name: string, dataPvcName: string, httpWeb3Prov: string, nimbusNodePort: number, 26 execEngProv: string, ethNetwork: string, ethRewardAddr: string, 27 p2pHostIp: string, cpSyncApiUrl: string | null, trustedBlockRoot: string | null, 28 trustedStateRoot: string | null, nimbusV: string, enableValidator: boolean, 29 validatorsSecName: string, secretsSecName: string, validatorPubkeys: string[], 30 podResources?: object, 32 const jwtSecretName = `${ethNetwork}-jwt` 33 const image = `statusim/nimbus-eth2:multiarch-${nimbusV}` 35 const validatorsDir = '/validators' 36 const secretsDir = '/secrets' 37 const keystoresSrcDir = '/keystores-src' 38 const secretsSrcDir = '/secrets-src' 42 `--network=${ethNetwork}`, 43 `--web3-url=${execEngProv}`, 45 `--tcp-port=${nimbusNodePort}`, 46 `--udp-port=${nimbusNodePort}`, 47 `--nat=extip:${p2pHostIp}`, 49 '--rest-address=0.0.0.0', 51 `--suggested-fee-recipient=${ethRewardAddr}`, 52 '--enr-auto-update=false', 57 `--external-beacon-api-url=${cpSyncApiUrl}`, 60 if (trustedBlockRoot) { 63 `--trusted-block-root=${trustedBlockRoot}`, 66 if (trustedStateRoot) { 69 `--trusted-state-root=${trustedStateRoot}`, 72 if (enableValidator) { 75 `--validators-dir=${validatorsDir}`, 76 `--secrets-dir=${secretsDir}`, 88 subPath: jwtSecretName, 92 let volumes: Record<string, unknown>[] = [ 95 persistentVolumeClaim: { 96 claimName: dataPvcName 102 secretName: jwtSecretName 107 let initContainers: Record<string, unknown>[] = [ 111 if (enableValidator) { 112 const validatorVolName = 'validator-data' 113 const secretsVolName = 'secrets-data' 118 name: validatorVolName, 119 mountPath: validatorsDir, 122 name: secretsVolName, 123 mountPath: secretsDir, 129 name: validatorsSecName, 131 secretName: validatorsSecName 135 name: secretsSecName, 137 secretName: secretsSecName 141 name: validatorVolName, 145 name: secretsVolName, 150 // Build shell script to organize keystores into Nimbus directory structure 151 const setupCmds = validatorPubkeys.map(pubkey => [ 152 `mkdir -p ${validatorsDir}/0x${pubkey}`, 153 `cp ${keystoresSrcDir}/keystore-${pubkey}.json ${validatorsDir}/0x${pubkey}/keystore.json`, 154 `cp ${secretsSrcDir}/secret-${pubkey} ${secretsDir}/0x${pubkey}`, 155 ].join(' && ')).join(' && ') 160 name: 'setup-validators', 161 image: 'busybox:1.36', 162 command: ['sh', '-c', setupCmds], 164 {name: validatorsSecName, mountPath: keystoresSrcDir}, 165 {name: secretsSecName, mountPath: secretsSrcDir}, 166 {name: validatorVolName, mountPath: validatorsDir}, 167 {name: secretsVolName, mountPath: secretsDir}, 174 apiVersion: 'apps/v1', 204 args, image, command: [], 216export const doSyncNimbus = async ({ 217 eth1ClientName, ethNetwork, ethRewardAddr, p2pHostIp, 218 nimbusNodePort, nimbusV, cpSyncApiUrl, trustedBlockRoot, trustedStateRoot, 219 enableValidator, guardValidatorFn, localValSecretsPath, ethValidatorNums, 221 eth1ClientName: string, ethNetwork: string, ethRewardAddr: string, p2pHostIp: string, 222 nimbusNodePort: number, nimbusV: string, cpSyncApiUrl: string | null, 223 trustedBlockRoot?: string | null, trustedStateRoot?: string | null, 224 enableValidator: boolean, guardValidatorFn?: GuardValidatorFn, localValSecretsPath?: string, ethValidatorNums?: number[], 230 const name = `nimbus-${ethNetwork}` 231 const dataPvcName = name 233 // Note: trustedBlockRoot requires LC bootstrap support which most checkpoint servers don't have. 234 // If trustedBlockRoot is not provided, Nimbus will sync from cpSyncApiUrl without LC validation. 236 let {httpWeb3Prov, execEngProv, jwtSecretName} = getEth2Vals({ethNetwork, eth1ClientName}) 238 const validatorsSecName = `${name}-validators` 239 const secretsSecName = `${name}-secrets` 241 let validatorPubkeys: string[] = [] 242 const validatorsSecretsH: Record<string, string> = {} 243 const secretsSecretsH: Record<string, string> = {} 245 if (enableValidator === true) { 247 await guardValidatorFn({ethNetwork, name, cluster_name, action}) 249 const {walletPassSecName} = getEth2Vals({ethNetwork, eth1ClientName}) 251 if (action != 'delete') { 254 const keystoreFiles = _.filter(fs.readdirSync(localValSecretsPath), (path) => { 255 return _.endsWith(path, '.json') && _.startsWith(path, 'keystore-') 258 _.each(keystoreFiles, (filename) => { 259 const keystoreVal = fs.readFileSync([localValSecretsPath, filename].join('/'), 'utf8') 260 const keystoreJson = JSON.parse(keystoreVal) 261 const pubkey = keystoreJson.pubkey 262 assertTruthy(pubkey && pubkey.length === 96, {filename, pubkeyLen: pubkey?.length}) 263 validatorPubkeys.push(pubkey) 265 validatorsSecretsH[`keystore-${pubkey}.json`] = keystoreVal 266 secretsSecretsH[`secret-${pubkey}`] = walletPassS 271 const nimbusDeployment = nimbusDeploymentTmpl({ 272 name, dataPvcName, httpWeb3Prov, nimbusNodePort, 273 nimbusV, execEngProv, ethNetwork, ethRewardAddr, 274 p2pHostIp, cpSyncApiUrl, trustedBlockRoot: trustedBlockRoot ?? null, trustedStateRoot: trustedStateRoot ?? null, 275 enableValidator, validatorsSecName, secretsSecName, validatorPubkeys, 278 deployment: nimbusDeployment, enabled: enableValidator === true && action != 'delete', 279 ethValidatorNum: ethValidatorNums?.[0], cluster_name, domainName: domainNames?.[0], cfApiKeySecretName, 283 ...(claimCheckConfigMap ? [claimCheckConfigMap] : []), 295 if (enableValidator === true) { 296 resources = _.union(resources, [ 302 resources = _.union(resources, cleanupResOnDelete({action, enabled: enableValidator, secNames: [validatorsSecName, secretsSecName]}))