Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: sanity checker for network config #279

Open
wants to merge 15 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ jobs:
run: yarn lint
- name: Run tests
run: yarn test
env:
DB_NAME: node_operator_keys_service_db
DB_PORT: 5432
DB_HOST: localhost
DB_USER: postgres
DB_PASSWORD: postgres
- name: Run E2E tests
run: yarn test:e2e
env:
Expand Down
22 changes: 1 addition & 21 deletions src/app/app.service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Inject, Injectable, LoggerService, OnModuleInit } from '@nestjs/common';
import { LOGGER_PROVIDER } from '@lido-nestjs/logger';
import { ExecutionProviderService } from '../common/execution-provider';
import { ConsensusProviderService } from '../common/consensus-provider';
import { ConfigService } from '../common/config';
import { PrometheusService } from '../common/prometheus';
import { APP_NAME, APP_VERSION } from './app.constants';
Expand All @@ -11,35 +10,16 @@ export class AppService implements OnModuleInit {
constructor(
@Inject(LOGGER_PROVIDER) protected readonly logger: LoggerService,
protected readonly executionProviderService: ExecutionProviderService,
protected readonly consensusProviderService: ConsensusProviderService,
protected readonly configService: ConfigService,
protected readonly prometheusService: PrometheusService,
) {}

public async onModuleInit(): Promise<void> {
if (this.configService.get('VALIDATOR_REGISTRY_ENABLE')) {
await this.validateNetwork();
}

const env = this.configService.get('NODE_ENV');
const version = APP_VERSION;
const name = APP_NAME;
const network = await this.executionProviderService.getNetworkName();
this.prometheusService.buildInfo.labels({ env, name, version, network }).inc();
this.logger.log('Init app', { env, name, version });
}

/**
* Validates the CL and EL chains match
*/
protected async validateNetwork(): Promise<void> {
const chainId = this.configService.get('CHAIN_ID');
const depositContract = await this.consensusProviderService.getDepositContract();
const elChainId = await this.executionProviderService.getChainId();
const clChainId = Number(depositContract.data?.chain_id);

if (chainId !== elChainId || elChainId !== clChainId) {
throw new Error('Execution and consensus chain ids do not match');
}
this.logger.log('Init app', { env, name, version, network });
}
}
3 changes: 2 additions & 1 deletion src/jobs/jobs.module.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { Module } from '@nestjs/common';
import { JobsService } from './jobs.service';
import { NetworkValidationModule } from '../network-validation';
import { KeysUpdateModule } from './keys-update/keys-update.module';
import { ValidatorsUpdateModule } from './validators-update/validators-update.module';

