Skip to content

Commit

Permalink
Merge pull request #235 from lidofinance/develop
Browse files Browse the repository at this point in the history
dev to main
  • Loading branch information
infloop committed Jan 18, 2024
2 parents d2be1a1 + 92538d3 commit d29a291
Show file tree
Hide file tree
Showing 49 changed files with 1,213 additions and 234 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "lido-keys-api",
"version": "0.10.1",
"version": "0.10.2",
"description": "Lido Node Operators keys service",
"author": "Lido team",
"private": true,
Expand Down Expand Up @@ -51,6 +51,7 @@
"@lido-nestjs/execution": "^1.11.0",
"@lido-nestjs/fetch": "^1.4.0",
"@lido-nestjs/logger": "^1.3.2",
"@lido-nestjs/middleware": "^1.2.0",
"@lido-nestjs/validators-registry": "^1.3.0",
"@mikro-orm/cli": "^5.5.3",
"@mikro-orm/core": "^5.5.3",
Expand Down
8 changes: 4 additions & 4 deletions src/app/simple-dvt-deploy.e2e-chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { RegistryKeyStorageService } from '../common/registry';
import { ElMetaStorageService } from '../storage/el-meta.storage';
import { SRModuleStorageService } from '../storage/sr-module.storage';
import { KeysUpdateService } from '../jobs/keys-update';
import { ExecutionProvider, ExecutionProviderService } from '../common/execution-provider';
import { ExecutionProvider } from '../common/execution-provider';
import { ConfigService } from '../common/config';
import { PrometheusService } from '../common/prometheus';
import { StakingRouterService } from '../staking-router-modules/staking-router.service';
Expand Down Expand Up @@ -64,8 +64,6 @@ describe('Simple DVT deploy', () => {
});

