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

Improvements after review #158

Merged
merged 8 commits into from
Sep 20, 2023
Merged
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: 3 additions & 3 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ import { StakingRouterModule } from '../staking-router-modules';
}),
ScheduleModule.forRoot(),
KeyRegistryModule.forRootAsync({
inject: [SimpleFallbackJsonRpcBatchProvider],
async useFactory(provider) {
return { provider };
inject: [SimpleFallbackJsonRpcBatchProvider, ConfigService],
async useFactory(provider, configService) {
return { provider, keysBatchSize: configService?.get('KEYS_FETCH_BATCH_SIZE') };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why configService is optional?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

another way i get TypeError: Cannot read properties of undefined (reading 'get')
but like this it works, it is possible to set keys batch via this env

},
}),
StakingRouterModule,
Expand Down
6 changes: 6 additions & 0 deletions src/common/config/env.validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
IsBoolean,
ValidateIf,
IsNotEmpty,
IsPositive,
} from 'class-validator';
import { Environment, LogLevel, LogFormat } from './interfaces';
import { NonEmptyArray } from '@lido-nestjs/execution/dist/interfaces/non-empty-array';
Expand Down Expand Up @@ -169,6 +170,11 @@ export class EnvironmentVariables {
@IsOptional()
@IsString()
LIDO_LOCATOR_ADDRESS = '';

@IsOptional()
@IsPositive()
@Transform(({ value }) => parseInt(value, 10))
KEYS_FETCH_BATCH_SIZE = 1100;
}