@Module({
imports: [KeysUpdateModule, ValidatorsUpdateModule],
imports: [NetworkValidationModule, KeysUpdateModule, ValidatorsUpdateModule],
providers: [JobsService],
})
export class JobsModule {}
6 changes: 6 additions & 0 deletions src/jobs/jobs.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Inject, Injectable, OnModuleDestroy, OnModuleInit } from '@nestjs/common';
import { LOGGER_PROVIDER, LoggerService } from 'common/logger';
import { NetworkValidationService } from '../network-validation';
import { ValidatorsUpdateService } from './validators-update/validators-update.service';
import { KeysUpdateService } from './keys-update';
import { SchedulerRegistry } from '@nestjs/schedule';
Expand All @@ -9,13 +10,18 @@ import { PrometheusService } from 'common/prometheus';
export class JobsService implements OnModuleInit, OnModuleDestroy {
constructor(
@Inject(LOGGER_PROVIDER) protected readonly logger: LoggerService,
protected readonly networkValidationService: NetworkValidationService,
protected readonly keysUpdateService: KeysUpdateService,
protected readonly validatorUpdateService: ValidatorsUpdateService,
protected readonly schedulerRegistry: SchedulerRegistry,
protected readonly prometheusService: PrometheusService,
) {}

public async onModuleInit(): Promise<void> {
this.logger.log('Started network config and DB validation');
await this.networkValidationService.validate();
this.logger.log('Finished network config and DB validation');

// Do not wait for initialization to avoid blocking the main process
this.initialize().catch((err) => this.logger.error(err));
}
Expand Down
2 changes: 1 addition & 1 deletion src/jobs/keys-update/staking-module-updater.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export class StakingModuleUpdaterService {
// Read current nonce from contract
const currNonce = await moduleInstance.getCurrentNonce(stakingModuleAddress, currentBlockHash);
// Read module in storage
const moduleInStorage = await this.srModulesStorage.findOneById(contractModule.moduleId);
const moduleInStorage = await this.srModulesStorage.findOneByModuleId(contractModule.moduleId);
const prevNonce = moduleInStorage?.nonce;

this.logger.log(`Nonce previous value: ${prevNonce}, nonce current value: ${currNonce}`);
Expand Down
2 changes: 1 addition & 1 deletion src/jobs/keys-update/test/detect-reorg.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ describe('detect reorg', () => {
{
provide: SRModuleStorageService,
useValue: {
findOneById: jest.fn(),
findOneByModuleId: jest.fn(),
upsert: jest.fn(),
},
},
Expand Down
12 changes: 6 additions & 6 deletions src/jobs/keys-update/test/update-cases.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { UpdaterState } from '../keys-update.interfaces';
describe('update cases', () => {
let updaterService: StakingModuleUpdaterService;
let stakingRouterService: StakingRouterService;
let sRModuleStorageService: SRModuleStorageService;
let srModuleStorageService: SRModuleStorageService;
let elMetaStorageService: ElMetaStorageService;
let loggerService: { log: jest.Mock<any, any> };
let executionProviderService: ExecutionProviderService;
Expand Down Expand Up @@ -50,7 +50,7 @@ describe('update cases', () => {
{
provide: SRModuleStorageService,
useValue: {
findOneById: jest.fn(),
findOneByModuleId: jest.fn(),
upsert: jest.fn(),
},
},
Expand All @@ -60,7 +60,7 @@ describe('update cases', () => {

updaterService = module.get<StakingModuleUpdaterService>(StakingModuleUpdaterService);
stakingRouterService = module.get<StakingRouterService>(StakingRouterService);
sRModuleStorageService = module.get<SRModuleStorageService>(SRModuleStorageService);
srModuleStorageService = module.get<SRModuleStorageService>(SRModuleStorageService);
executionProviderService = module.get<ExecutionProviderService>(ExecutionProviderService);
elMetaStorageService = module.get<ElMetaStorageService>(ElMetaStorageService);
loggerService = module.get(LOGGER_PROVIDER);
Expand Down Expand Up @@ -126,7 +126,7 @@ describe('update cases', () => {
} as any),
);

jest.spyOn(sRModuleStorageService, 'findOneById').mockImplementation(
jest.spyOn(srModuleStorageService, 'findOneByModuleId').mockImplementation(
() =>
({
nonce: 0,
Expand All @@ -153,7 +153,7 @@ describe('update cases', () => {
updaterState.lastChangedBlockHash = currBh;
});
const mockElUpdate = jest.spyOn(elMetaStorageService, 'update').mockImplementation();
jest.spyOn(sRModuleStorageService, 'findOneById').mockImplementation(
jest.spyOn(srModuleStorageService, 'findOneByModuleId').mockImplementation(
() =>
({
nonce: 1,
Expand All @@ -179,7 +179,7 @@ describe('update cases', () => {
updaterState.lastChangedBlockHash = currBh;
});
const mockElUpdate = jest.spyOn(elMetaStorageService, 'update').mockImplementation();
jest.spyOn(sRModuleStorageService, 'findOneById').mockImplementation(
jest.spyOn(srModuleStorageService, 'findOneByModuleId').mockImplementation(
() =>
({
nonce: 1,
Expand Down
16 changes: 16 additions & 0 deletions src/migrations/Migration20240427195401.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Migration } from '@mikro-orm/migrations';

export class Migration20240427195401 extends Migration {
async up(): Promise<void> {
this.addSql(
'create table "app_info_entity" ("chain_id" serial primary key, "locator_address" varchar(42) not null);',
);
this.addSql(
'alter table "app_info_entity" add constraint "app_info_entity_locator_address_unique" unique ("locator_address");',
);
}

async down(): Promise<void> {
this.addSql('drop table if exists "app_info_entity" cascade;');
}
}
2 changes: 2 additions & 0 deletions src/mikro-orm.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { ConsensusValidatorEntity } from '@lido-nestjs/validators-registry';
import { readFileSync } from 'fs';
import { SrModuleEntity } from './storage/sr-module.entity';
import { ElMetaEntity } from './storage/el-meta.entity';
import { AppInfoEntity } from './storage/app-info.entity';
import { Logger } from '@nestjs/common';

dotenv.config();
Expand Down Expand Up @@ -126,6 +127,7 @@ const config: Options = {
ConsensusMetaEntity,
SrModuleEntity,
ElMetaEntity,
AppInfoEntity,
],
migrations: getMigrationOptions(path.join(__dirname, 'migrations'), ['@lido-nestjs/validators-registry']),
};
Expand Down
2 changes: 2 additions & 0 deletions src/network-validation/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './network-validation.module';
export * from './network-validation.service';
8 changes: 8 additions & 0 deletions src/network-validation/network-validation.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Module } from '@nestjs/common';
import { NetworkValidationService } from './network-validation.service';

@Module({
providers: [NetworkValidationService],
exports: [NetworkValidationService],
})
export class NetworkValidationModule {}
Loading
Loading