Skip to content

Commit

Permalink
fix: add moduleAddress to operators table, Registry__factory
Browse files Browse the repository at this point in the history
  • Loading branch information
Amuhar committed Jul 25, 2023
1 parent 85a2bbd commit caee531
Show file tree
Hide file tree
Showing 18 changed files with 142 additions and 52 deletions.
1 change: 1 addition & 0 deletions src/common/registry/fetch/interfaces/operator.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ export interface RegistryOperator {
stoppedValidators: number;
totalSigningKeys: number;
usedSigningKeys: number;
moduleAddress: string;
}
21 changes: 14 additions & 7 deletions src/common/registry/fetch/key-batch.fetch.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
import { Inject, Injectable } from '@nestjs/common';
import { Registry, REGISTRY_CONTRACT_TOKEN } from '@lido-nestjs/contracts';
import { Injectable } from '@nestjs/common';
import { Registry__factory } 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 { ExecutionProvider } from 'common/execution-provider';

@Injectable()
export class RegistryKeyBatchFetchService {
constructor(
@Inject(REGISTRY_CONTRACT_TOKEN)
private contract: Registry,

private operatorsService: RegistryOperatorFetchService,
protected readonly provider: ExecutionProvider,
protected readonly operatorsService: RegistryOperatorFetchService,
) {}

private getContract(moduleAddress: string) {
return Registry__factory.connect(moduleAddress, this.provider);
}

/**
* Split one big string into array of strings
* `0x${key1}{key2}...` -> `[`0x${key1}`, `0x${key2}`]`
Expand Down Expand Up @@ -116,7 +119,11 @@ export class RegistryKeyBatchFetchService {
const currentBatchSize = Math.min(batchSize, totalAmount - i * batchSize);

const promise = (async () => {
const keys = await this.contract.getSigningKeys(operatorIndex, currentFromIndex, currentBatchSize);
const keys = await this.getContract(moduleAddress).getSigningKeys(
operatorIndex,
currentFromIndex,
currentBatchSize,
);
return this.formatKeys(operatorIndex, keys, currentFromIndex, moduleAddress);
})();

Expand Down
16 changes: 8 additions & 8 deletions src/common/registry/fetch/key.fetch.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { Inject, Injectable } from '@nestjs/common';
import { Injectable } from '@nestjs/common';
import { rangePromise } from '@lido-nestjs/utils';
import { Registry, REGISTRY_CONTRACT_TOKEN } from '@lido-nestjs/contracts';
import { Registry__factory } from '@lido-nestjs/contracts';
import { CallOverrides } from './interfaces/overrides.interface';
import { RegistryKey } from './interfaces/key.interface';
import { RegistryOperatorFetchService } from './operator.fetch';
import { REGISTRY_KEY_BATCH_SIZE } from './key.constants';
import { ExecutionProvider } from 'common/execution-provider';

@Injectable()
export class RegistryKeyFetchService {
constructor(
@Inject(REGISTRY_CONTRACT_TOKEN)
private contract: Registry,
constructor(protected readonly provider: ExecutionProvider, private operatorsService: RegistryOperatorFetchService) {}

private operatorsService: RegistryOperatorFetchService,
) {}
private getContract(moduleAddress: string) {
return Registry__factory.connect(moduleAddress, this.provider);
}

/** fetches one key */
public async fetchOne(
Expand All @@ -23,7 +23,7 @@ export class RegistryKeyFetchService {
moduleAddress: string,
overrides: CallOverrides = {},
): Promise<RegistryKey> {
const keyData = await this.contract.getSigningKey(operatorIndex, keyIndex, overrides as any);
const keyData = await this.getContract(moduleAddress).getSigningKey(operatorIndex, keyIndex, overrides as any);

const { key, depositSignature, used } = keyData;

Expand Down
15 changes: 10 additions & 5 deletions src/common/registry/fetch/meta.fetch.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { Inject, Injectable } from '@nestjs/common';
import { Registry, REGISTRY_CONTRACT_TOKEN } from '@lido-nestjs/contracts';
import { Injectable } from '@nestjs/common';
import { Registry__factory } from '@lido-nestjs/contracts';
import { CallOverrides } from './interfaces/overrides.interface';
import { ExecutionProvider } from 'common/execution-provider';

@Injectable()
export class RegistryMetaFetchService {
constructor(@Inject(REGISTRY_CONTRACT_TOKEN) private registryContract: Registry) {}
constructor(protected readonly provider: ExecutionProvider) {}

private getContract(moduleAddress: string) {
return Registry__factory.connect(moduleAddress, this.provider);
}

/** fetches keys operation index */
public async fetchKeysOpIndex(overrides: CallOverrides = {}, moduleAddress: string): Promise<number> {
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.registryContract.getKeysOpIndex(overrides as any);
const bigNumber = await this.getContract(moduleAddress).getKeysOpIndex(overrides as any);
return bigNumber.toNumber();
}
}
23 changes: 13 additions & 10 deletions src/common/registry/fetch/operator.fetch.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { Inject, Injectable } from '@nestjs/common';
import { Injectable } from '@nestjs/common';
import { rangePromise } from '@lido-nestjs/utils';
import { Registry, REGISTRY_CONTRACT_TOKEN } from '@lido-nestjs/contracts';
import { Registry__factory } from '@lido-nestjs/contracts';
import { CallOverrides } from './interfaces/overrides.interface';
import { RegistryOperator } from './interfaces/operator.interface';
import { REGISTRY_OPERATORS_BATCH_SIZE } from './operator.constants';
import { ExecutionProvider } from 'common/execution-provider';

@Injectable()
export class RegistryOperatorFetchService {
constructor(
@Inject(REGISTRY_CONTRACT_TOKEN)
private contract: Registry,
) {}
constructor(protected readonly provider: ExecutionProvider) {}

private getContract(moduleAddress: string) {
return Registry__factory.connect(moduleAddress, this.provider);
}

/** fetches number of operators */
public async count(overrides: CallOverrides = {}): Promise<number> {
const bigNumber = await this.contract.getNodeOperatorsCount(overrides as any);
public async count(moduleAddress: string, overrides: CallOverrides = {}): Promise<number> {
const bigNumber = await this.getContract(moduleAddress).getNodeOperatorsCount(overrides as any);
return bigNumber.toNumber();
}

Expand All @@ -26,7 +28,7 @@ export class RegistryOperatorFetchService {
overrides: CallOverrides = {},
): Promise<RegistryOperator> {
const fullInfo = true;
const operator = await this.contract.getNodeOperator(operatorIndex, fullInfo, overrides as any);
const operator = await this.getContract(moduleAddress).getNodeOperator(operatorIndex, fullInfo, overrides as any);

const {
name,
Expand All @@ -47,6 +49,7 @@ export class RegistryOperatorFetchService {
stoppedValidators: totalExitedValidators.toNumber(),
totalSigningKeys: totalAddedValidators.toNumber(),
usedSigningKeys: totalDepositedValidators.toNumber(),
moduleAddress,
};
}

Expand All @@ -62,7 +65,7 @@ export class RegistryOperatorFetchService {
}

if (toIndex == null || toIndex === -1) {
toIndex = await this.count(overrides);
toIndex = await this.count(moduleAddress, overrides);
}

const fetcher = async (operatorIndex: number) => {
Expand Down
2 changes: 1 addition & 1 deletion src/common/registry/main/abstract-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ export abstract class AbstractRegistryService {
const blockHash = block.hash;
const blockTag = { blockHash };

const keysOpIndex = await this.metaFetch.fetchKeysOpIndex({ blockTag }, moduleAddress);
const keysOpIndex = await this.metaFetch.fetchKeysOpIndex(moduleAddress, { blockTag });

return {
blockNumber: block.number,
Expand Down
4 changes: 4 additions & 0 deletions src/common/registry/storage/operator.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export class RegistryOperator {
this.stoppedValidators = operator.stoppedValidators;
this.totalSigningKeys = operator.totalSigningKeys;
this.usedSigningKeys = operator.usedSigningKeys;
this.moduleAddress = operator.moduleAddress;
}

@PrimaryKey()
Expand All @@ -39,4 +40,7 @@ export class RegistryOperator {

@Property()
usedSigningKeys!: number;

@Property({ length: 42 })
moduleAddress!: string;
}
4 changes: 2 additions & 2 deletions src/http/common/entities/sr-module.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { ApiProperty } from '@nestjs/swagger';
import { SRModuleEntity } from 'storage/sr-module.entity';
import { SrModuleEntity } from 'storage/sr-module.entity';

export class SRModule {
constructor(nonce: number, module: SRModuleEntity) {
constructor(nonce: number, module: SrModuleEntity) {
this.nonce = nonce;
this.type = module.type;
this.id = module.id;
Expand Down
11 changes: 11 additions & 0 deletions src/migrations/Migration20230724202500.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Migration } from '@mikro-orm/migrations';

export class Migration20230724202500 extends Migration {
async up(): Promise<void> {
this.addSql('alter table "registry_operator" add column "module_address" varchar(42) null;');
}

async down(): Promise<void> {
this.addSql('alter table "registry_operator" drop column "module_address";');
}
}
31 changes: 31 additions & 0 deletions src/migrations/Migration20230724204141.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Migration } from '@mikro-orm/migrations';

export class Migration20230724204141 extends Migration {
public async up(): Promise<void> {
if (process.env.CHAIN_ID == '1') {
this.addSql("UPDATE registry_operator SET module_address = '0x55032650b14df07b85bF18A3a3eC8E0Af2e028d5'");
return;
}

if (process.env.CHAIN_ID == '5') {
this.addSql("UPDATE registry_operator SET module_address = '0x9D4AF1Ee19Dad8857db3a45B0374c81c8A1C6320'");
return;
}

//TODO: will have problem on new testnet for example
// maybe better instead of this migration truncate values in db but than update will take more time for holders
// I prefer second way

throw new Error('CHAIN_ID is wrong, it should be 1 or 5');
}

public async down(): Promise<void> {
if (process.env.CHAIN_ID === '1') {
this.addSql('UPDATE registry_operator SET module_address = NULL');
} else if (process.env.CHAIN_ID === '5') {
this.addSql('UPDATE registry_operator SET module_address = NULL');
} else {
throw new Error('CHAIN_ID is wrong, it should be 1 or 5');
}
}
}
17 changes: 17 additions & 0 deletions src/migrations/Migration20230724205529.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Migration } from '@mikro-orm/migrations';

export class Migration20230724205529 extends Migration {
async up(): Promise<void> {
this.addSql(
'alter table "registry_operator" alter column "module_address" type varchar(42) using ("module_address"::varchar(42));',
);
this.addSql('alter table "registry_operator" alter column "module_address" set not null;');
}

async down(): Promise<void> {
this.addSql(
'alter table "registry_operator" alter column "module_address" type varchar using ("module_address"::varchar);',
);
this.addSql('alter table "registry_operator" alter column "module_address" drop not null;');
}
}
11 changes: 11 additions & 0 deletions src/migrations/Migration20230724210022.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Migration } from '@mikro-orm/migrations';

export class Migration20230724210022 extends Migration {
public async up(): Promise<void> {
this.addSql('ALTER TABLE "srmodule_entity" RENAME TO "sr_module_entity"');
}

public async down(): Promise<void> {
this.addSql('ALTER TABLE "sr_module_entity" RENAME TO "srmodule_entity"');
}
}
4 changes: 2 additions & 2 deletions src/mikro-orm.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { RegistryMeta, RegistryOperator, RegistryKey } from './common/registry';
import { ConsensusMetaEntity } from '@lido-nestjs/validators-registry';
import { ConsensusValidatorEntity } from '@lido-nestjs/validators-registry';
import { readFileSync } from 'fs';
import { SRModuleEntity } from './storage/sr-module.entity';
import { SrModuleEntity } from './storage/sr-module.entity';
import { ElMetaEntity } from './storage/el-meta.entity';

dotenv.config();
Expand Down Expand Up @@ -123,7 +123,7 @@ const config: Options = {
RegistryMeta,
ConsensusValidatorEntity,
ConsensusMetaEntity,
SRModuleEntity,
SrModuleEntity,
ElMetaEntity,
],
migrations: getMigrationOptions(path.join(__dirname, 'migrations'), ['@lido-nestjs/validators-registry']),
Expand Down
8 changes: 4 additions & 4 deletions src/staking-router-modules/staking-router.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { KeyWithModuleAddress } from 'http/keys/entities';
import { ELBlockSnapshot, ModuleId } from 'http/common/entities';
import { config } from './staking-module-impl-config';
import { IsolationLevel } from '@mikro-orm/core';
import { SRModuleEntity } from 'storage/sr-module.entity';
import { SrModuleEntity } from 'storage/sr-module.entity';
import { SRModuleStorageService } from 'storage/sr-module.storage';
import { ElMetaStorageService } from 'storage/el-meta.storage';
import { ElMetaEntity } from 'storage/el-meta.entity';
Expand All @@ -29,12 +29,12 @@ export class StakingRouterService {
) {}

// modules list is used in endpoints
public async getStakingModules(): Promise<SRModuleEntity[]> {
public async getStakingModules(): Promise<SrModuleEntity[]> {
const srModules = await this.srModulesStorage.findAll();
return srModules;
}

public async getStakingModule(moduleId: ModuleId): Promise<SRModuleEntity | null> {
public async getStakingModule(moduleId: ModuleId): Promise<SrModuleEntity | null> {
// TODO: here should be more checks
if (typeof moduleId === 'number') {
return await this.srModulesStorage.findOneById(moduleId);
Expand Down Expand Up @@ -89,7 +89,7 @@ export class StakingRouterService {
// return;
// }

// TODO: move to SRModuleEntity storage module
// TODO: move to SrModuleEntity storage module
await this.srModulesStorage.store(module, currNonce);
// here we already sure that we need to update keys and operators
// TODO: next step is removing meta and nonce checking from updateKeys algo in registry implementation
Expand Down
2 changes: 1 addition & 1 deletion src/storage/sr-module.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { StakingModule } from '../staking-router-modules/interfaces';
import { SRModuleRepository } from './sr-module.repository';

@Entity({ customRepository: () => SRModuleRepository })
export class SRModuleEntity {
export class SrModuleEntity {
[EntityRepositoryType]?: SRModuleRepository;
[PrimaryKeyType]?: [number, string];

Expand Down
4 changes: 2 additions & 2 deletions src/storage/sr-module.repository.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { EntityRepository } from '@mikro-orm/knex';
import { SRModuleEntity } from './sr-module.entity';
import { SrModuleEntity } from './sr-module.entity';

export class SRModuleRepository extends EntityRepository<SRModuleEntity> {}
export class SRModuleRepository extends EntityRepository<SrModuleEntity> {}
16 changes: 8 additions & 8 deletions src/storage/sr-module.storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { QueryOrder } from '@mikro-orm/core';
import { FilterQuery, FindOptions } from '@mikro-orm/core';
import { Injectable } from '@nestjs/common';
import { StakingModule } from 'staking-router-modules/interfaces';
import { SRModuleEntity } from './sr-module.entity';
import { SrModuleEntity } from './sr-module.entity';
import { SRModuleRepository } from './sr-module.repository';

@Injectable()
Expand All @@ -11,30 +11,30 @@ export class SRModuleStorageService {

/** find module */
async find<P extends string = never>(
where: FilterQuery<SRModuleEntity>,
options?: FindOptions<SRModuleEntity, P>,
): Promise<SRModuleEntity[]> {
where: FilterQuery<SrModuleEntity>,
options?: FindOptions<SrModuleEntity, P>,
): Promise<SrModuleEntity[]> {
return await this.repository.find(where, options);
}

/** find key by index */
async findOneById(moduleId: number): Promise<SRModuleEntity | null> {
async findOneById(moduleId: number): Promise<SrModuleEntity | null> {
return await this.repository.findOne({ id: moduleId });
}

async findOneByContractAddress(contractAddress: string): Promise<SRModuleEntity | null> {
async findOneByContractAddress(contractAddress: string): Promise<SrModuleEntity | null> {
return await this.repository.findOne({ stakingModuleAddress: contractAddress });
}

/** find all keys */
async findAll(): Promise<SRModuleEntity[]> {
async findAll(): Promise<SrModuleEntity[]> {
return await this.repository.findAll({
orderBy: [{ id: QueryOrder.ASC }],
});
}

async store(module: StakingModule, currNonce: number): Promise<void> {
const srModule = new SRModuleEntity(module, currNonce);
const srModule = new SrModuleEntity(module, currNonce);
// TODO: what exactly will happen during attempt to write in db module that already exists in db
await this.repository
.createQueryBuilder()
Expand Down
Loading

0 comments on commit caee531

Please sign in to comment.