export function validate(config: Record<string, unknown>) {
Expand Down
3 changes: 3 additions & 0 deletions src/common/registry/fetch/interfaces/module.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ import { ModuleMetadata } from '@nestjs/common';
import { Signer } from 'ethers';
import { Provider } from '@ethersproject/providers';

export const REGISTRY_FETCH_OPTIONS_TOKEN = Symbol('registryFetchOptionsToken');

export interface RegistryFetchOptions {
registryAddress?: string;
lidoAddress?: string;
provider?: Provider | Signer;
keysBatchSize?: number;
}

export interface RegistryFetchModuleSyncOptions extends Pick<ModuleMetadata, 'imports'>, RegistryFetchOptions {}
Expand Down
1 change: 1 addition & 0 deletions src/common/registry/fetch/key-batch.constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
*/
export const KEYS_LENGTH = 96;
export const SIGNATURE_LENGTH = 192;
export const KEYS_BATCH_SIZE = 1100;
7 changes: 4 additions & 3 deletions src/common/registry/fetch/key-batch.fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ import { REGISTRY_CONTRACT_TOKEN, Registry } from '@lido-nestjs/contracts';
import { CallOverrides } from './interfaces/overrides.interface';
import { KeyBatchRecord, RegistryKey } from './interfaces/key.interface';
import { RegistryOperatorFetchService } from './operator.fetch';
import { KEYS_LENGTH, SIGNATURE_LENGTH } from './key-batch.constants';
import { KEYS_BATCH_SIZE, KEYS_LENGTH, SIGNATURE_LENGTH } from './key-batch.constants';
import { RegistryFetchOptions, REGISTRY_FETCH_OPTIONS_TOKEN } from './interfaces/module.interface';

@Injectable()
export class RegistryKeyBatchFetchService {
constructor(
protected readonly operatorsService: RegistryOperatorFetchService,
@Inject(REGISTRY_CONTRACT_TOKEN) private contract: Registry,
@Inject(REGISTRY_FETCH_OPTIONS_TOKEN) private options: RegistryFetchOptions,
) {}

private getContract(moduleAddress: string) {
Expand Down Expand Up @@ -107,8 +109,7 @@ export class RegistryKeyBatchFetchService {
fromIndex: number,
totalAmount: number,
) {
// TODO: move to constants/config cause this limit depends on eth node
const batchSize = 1100;
const batchSize = this.options.keysBatchSize || KEYS_BATCH_SIZE;

const numberOfBatches = Math.ceil(totalAmount / batchSize);
const promises: Promise<RegistryKey[]>[] = [];
Expand Down
8 changes: 3 additions & 5 deletions src/common/registry/fetch/meta.fetch.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { Inject, Injectable } from '@nestjs/common';
// import { Registry__factory } from '@lido-nestjs/contracts';
import { CallOverrides } from './interfaces/overrides.interface';
import { REGISTRY_CONTRACT_TOKEN, Registry } from '@lido-nestjs/contracts';

Expand All @@ -12,10 +11,9 @@ export class RegistryMetaFetchService {
return this.contract.attach(moduleAddress);
}

/** fetches keys operation index */
public async fetchKeysOpIndex(moduleAddress: string, overrides: CallOverrides = {}): Promise<number> {
// TODO: read data from all contract that implement curated-v1-onchain type
const bigNumber = await this.getContract(moduleAddress).getKeysOpIndex(overrides as any);
/** Fetches nonce from staking module contract */
public async fetchStakingModuleNonce(moduleAddress: string, overrides: CallOverrides = {}): Promise<number> {
const bigNumber = await this.getContract(moduleAddress).getNonce(overrides as any);
return bigNumber.toNumber();
}
}
19 changes: 18 additions & 1 deletion src/common/registry/fetch/registry-fetch.module.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { DynamicModule, Module } from '@nestjs/common';
import { LidoContractModule, RegistryContractModule } from '@lido-nestjs/contracts';
import { RegistryFetchModuleSyncOptions, RegistryFetchModuleAsyncOptions } from './interfaces/module.interface';
import {
RegistryFetchModuleSyncOptions,
RegistryFetchModuleAsyncOptions,
REGISTRY_FETCH_OPTIONS_TOKEN,
} from './interfaces/module.interface';
import { RegistryOperatorFetchService } from './operator.fetch';
import { RegistryMetaFetchService } from './meta.fetch';
import { RegistryKeyFetchService } from './key.fetch';
Expand Down Expand Up @@ -52,6 +56,12 @@ export class RegistryFetchModule {
provider: options?.provider,
}),
],
providers: [
{
provide: REGISTRY_FETCH_OPTIONS_TOKEN,
useValue: options?.keysBatchSize ? { keysBatchSize: options.keysBatchSize } : {},
},
],
exports: [LidoContractModule, RegistryContractModule],
};
}
Expand Down Expand Up @@ -80,6 +90,13 @@ export class RegistryFetchModule {
inject: options.inject,
}),
],
providers: [
{
provide: REGISTRY_FETCH_OPTIONS_TOKEN,
useFactory: options.useFactory,
inject: options.inject,
},
],
exports: [LidoContractModule, RegistryContractModule],
};
}
Expand Down
18 changes: 3 additions & 15 deletions src/common/registry/main/abstract-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,6 @@ export abstract class AbstractRegistryService {
// TODO: use feature flag
const result = await this.keyBatchFetch.fetch(moduleAddress, operatorIndex, fromIndex, toIndex, overrides);

// add moduleAddress
const operatorKeys = result.filter((key) => key);

this.logger.log('Keys fetched', {
Expand All @@ -133,12 +132,10 @@ export abstract class AbstractRegistryService {

/** returns the latest operators data from the db */
public async getOperatorsFromStorage(moduleAddress: string) {
// TODO: find for module
return await this.operatorStorage.findAll(moduleAddress);
}

/** returns all the keys from storage */
// the same
public async getOperatorsKeysFromStorage(moduleAddress: string) {
return await this.keyStorage.findAll(moduleAddress);
}
Expand All @@ -161,12 +158,12 @@ export abstract class AbstractRegistryService {

/** contract */
/** returns the meta data from the contract */
public async getNonceFromContract(moduleAddress: string, blockHash: string): Promise<number> {
const keysOpIndex = await this.metaFetch.fetchKeysOpIndex(moduleAddress, { blockTag: { blockHash } });
public async getStakingModuleNonce(moduleAddress: string, blockHash: string): Promise<number> {
const keysOpIndex = await this.metaFetch.fetchStakingModuleNonce(moduleAddress, { blockTag: { blockHash } });
return keysOpIndex;
}

/** saves all the data to the db */
/** saves all data to the db for staking module*/
public async saveOperators(moduleAddress: string, currentOperators: RegistryOperator[]) {
// save all data in a transaction
await this.entityManager.transactional(async (entityManager) => {
Expand All @@ -189,20 +186,11 @@ export abstract class AbstractRegistryService {
await entityManager
.createQueryBuilder(RegistryOperator)
.insert(operatorsChunk)
// TODO: module_address or moduleAddress ?
.onConflict(['index', 'module_address'])
.merge()
.execute();
}),
);
});
}

/** clears the db */
public async clear() {
await this.entityManager.transactional(async (entityManager) => {
entityManager.nativeDelete(RegistryKey, {});
entityManager.nativeDelete(RegistryOperator, {});
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export class KeyRegistryService extends AbstractRegistryService {
return currOperator.totalSigningKeys;
}
/** returns all operators keys from the db */
public async getAllKeysFromStorage(moduleAddress: string) {
public async getModuleKeysFromStorage(moduleAddress: string) {
return await this.keyStorage.findAll(moduleAddress);
}
/** returns used keys from the db */
Expand Down
3 changes: 1 addition & 2 deletions src/common/registry/storage/constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export const KEY_LEN = 98;
export const DEPOSIT_SIGNATURE_LEN = 194;
export const MODULE_ADDRESS_LEN = 42;
export const REWARD_ADDRESS_LEN = 42;
export const ADDRESS_LEN = 42;
4 changes: 2 additions & 2 deletions src/common/registry/storage/key.entity.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Entity, EntityRepositoryType, PrimaryKey, PrimaryKeyType, Property } from '@mikro-orm/core';
import { DEPOSIT_SIGNATURE_LEN, MODULE_ADDRESS_LEN, KEY_LEN } from './constants';
import { DEPOSIT_SIGNATURE_LEN, ADDRESS_LEN, KEY_LEN } from './constants';
import { RegistryKeyRepository } from './key.repository';

@Entity({ customRepository: () => RegistryKeyRepository })
Expand Down Expand Up @@ -32,6 +32,6 @@ export class RegistryKey {
used!: boolean;

@PrimaryKey()
@Property({ length: MODULE_ADDRESS_LEN })
@Property({ length: ADDRESS_LEN })
moduleAddress!: string;
}
6 changes: 3 additions & 3 deletions src/common/registry/storage/operator.entity.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Entity, EntityRepositoryType, PrimaryKey, PrimaryKeyType, Property } from '@mikro-orm/core';
import { MODULE_ADDRESS_LEN, REWARD_ADDRESS_LEN } from './constants';
import { ADDRESS_LEN } from './constants';
import { RegistryOperatorRepository } from './operator.repository';

@Entity({ customRepository: () => RegistryOperatorRepository })
Expand Down Expand Up @@ -28,7 +28,7 @@ export class RegistryOperator {
@Property({ length: 256 })
name!: string;

@Property({ length: REWARD_ADDRESS_LEN })
@Property({ length: ADDRESS_LEN })
rewardAddress!: string;

@Property()
Expand All @@ -44,6 +44,6 @@ export class RegistryOperator {
usedSigningKeys!: number;

@PrimaryKey()
@Property({ length: MODULE_ADDRESS_LEN })
@Property({ length: ADDRESS_LEN })
moduleAddress!: string;
}
2 changes: 1 addition & 1 deletion src/common/registry/test/fetch/meta.fetch.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ describe('Operators', () => {
});

test('fetch keysOpIndex', async () => {
const keysOpIndex = await fetchService.fetchKeysOpIndex(address);
const keysOpIndex = await fetchService.fetchStakingModuleNonce(address);
expect(typeof keysOpIndex).toBe('number');
expect(keysOpIndex).toBeGreaterThan(0);
});
Expand Down
2 changes: 1 addition & 1 deletion src/common/registry/test/fetch/meta.fetch.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ describe('Meta', () => {
const iface = new Interface(Registry__factory.abi);
return iface.encodeFunctionResult('getKeysOpIndex', [expected]);
});
const result = await fetchService.fetchKeysOpIndex(address);
const result = await fetchService.fetchStakingModuleNonce(address);

expect(result).toEqual(expected);
expect(mockCall).toBeCalledTimes(1);
Expand Down
1 change: 0 additions & 1 deletion src/common/registry/test/fetch/operator.fetch.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ describe('Operators', () => {

mockCall.mockImplementation(async () => {
const iface = new Interface(Registry__factory.abi);
// TODO: moduleAddress depends on chain id
operator['moduleAddress'] = address;
return iface.encodeFunctionResult('getNodeOperator', operatorFields(operator));
});
Expand Down
8 changes: 2 additions & 6 deletions src/common/registry/test/key-registry/async.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { getNetwork } from '@ethersproject/networks';
import { getDefaultProvider } from '@ethersproject/providers';
import { KeyRegistryModule, KeyRegistryService, RegistryStorageService } from '../../';
import { MikroORM } from '@mikro-orm/core';
import { mikroORMConfig } from '../testing.utils';

describe('Async module initializing', () => {
const provider = getDefaultProvider('mainnet');
Expand All @@ -26,12 +27,7 @@ describe('Async module initializing', () => {

test('forRootAsync', async () => {
await testModules([
MikroOrmModule.forRoot({
dbName: ':memory:',
type: 'sqlite',
allowGlobalContext: true,
entities: ['./**/*.entity.ts'],
}),
MikroOrmModule.forRoot(mikroORMConfig),
LoggerModule.forRoot({ transports: [nullTransport()] }),
KeyRegistryModule.forRootAsync({
async useFactory() {
Expand Down
18 changes: 7 additions & 11 deletions src/common/registry/test/key-registry/connect.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { BatchProviderModule, ExtendedJsonRpcBatchProvider } from '@lido-nestjs/

import { KeyRegistryModule, KeyRegistryService, RegistryStorageService } from '../../';

import { compareTestMetaOperators } from '../testing.utils';
import { clearDb, compareTestOperators, mikroORMConfig } from '../testing.utils';

import { operators } from '../fixtures/connect.fixture';
import { MikroORM } from '@mikro-orm/core';
Expand All @@ -17,6 +17,7 @@ dotenv.config();
describe('Registry', () => {
let registryService: KeyRegistryService;
let storageService: RegistryStorageService;
let mikroOrm: MikroORM;
if (!process.env.CHAIN_ID) {
console.error("CHAIN_ID wasn't provides");
process.exit(1);
Expand All @@ -28,12 +29,7 @@ describe('Registry', () => {

beforeEach(async () => {
const imports = [
MikroOrmModule.forRoot({
dbName: ':memory:',
type: 'sqlite',
allowGlobalContext: true,
entities: ['./**/*.entity.ts'],
}),
MikroOrmModule.forRoot(mikroORMConfig),
BatchProviderModule.forRoot({
url: process.env.PROVIDERS_URLS as string,
requestPolicy: {
Expand All @@ -53,13 +49,13 @@ describe('Registry', () => {
const moduleRef = await Test.createTestingModule({ imports }).compile();
registryService = moduleRef.get(KeyRegistryService);
storageService = moduleRef.get(RegistryStorageService);

const generator = moduleRef.get(MikroORM).getSchemaGenerator();
mikroOrm = moduleRef.get(MikroORM);
const generator = mikroOrm.getSchemaGenerator();
await generator.updateSchema();
});

afterEach(async () => {
await registryService.clear();
await clearDb(mikroOrm);
await storageService.onModuleDestroy();
});

Expand All @@ -68,7 +64,7 @@ describe('Registry', () => {

await registryService.update(address, blockHash);

await compareTestMetaOperators(address, registryService, {
await compareTestOperators(address, registryService, {
operators: operatorsWithModuleAddress,
});

Expand Down
Loading
Loading