Skip to content

Commit 5a62289

Browse files
committed
changes from other branch
Signed-off-by: instamenta <[email protected]>
1 parent 88c2506 commit 5a62289

7 files changed

+205
-15
lines changed

src/commands/network.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ export interface NetworkDeployConfigClass {
6161
grpcWebTlsCertificatePath: string;
6262
grpcTlsKeyPath: string;
6363
grpcWebTlsKeyPath: string;
64+
genesisNetworkJson: string;
6465
getUnusedConfigs: () => string[];
6566
haproxyIps: string;
6667
envoyIps: string;
@@ -140,6 +141,7 @@ export class NetworkCommand extends BaseCommand {
140141
releaseTag?: string;
141142
persistentVolumeClaims?: string;
142143
valuesFile?: string;
144+
genesisNetworkJson?: string;
143145
haproxyIpsParsed?: Record<NodeAlias, IP>;
144146
envoyIpsParsed?: Record<NodeAlias, IP>;
145147
} = {},
@@ -197,6 +199,8 @@ export class NetworkCommand extends BaseCommand {
197199
valuesArg += this.prepareValuesFiles(config.valuesFile);
198200
}
199201

202+
valuesArg += `--set "hedera.configMaps.genesisNetworkJson=${config.genesisNetworkJson}"`
203+
200204
this.logger.debug('Prepared helm chart values', {valuesArg});
201205
return valuesArg;
202206
}
@@ -257,6 +261,8 @@ export class NetworkCommand extends BaseCommand {
257261
constants.SOLO_DEPLOYMENT_CHART,
258262
);
259263

264+
config.genesisNetworkJson = this.prepareGenesisNetworkJson(config)
265+
260266
config.valuesArg = await this.prepareValuesArg(config);
261267

