@hashgraph/solo
Version:
An opinionated CLI tool to deploy and manage private Hedera Networks.
143 lines (121 loc) • 5.99 kB
text/typescript
// SPDX-License-Identifier: Apache-2.0
import {Templates} from './templates.js';
import {type PriorityMapping, type ToJSON} from '../types/index.js';
import * as constants from './constants.js';
import {type BlockNodeStateSchema} from '../data/schema/model/remote/state/block-node-state-schema.js';
import {type ClusterSchema} from '../data/schema/model/common/cluster-schema.js';
import * as versions from '../../version.js';
import {inject} from 'tsyringe-neo';
import {InjectTokens} from './dependency-injection/inject-tokens.js';
import {patchInject} from './dependency-injection/container-helper.js';
import {type RemoteConfigRuntimeStateApi} from '../business/runtime-state/api/remote-config-runtime-state-api.js';
import {ExternalBlockNodeStateSchema} from '../data/schema/model/remote/state/external-block-node-state-schema.js';
import {type ConfigProvider} from '../data/configuration/api/config-provider.js';
import {SoloConfigSchema} from '../data/schema/model/solo/solo-config-schema.js';
import {SoloConfig} from '../business/runtime-state/config/solo/solo-config.js';
type BlockNodeConnectionDataBase = {
messageSizeSoftLimitBytes?: number;
messageSizeHardLimitBytes?: number;
};
type BlockNodeConnectionData =
| ({
address: string;
port: number;
priority: number;
} & BlockNodeConnectionDataBase)
| ({
address: string;
streamingPort: number;
servicePort: number;
priority: number;
} & BlockNodeConnectionDataBase);
interface BlockNodesJsonStructure {
nodes: BlockNodeConnectionData[];
blockItemBatchSize: number;
}
/**
* Wrapper used to generate `block-nodes.json` file
* for the consensus node used to configure block node connections.
*/
export class BlockNodesJsonWrapper implements ToJSON {
private readonly remoteConfig: RemoteConfigRuntimeStateApi;
private readonly configProvider: ConfigProvider;
private readonly blockNodes: BlockNodeStateSchema[];
private readonly externalBlockNodes: ExternalBlockNodeStateSchema[];
private readonly tssEnabled: boolean;
public constructor(
private readonly blockNodeMap: PriorityMapping[],
private readonly externalBlockNodeMap: PriorityMapping[],
(InjectTokens.RemoteConfigRuntimeState) remoteConfig?: RemoteConfigRuntimeStateApi,
(InjectTokens.ConfigProvider) configProvider?: ConfigProvider,
) {
this.remoteConfig = patchInject(remoteConfig, InjectTokens.RemoteConfigRuntimeState, this.constructor.name);
this.configProvider = patchInject(configProvider, InjectTokens.ConfigProvider, this.constructor.name);
this.blockNodes = this.remoteConfig.configuration.state.blockNodes;
this.externalBlockNodes = this.remoteConfig.configuration.state.externalBlockNodes;
this.tssEnabled = this.remoteConfig.configuration.state.tssEnabled ?? false;
}
public toJSON(): string {
return JSON.stringify(this.buildBlockNodesJsonStructure());
}
private buildBlockNodesJsonStructure(): BlockNodesJsonStructure {
// Figure out field name for port
const useLegacyPortName: boolean = this.remoteConfig.configuration.versions.consensusNode.lessThan(
versions.MINIMUM_HIERO_CONSENSUS_NODE_VERSION_FOR_LEGACY_PORT_NAME_FOR_BLOCK_NODES_JSON_FILE,
);
const blockNodeConnectionData: BlockNodeConnectionData[] = [];
for (const [id, priority] of this.blockNodeMap) {
const blockNodeComponent: BlockNodeStateSchema = this.blockNodes.find(
(component): boolean => component.metadata.id === id,
);
const cluster: ClusterSchema = this.remoteConfig.configuration.clusters.find(
(cluster): boolean => cluster.name === blockNodeComponent.metadata.cluster,
);
const address: string = Templates.renderSvcFullyQualifiedDomainName(
Templates.renderBlockNodeName(blockNodeComponent.metadata.id),
blockNodeComponent.metadata.namespace,
cluster.dnsBaseDomain,
);
// Figure out the block node port
const useLegacyPort: boolean = this.remoteConfig.configuration.versions.blockNodeChart.lessThan(
versions.MINIMUM_HIERO_BLOCK_NODE_VERSION_FOR_NEW_LIVENESS_CHECK_PORT,
);
const port: number = useLegacyPort ? constants.BLOCK_NODE_PORT_LEGACY : constants.BLOCK_NODE_PORT;
const soloConfig: SoloConfig = new SoloConfig(this.configProvider.config().asObject(SoloConfigSchema));
const tssMessageSizeFields: BlockNodeConnectionDataBase = this.tssEnabled
? {
messageSizeSoftLimitBytes: soloConfig.tss.messageSizeSoftLimitBytes,
messageSizeHardLimitBytes: soloConfig.tss.messageSizeHardLimitBytes,
}
: {};
blockNodeConnectionData.push(
useLegacyPortName
? {address, port, priority, ...tssMessageSizeFields}
: {address, streamingPort: port, servicePort: port, priority, ...tssMessageSizeFields},
);
}
for (const [id, priority] of this.externalBlockNodeMap) {
const blockNodeComponent: ExternalBlockNodeStateSchema = this.externalBlockNodes.find(
(component): boolean => component.id === id,
);
const address: string = blockNodeComponent.address;
const port: number = blockNodeComponent.port;
const soloConfig: SoloConfig = new SoloConfig(this.configProvider.config().asObject(SoloConfigSchema));
const tssMessageSizeFields: BlockNodeConnectionDataBase = this.tssEnabled
? {
messageSizeSoftLimitBytes: soloConfig.tss.messageSizeSoftLimitBytes,
messageSizeHardLimitBytes: soloConfig.tss.messageSizeHardLimitBytes,
}
: {};
blockNodeConnectionData.push(
useLegacyPortName
? {address, port, priority, ...tssMessageSizeFields}
: {address, streamingPort: port, servicePort: port, priority, ...tssMessageSizeFields},
);
}
return {
nodes: blockNodeConnectionData,
blockItemBatchSize: constants.BLOCK_ITEM_BATCH_SIZE,
};
}
}