moduleRef = await Test.createTestingModule({ imports: [AppModule] })
.overrideProvider(ExecutionProviderService)
.useValue(session.provider)
.overrideProvider(SimpleFallbackJsonRpcBatchProvider)
.useValue(session.provider)
.overrideProvider(ExecutionProvider)
Expand All @@ -89,7 +87,9 @@ describe('Simple DVT deploy', () => {
.overrideProvider(ConfigService)
.useValue({
get(path) {
const conf = { LIDO_LOCATOR_ADDRESS: '0xC1d0b3DE6792Bf6b4b37EccdcC24e45978Cfd2Eb' };
const conf = {
LIDO_LOCATOR_ADDRESS: '0xC1d0b3DE6792Bf6b4b37EccdcC24e45978Cfd2Eb',
};
return conf[path];
},
})
Expand Down
9 changes: 9 additions & 0 deletions src/common/execution-provider/execution-provider.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,13 @@ export class ExecutionProviderService {
const block = await this.provider.getBlock(blockHashOrBlockTag);
return { number: block.number, hash: block.hash, timestamp: block.timestamp };
}

/**
*
* Returns full block info
*/
public async getFullBlock(blockHashOrBlockTag: number | string) {
const block = await this.provider.getBlock(blockHashOrBlockTag);
return block;
}
}
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 @@ -8,4 +8,5 @@ export interface RegistryOperator {
totalSigningKeys: number;
usedSigningKeys: number;
moduleAddress: string;
finalizedUsedSigningKeys: number;
}
25 changes: 24 additions & 1 deletion src/common/registry/fetch/operator.fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,20 +59,37 @@ export class RegistryOperatorFetchService {
return false;
}

/** return blockTag for finalized block, it need for testing purposes */
public getFinalizedBlockTag() {
return 'finalized';
}

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

/** fetches finalized operator */
public async getFinalizedNodeOperator(moduleAddress: string, operatorIndex: number) {
const fullInfo = true;
const contract = this.getContract(moduleAddress);
const finalizedOperator = await contract.getNodeOperator(operatorIndex, fullInfo, {
blockTag: this.getFinalizedBlockTag(),
});
return finalizedOperator;
}

/** fetches one operator */
public async fetchOne(
moduleAddress: string,
operatorIndex: number,
overrides: CallOverrides = {},
): Promise<RegistryOperator> {
const fullInfo = true;
const operator = await this.getContract(moduleAddress).getNodeOperator(operatorIndex, fullInfo, overrides as any);
const contract = this.getContract(moduleAddress);

const operator = await contract.getNodeOperator(operatorIndex, fullInfo, overrides as any);

const {
name,
Expand All @@ -84,6 +101,11 @@ export class RegistryOperatorFetchService {
totalDepositedValidators,
} = operator;

const { totalDepositedValidators: finalizedUsedSigningKeys } = await this.getFinalizedNodeOperator(
moduleAddress,
operatorIndex,
);

return {
index: operatorIndex,
active,
Expand All @@ -94,6 +116,7 @@ export class RegistryOperatorFetchService {
totalSigningKeys: totalAddedValidators.toNumber(),
usedSigningKeys: totalDepositedValidators.toNumber(),
moduleAddress,
finalizedUsedSigningKeys: finalizedUsedSigningKeys.toNumber(),
};
}

Expand Down
7 changes: 3 additions & 4 deletions src/common/registry/main/abstract-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,10 @@ export abstract class AbstractRegistryService {
const prevOperator = previousOperators[currentIndex] ?? null;
const isSameOperator = compareOperators(prevOperator, currOperator);

const finalizedUsedSigningKeys = prevOperator ? prevOperator.finalizedUsedSigningKeys : null;
// skip updating keys from 0 to `usedSigningKeys` of previous collected data
// since the contract guarantees that these keys cannot be changed
const unchangedKeysMaxIndex = isSameOperator ? prevOperator.usedSigningKeys : 0;
const unchangedKeysMaxIndex = isSameOperator && finalizedUsedSigningKeys ? finalizedUsedSigningKeys : 0;
// get the right border up to which the keys should be updated
// it's different for different scenarios
const toIndex = this.getToIndex(currOperator);
Expand All @@ -121,7 +122,7 @@ export abstract class AbstractRegistryService {

const operatorIndex = currOperator.index;
const overrides = { blockTag: { blockHash } };
// TODO: use feature flag

const result = await this.keyBatchFetch.fetch(moduleAddress, operatorIndex, fromIndex, toIndex, overrides);

const operatorKeys = result.filter((key) => key);
Expand All @@ -138,8 +139,6 @@ export abstract class AbstractRegistryService {

this.logger.log('Keys saved', { operatorIndex });
}

console.timeEnd('FETCH_OPERATORS');
}

/** storage */
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 @@ -17,6 +17,7 @@ export class RegistryOperator {
this.totalSigningKeys = operator.totalSigningKeys;
this.usedSigningKeys = operator.usedSigningKeys;
this.moduleAddress = operator.moduleAddress;
this.finalizedUsedSigningKeys = operator.finalizedUsedSigningKeys;
}

@PrimaryKey()
Expand Down Expand Up @@ -46,4 +47,7 @@ export class RegistryOperator {
@PrimaryKey()
@Property({ length: ADDRESS_LEN })
moduleAddress!: string;

@Property()
finalizedUsedSigningKeys!: number;
}
28 changes: 27 additions & 1 deletion src/common/registry/test/fetch/key.fetch.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,33 @@ describe('Keys', () => {
const result = await fetchService.fetch(address, expected.operatorIndex);

expect(result).toEqual([expected]);
expect(mockCall).toBeCalledTimes(2);
expect(mockCall).toBeCalledTimes(3);
});

test('fetch all operator keys with reorg', async () => {
const expected = { operatorIndex: 1, index: 0, moduleAddress: address, ...key };

mockCall
.mockImplementationOnce(async () => {
const iface = new Interface(Registry__factory.abi);
return iface.encodeFunctionResult(
'getNodeOperator',
operatorFields({
...operator,
moduleAddress: address,
totalSigningKeys: 1,
usedSigningKeys: 2,
finalizedUsedSigningKeys: 1,
}),
);
})
.mockImplementation(async () => {
const iface = new Interface(Registry__factory.abi);
return iface.encodeFunctionResult('getSigningKey', keyFields);
});
const result = await fetchService.fetch(address, expected.operatorIndex);
expect(result).toEqual([expected]);
expect(mockCall).toBeCalledTimes(3);
});

test('fetch. fromIndex > toIndex', async () => {
Expand Down
9 changes: 4 additions & 5 deletions src/common/registry/test/fetch/operator.fetch.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ describe('Operators', () => {
const result = await fetchService.fetchOne(address, expected.index);

expect(result).toEqual(expected);
expect(mockCall).toBeCalledTimes(1);
expect(mockCall).toBeCalledTimes(2);
});

test('fetch', async () => {
Expand All @@ -62,7 +62,7 @@ describe('Operators', () => {
const result = await fetchService.fetch(address, expectedFirst.index, expectedSecond.index + 1);

expect(result).toEqual([expectedFirst, expectedSecond]);
expect(mockCall).toBeCalledTimes(2);
expect(mockCall).toBeCalledTimes(4);
});

test('fetch all', async () => {
Expand All @@ -73,16 +73,15 @@ describe('Operators', () => {
const iface = new Interface(Registry__factory.abi);
return iface.encodeFunctionResult('getNodeOperatorsCount', [1]);
})
.mockImplementationOnce(async () => {
.mockImplementation(async () => {
const iface = new Interface(Registry__factory.abi);
operator['moduleAddress'] = address;
// operatorFields(operator);
return iface.encodeFunctionResult('getNodeOperator', operatorFields(operator));
});
const result = await fetchService.fetch(address);

expect(result).toEqual([expected]);
expect(mockCall).toBeCalledTimes(2);
expect(mockCall).toBeCalledTimes(3);
});

test('fetch. fromIndex > toIndex', async () => {
Expand Down
Loading

0 comments on commit d29a291

Please sign in to comment.