262268
// compute other config parameters
@@ -390,7 +396,7 @@ export class NetworkCommand extends BaseCommand {
390396
task: (ctx, parentTask) => {
391397
const config = ctx.config;
392398

393-
// set up the sub-tasks
399+
// set up the subtasks
394400
return parentTask.newListr(self.platformInstaller.copyNodeKeys(config.stagingDir, config.nodeAliases), {
395401
concurrent: true,
396402
rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION,
@@ -506,7 +512,7 @@ export class NetworkCommand extends BaseCommand {
506512
),
507513
});
508514

509-
// set up the sub-tasks
515+
// set up the subtasks
510516
return task.newListr(subTasks, {
511517
concurrent: false, // no need to run concurrently since if one node is up, the rest should be up by then
512518
rendererOptions: {
@@ -675,6 +681,14 @@ export class NetworkCommand extends BaseCommand {
675681
return true;
676682
}
677683

684+
prepareGenesisNetworkJson(config: NetworkDeployConfigClass): string {
685+
const data = {network: {nodes: []}}
686+
687+
// TODO
688+
689+
return JSON.stringify(data);
690+
}
691+
678692
getCommandDefinition(): {command: string; desc: string; builder: CommandBuilder} {
679693
const self = this;
680694
return {

src/core/account_manager.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ export class AccountManager {
225225
* @param networkNodeServicesMap - a map of the service objects that proxy the nodes
226226
* @param operatorId - the account id of the operator of the transactions
227227
* @param operatorKey - the private key of the operator of the transactions
228+
* @param skipNodeAlias -
228229
* @returns a node client that can be used to call transactions
229230
*/
230231
async _getNodeClient(

src/core/helpers.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,13 +254,14 @@ export function addDebugOptions(valuesArg: string, debugNodeAlias: NodeAlias, in
254254
export function addSaveContextParser(ctx: any) {
255255
const exportedCtx = {} as Record<string, string>;
256256

257-
const config = /** @type {NodeAddConfigClass} **/ ctx.config;
257+
const config = ctx.config as NodeAddConfigClass;
258258
const exportedFields = ['tlsCertHash', 'upgradeZipHash', 'newNode'];
259259

260260
exportedCtx.signingCertDer = ctx.signingCertDer.toString();
261261
exportedCtx.gossipEndpoints = ctx.gossipEndpoints.map((ep: any) => `${ep.getDomainName}:${ep.getPort}`);
262262
exportedCtx.grpcServiceEndpoints = ctx.grpcServiceEndpoints.map((ep: any) => `${ep.getDomainName}:${ep.getPort}`);
263263
exportedCtx.adminKey = ctx.adminKey.toString();
264+
// @ts-ignore
264265
exportedCtx.existingNodeAliases = config.existingNodeAliases;
265266

266267
for (const prop of exportedFields) {
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/**
2+
* Copyright (C) 2024 Hedera Hashgraph, LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the ""License"");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an ""AS IS"" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*/
17+
import type {NodeAlias, NodeAliases} from '../../types/aliases.js';
18+
import {GenesisNetworkNodeDataWrapper} from './genesisNetworkNodeDataWrapper.js';
19+
import {Templates} from '../templates.js';
20+
import {KeyManager} from '../key_manager.js';
21+
22+
import crypto from 'node:crypto';
23+
import {PrivateKey} from '@hashgraph/sdk';
24+
import {constants} from '../index.js';
25+
26+
export class GenesisNetworkDataConstructor {
27+
public readonly nodes: Record<NodeAlias, GenesisNetworkNodeDataWrapper>;
28+
29+
constructor (public readonly nodeAliases: NodeAliases) {
30+
this.nodeAliases.forEach(nodeAlias => {
31+
this.nodes[nodeAlias] = new GenesisNetworkNodeDataWrapper(Templates.nodeIdFromNodeAlias(nodeAlias))
32+
33+
const adminKey = PrivateKey.fromStringED25519(constants.GENESIS_KEY)
34+
this.nodes[nodeAlias].adminKey = adminKey.publicKey
35+
})
36+
}
37+
38+
/**
39+
* @param keyManager
40+
* @param keysDir - !!! config.keysDir !!!
41+
*/
42+
async load (keyManager: KeyManager, keysDir: string) {
43+
await Promise.all(this.nodeAliases.map(async nodeAlias => {
44+
const nodeKeys = await keyManager.loadSigningKey(nodeAlias, keysDir);
45+
46+
this.nodes[nodeAlias].gossipCaCertificate = nodeKeys.certificate.toString()
47+
48+
const certificate = nodeKeys.certificate.toString();
49+
50+
// TODO: change parameters
51+
const hash = crypto.createHash('sha256').update(certificate).digest('hex');
52+
53+
this.nodes[nodeAlias].gossipCaCertificate = certificate;
54+
this.nodes[nodeAlias].grpcCertificateHash = hash;
55+
}))
56+
}
57+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/**
2+
* Copyright (C) 2024 Hedera Hashgraph, LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the ""License"");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an ""AS IS"" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*/
17+
import type {Nullable} from '../../types/aliases.js';
18+
import type {AccountId, Key} from '@hashgraph/sdk';
19+
import type {ServiceEndpoint} from '../../types/index.js';
20+
21+
interface Node {
22+
nodeId: number;
23+
accountId: AccountId | string;
24+
description: string;
25+
gossipEndpoint: Nullable<ServiceEndpoint>;
26+
serviceEndpoint: Nullable<ServiceEndpoint>;
27+
gossipCaCertificate: string; // Bytes
28+
grpcCertificateHash: string; // Bytes
29+
weight: number;
30+
deleted: boolean;
31+
adminKey: Nullable<Key>;
32+
}
33+
34+
export class GenesisNetworkNodeDataWrapper implements Node{
35+
public readonly nodeId: number;
36+
public readonly accountId: AccountId | string;
37+
public readonly description: string;
38+
public gossipEndpoint: ServiceEndpoint;
39+
public serviceEndpoint: ServiceEndpoint;
40+
public gossipCaCertificate: string;
41+
public grpcCertificateHash: string;
42+
public readonly weight: number;
43+
public readonly deleted: boolean;
44+
public adminKey: Nullable<Key>;
45+
46+
constructor (nodeId: number) {
47+
this.nodeId = nodeId;
48+
this.deleted = false;
49+
}
50+
51+
addGossipEndpoint (ipAddressV4: string, port: number, domainName: string): void {
52+
this.gossipEndpoint = {ipAddressV4, port, domainName};
53+
}
54+
55+
addServiceEndpoint (ipAddressV4: string, port: number, domainName: string): void {
56+
this.serviceEndpoint = {ipAddressV4, port, domainName};
57+
}
58+
}

src/core/profile_manager.ts

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import * as helpers from './helpers.js';
3131
import {getNodeAccountMap} from './helpers.js';
3232
import type {SoloLogger} from './logging.js';
3333
import type {NodeAlias, NodeAliases} from '../types/aliases.js';
34+
import {GenesisNetworkDataConstructor} from './models/genesisNetworkDataConstructor.js';
3435

3536
const consensusSidecars = [
3637
'recordStreamUploader',
@@ -100,10 +101,10 @@ export class ProfileManager {
100101
}
101102

102103
/**
103-
* Set value in the yaml object
104+
* Set value in the YAML object
104105
* @param itemPath - item path in the yaml
105106
* @param value - value to be set
106-
* @param yamlRoot - root of the yaml object
107+
* @param yamlRoot - root of the YAML object
107108
* @returns
108109
*/
109110
_setValue(itemPath: string, value: any, yamlRoot: object): object {
@@ -309,14 +310,14 @@ export class ProfileManager {
309310
const nodeAliases = helpers.parseNodeAliases(this.configManager.getFlag(flags.nodeAliasesUnparsed));
310311
if (!nodeAliases) throw new SoloError('Node IDs are not set in the config');
311312

312-
// generate the yaml
313+
// generate the YAML
313314
const yamlRoot = {};
314315
this.resourcesForConsensusPod(profile, nodeAliases, yamlRoot);
315316
this.resourcesForHaProxyPod(profile, yamlRoot);
316317
this.resourcesForEnvoyProxyPod(profile, yamlRoot);
317318
this.resourcesForMinioTenantPod(profile, yamlRoot);
318319

319-
// write the yaml
320+
// write the YAML
320321
const cachedValuesFile = path.join(this.cacheDir, `solo-${profileName}.yaml`);
321322
return new Promise<string>((resolve, reject) => {
322323
fs.writeFile(cachedValuesFile, yaml.stringify(yamlRoot), err => {
@@ -372,11 +373,11 @@ export class ProfileManager {
372373
const profile = this.getProfile(profileName) as any;
373374
if (!profile.rpcRelay) return Promise.resolve(); // use chart defaults
374375

375-
// generate the yaml
376+
// generate the YAML
376377
const yamlRoot = {};
377378
this._setChartItems('', profile.rpcRelay, yamlRoot);
378379

379-
// write the yaml
380+
// write the YAML
380381
const cachedValuesFile = path.join(this.cacheDir, `rpcRelay-${profileName}.yaml`);
381382
return new Promise<string>((resolve, reject) => {
382383
fs.writeFile(cachedValuesFile, yaml.stringify(yamlRoot), err => {
@@ -392,11 +393,11 @@ export class ProfileManager {
392393
prepareValuesHederaExplorerChart(profileName: string) {
393394
if (!profileName) throw new MissingArgumentError('profileName is required');
394395
const profile = this.getProfile(profileName) as any;
395-
// generate the yaml
396+
// generate the YAML
396397
const yamlRoot = {};
397398
this.resourcesForHederaExplorerPod(profile, yamlRoot);
398399

399-
// write the yaml
400+
// write the YAML
400401
const cachedValuesFile = path.join(this.cacheDir, `explorer-${profileName}.yaml`);
401402
return new Promise<string>((resolve, reject) => {
402403
fs.writeFile(cachedValuesFile, yaml.stringify(yamlRoot), err => {
@@ -412,14 +413,14 @@ export class ProfileManager {
412413
/**
413414
* Prepare a values file for mirror-node Helm chart
414415
* @param profileName - resource profile name
415-
* @returns return the full path to the values file
416+
* @returns the full path to the values file
416417
*/
417418
prepareValuesForMirrorNodeChart(profileName: string) {
418419
if (!profileName) throw new MissingArgumentError('profileName is required');
419420
const profile = this.getProfile(profileName) as any;
420421
if (!profile.mirror) return Promise.resolve(); // use chart defaults
421422

422-
// generate the yaml
423+
// generate the YAML
423424
const yamlRoot = {};
424425
if (profile.mirror.postgresql) {
425426
if (profile.mirror.postgresql.persistence) {
@@ -435,7 +436,7 @@ export class ProfileManager {
435436
this._setChartItems('grpc', profile.mirror.grpc, yamlRoot);
436437
this._setChartItems('monitor', profile.mirror.monitor, yamlRoot);
437438

438-
// write the yaml
439+
// write the YAML
439440
const cachedValuesFile = path.join(this.cacheDir, `mirror-${profileName}.yaml`);
440441
return new Promise<string>((resolve, reject) => {
441442
fs.writeFile(cachedValuesFile, yaml.stringify(yamlRoot), err => {
@@ -467,6 +468,7 @@ export class ProfileManager {
467468
* @param releaseTag - release tag e.g. v0.42.0
468469
* @param [appName] - the app name (default: HederaNode.jar)
469470
* @param [chainId] - chain ID (298 for local network)
471+
* @param genesisNetworkData
470472
* @returns the config.txt file path
471473
*/
472474
prepareConfigTxt(
@@ -476,6 +478,7 @@ export class ProfileManager {
476478
releaseTag: string,
477479
appName = constants.HEDERA_APP_NAME,
478480
chainId = constants.HEDERA_CHAIN_ID,
481+
genesisNetworkData: GenesisNetworkDataConstructor
479482
) {
480483
if (!nodeAccountMap || nodeAccountMap.size === 0)
481484
throw new MissingArgumentError('nodeAccountMap the map of node IDs to account IDs is required');
@@ -502,6 +505,9 @@ export class ProfileManager {
502505
const internalIP = Templates.renderFullyQualifiedNetworkPodName(namespace, nodeAlias);
503506
const externalIP = Templates.renderFullyQualifiedNetworkSvcName(namespace, nodeAlias);
504507

508+
genesisNetworkData.nodes[nodeAlias].addGossipEndpoint(externalIP, +externalPort, '');
509+
genesisNetworkData.nodes[nodeAlias].addServiceEndpoint(internalIP, +internalPort, '');
510+
505511
const account = nodeAccountMap.get(nodeAlias);
506512
if (releaseVersion.minor >= 40) {
507513
configLines.push(

src/types/index.ts

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import type * as x509 from '@peculiar/x509';
1818
import type net from 'net';
1919
import type * as WebSocket from 'ws';
2020
import type crypto from 'crypto';
21-
import type {ListrTask} from 'listr2';
21+
import type {ListrTask, ListrTaskWrapper} from 'listr2';
2222

2323
// NOTE: DO NOT add any Solo imports in this file to avoid circular dependencies
2424

@@ -80,3 +80,56 @@ export interface ToObject<T> {
8080
export type SoloListrTask<T> = ListrTask<T, any, any>;
8181

8282
export type EmptyContextConfig = object;
83+
84+
export type SoloListrTaskWrapper<T> = ListrTaskWrapper<T, any, any>
85+
86+
// export interface NodeMetadata {
87+
// rosterEntry: RosterEntry
88+
// node: Node
89+
// tssEncryptionKey: string
90+
// }
91+
92+
// export interface RosterEntry {
93+
// nodeId: number
94+
// weight: number
95+
// gossipCaCertificate: string
96+
// gossipEndpoint: Array<ServiceEndpoint>
97+
// }
98+
99+
export interface ServiceEndpoint {
100+
ipAddressV4: string
101+
port: number
102+
domainName: string
103+
}
104+
105+
// basically what node update does
106+
//
107+
// export interface Node {
108+
// nodeId number ✅
109+
// AccountID accountId ✅
110+
// description string ✅
111+
// gossipEndpoint Array<ServiceEndpoint>
112+
// all of this are in single network, single cluster,
113+
// is going to be fully qualified domain name for
114+
// what we are currently putting as external ( ha proxy endpoint )
115+
// serviceEndpoint: Array<ServiceEndpoint>
116+
// gossipCaCertificate: Bytes - node keys ✅
117+
// grpcCertificateHash: Bytes - kode in node command how to generate it
118+
// weight: number,
119+
// deleted: boolean, ✅
120+
// adminKey: Key ✅
121+
// right now dynamically
122+
// generate it but add it as a secret as
123+
// all other ledger uhh account keys
124+
//
125+
// generate it the same way without genesis, a unique one and store it as a secret, we want to name it a bit differently
126+
// }
127+
128+
// gleda configureNodeAccess
129+
130+
// internal is the network pod name
131+
// external ip is the network service name
132+
// the gossip endpoint is externalIP
133+
134+
// the service endpoint - for the grpc calls, configureNodeAccess
135+

0 commit comments

Comments
 (0)