Skip to content

Commit

Permalink
feat: added /keys/pubkey tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Amuhar committed Aug 29, 2023
1 parent 6349484 commit 54075d9
Show file tree
Hide file tree
Showing 2 changed files with 175 additions and 19 deletions.
145 changes: 129 additions & 16 deletions src/http/keys/keys.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import { nullTransport, LoggerModule } from '@lido-nestjs/logger';

import * as request from 'supertest';
import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify';
import { hexZeroPad } from 'ethers/lib/utils';
// import { validationOpt } from '../../main';

describe('KeyController (e2e)', () => {
Expand All @@ -32,34 +31,76 @@ describe('KeyController (e2e)', () => {
timestamp: 1691500803,
};

const getKey = (value: string) => {
return {
key: hexZeroPad(value, 98),
depositSignature: hexZeroPad(value, 194),
used: true,
};
};

const dvtModuleKeys = [
{ operatorIndex: 1, index: 1, moduleAddress: dvtModule.stakingModuleAddress, ...getKey('0x01'), used: true },
{ operatorIndex: 1, index: 2, moduleAddress: dvtModule.stakingModuleAddress, ...getKey('0x02'), used: false },
{
operatorIndex: 1,
index: 1,
moduleAddress: dvtModule.stakingModuleAddress,
key: '0xa544bc44d9eacbf4dd6a2d6087b43f4c67fd5618651b97effcb30997bf49e5d7acf0100ef14e5d087cc228bc78d498e6',
depositSignature:
'0x967875a0104d9f674538e2ec0df4be0a61ef08061cdcfa83e5a63a43dadb772d29053368224e5d8e046ba1a78490f5fc0f0186f23af0465d0a82b2db2e7535782fe12e1fd1cd4f6eb77d8dc7a4f7ab0fde31435d5fa98a013e0a716c5e1ef6a2',
used: true,
},
{
operatorIndex: 1,
index: 2,
moduleAddress: dvtModule.stakingModuleAddress,
key: '0xb3e9f4e915f9fb9ef9c55da1815071f3f728cc6fc434fba2c11e08db5b5fa22b71d5975cec30ef97e7fc901e5a04ee5b',
depositSignature:
'0xb048f4a409d5a0aa638e5ec65c21e936ffde9a8d848e74e6b2f6972a4145620dc78c79db5425ea1a5c6b1dd8d50fc77f0bcec894c0a9446776936f2adf4f1dc7056fb3c4bdf9dbd00981288d4e582875d10b13d780dddc642496e97826abd3c7',
used: false,
},
];

const keyForOperatorTwo = {
operatorIndex: 2,
index: 5,
moduleAddress: curatedModule.stakingModuleAddress,
...getKey('0x03'),
key: '0x91024d603575605569c212b00f375c8bad733a697b453fbe054bb996bd24c7d1a5b6034cc58943aeddab05cbdfd40632',
depositSignature:
'0x9990450099816e066c20b5947be6bf089b57fcfacfb2c8285ddfd6c678a44198bf7c013a0d1a6353ed19dd94423eef7b010d25aaa2c3093760c79bf247f5350120e8a74e4586eeba0f1e2bcf17806f705007d7b5862039da5cd93ee659280d77',
used: true,
};

const keyForOperatorTwoDuplicate = { ...keyForOperatorTwo, index: 6 };

const curatedModuleKeys = [
{ operatorIndex: 1, index: 1, moduleAddress: curatedModule.stakingModuleAddress, ...getKey('0x04'), used: true },
{ operatorIndex: 1, index: 2, moduleAddress: curatedModule.stakingModuleAddress, ...getKey('0x05'), used: true },
{ operatorIndex: 1, index: 3, moduleAddress: curatedModule.stakingModuleAddress, ...getKey('0x06'), used: false },
{ operatorIndex: 2, index: 4, moduleAddress: curatedModule.stakingModuleAddress, ...getKey('0x07'), used: true },
{
operatorIndex: 1,
index: 1,
moduleAddress: curatedModule.stakingModuleAddress,
key: '0xa554bc44d9eacbf4dd6a2d6087b43f4c67fd5618651b97effcb30997bf49e5d7acf0100ef14e5d087cc228bc78d498e6',
depositSignature:
'0x967875a0104d9f674538e2ec0df4be0a61ef08061cdcfa83e5a63a43dadb772d29053368224e5d8e046ba1a78490f5fc0f0186f23af0465d0a82b2db2e7535782fe12e1fd1cd4f6eb77d8dc7a4f7ab0fde31435d5fa98a013e0a716c5e1ef6a2',
used: true,
},
{
operatorIndex: 1,
index: 2,
moduleAddress: curatedModule.stakingModuleAddress,
key: '0xb3a9f4e915f9fb9ef9c55da1815071f3f728cc6fc434fba2c11e08db5b5fa22b71d5975cec30ef97e7fc901e5a04ee5b',
depositSignature:
'0xb048f4a409d5a0aa638e5ec65c21e936ffde9a8d848e74e6b2f6972a4145620dc78c79db5425ea1a5c6b1dd8d50fc77f0bcec894c0a9446776936f2adf4f1dc7056fb3c4bdf9dbd00981288d4e582875d10b13d780dddc642496e97826abd3c7',
used: true,
},
{
operatorIndex: 1,
index: 3,
moduleAddress: curatedModule.stakingModuleAddress,
key: '0x91524d603575605569c212b00f375c8bad733a697b453fbe054bb996bd24c7d1a5b6034cc58943aeddab05cbdfd40632',
depositSignature:
'0x9990450099816e066c20b5947be6bf089b57fcfacfb2c8285ddfd6c678a44198bf7c013a0d1a6353ed19dd94423eef7b010d25aaa2c3093760c79bf247f5350120e8a74e4586eeba0f1e2bcf17806f705007d7b5862039da5cd93ee659280d77',
used: false,
},
{
operatorIndex: 2,
index: 4,
moduleAddress: curatedModule.stakingModuleAddress,
key: '0xa544bc44d8eacbf4dd6a2d6087b43f4c67fd5618651b97effcb30997bf49e5d7acf0100ef14e5d087cc228bc78d498e6',
depositSignature:
'0x967875a0104d1f674538e2ec0df4be0a61ef08061cdcfa83e5a63a43dadb772d29053368224e5d8e046ba1a78490f5fc0f0186f23af0465d0a82b2db2e7535782fe12e1fd1cd4f6eb77d8dc7a4f7ab0fde31435d5fa98a013e0a716c5e1ef6a2',
used: true,
},
keyForOperatorTwo,
keyForOperatorTwoDuplicate,
];
Expand Down Expand Up @@ -421,4 +462,76 @@ describe('KeyController (e2e)', () => {
});
});
});

describe('The /v1/keys/{pubkey} requests', () => {
describe('too early response case', () => {
beforeEach(async () => {
await cleanDB();
});

afterEach(async () => {
await cleanDB();
});

it('should return too early response if there are no modules in database', async () => {
// lets save meta
await elMetaStorageService.update(elMeta);
// lets save keys
await keysStorageService.save(keys);
const resp = await request(app.getHttpServer()).get(`/v1/keys/wrongkey`);
expect(resp.status).toEqual(425);
expect(resp.body).toEqual({ message: 'Too early response', statusCode: 425 });
});

it('should return too early response if there are no meta', async () => {
// lets save keys
await keysStorageService.save(keys);
await moduleStorageService.store(curatedModule, 1);
const resp = await request(app.getHttpServer()).get(`/v1/keys/wrongkey`);
expect(resp.status).toEqual(425);
expect(resp.body).toEqual({ message: 'Too early response', statusCode: 425 });
});
});

describe('api ready to work', () => {
beforeAll(async () => {
// lets save meta
await elMetaStorageService.update(elMeta);
// lets save keys
await keysStorageService.save(keys);
// lets save modules
await moduleStorageService.store(dvtModule, 1);
await moduleStorageService.store(curatedModule, 1);
});

afterAll(async () => {
await cleanDB();
});

it('should return all keys that satisfy the request', async () => {
const resp = await request(app.getHttpServer()).get(`/v1/keys/${keyForOperatorTwoDuplicate.key}`);
expect(resp.status).toEqual(200);
// as pubkeys contains 3 elements and keyForOperatorTwo has a duplicate
expect(resp.body.data.length).toEqual(2);
expect(resp.body.data).toEqual(expect.arrayContaining([keyForOperatorTwo, keyForOperatorTwoDuplicate]));
expect(resp.body.meta).toEqual({
elBlockSnapshot: {
blockNumber: elMeta.number,
blockHash: elMeta.hash,
timestamp: elMeta.timestamp,
},
});
});

it('should return 404 if key was not found', async () => {
const resp = await request(app.getHttpServer()).get(`/v1/keys/someunknownkey`);
expect(resp.status).toEqual(404);
expect(resp.body).toEqual({
error: 'Not Found',
message: 'There are no keys with someunknownkey public key in db.',
statusCode: 404,
});
});
});
});
});
49 changes: 46 additions & 3 deletions src/http/keys/keys.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Inject, Injectable, LoggerService } from '@nestjs/common';
import { Inject, Injectable, LoggerService, NotFoundException } from '@nestjs/common';
import { LOGGER_PROVIDER } from '@lido-nestjs/logger';
import { KeyListResponse, KeyWithModuleAddress } from './entities';
import { StakingRouterService } from '../../staking-router-modules/staking-router.service';
Expand All @@ -7,6 +7,8 @@ import { KeyField } from 'staking-router-modules/interfaces/filters';
import { IsolationLevel } from '@mikro-orm/core';
import { EntityManager } from '@mikro-orm/knex';

type KeyWithModuleAddressFieldT = keyof KeyWithModuleAddress;

@Injectable()
export class KeysService {
constructor(
Expand Down Expand Up @@ -43,7 +45,42 @@ export class KeysService {
}

async getByPubkey(pubkey: string): Promise<KeyListResponse> {
return this.getByPubkeys([pubkey]);
const { keys, elBlockSnapshot } = await this.entityManager.transactional(
async () => {
const { stakingModules, elBlockSnapshot } = await this.stakingRouterService.getStakingModulesAndMeta();
const collectedKeys: KeyWithModuleAddress[][] = [];

for (const module of stakingModules) {
const moduleInstance = this.stakingRouterService.getStakingRouterModuleImpl(module.type);
const fields: KeyWithModuleAddressFieldT[] = [
'key',
'depositSignature',
'operatorIndex',
'used',
'moduleAddress',
];
const keys: KeyWithModuleAddress[] = await moduleInstance.getKeysByPubkey(
module.stakingModuleAddress,
pubkey,
fields,
);

collectedKeys.push(keys);
}

return { keys: collectedKeys.flat(), elBlockSnapshot };
},
{ isolationLevel: IsolationLevel.REPEATABLE_READ },
);

if (keys.length == 0) {
throw new NotFoundException(`There are no keys with ${pubkey} public key in db.`);
}

return {
data: keys,
meta: { elBlockSnapshot },
};
}

async getByPubkeys(pubKeys: string[]): Promise<KeyListResponse> {
Expand All @@ -54,7 +91,13 @@ export class KeysService {

for (const module of stakingModules) {
const moduleInstance = this.stakingRouterService.getStakingRouterModuleImpl(module.type);
const fields: KeyField[] = ['key', 'depositSignature', 'operatorIndex', 'used', 'moduleAddress'];
const fields: KeyWithModuleAddressFieldT[] = [
'key',
'depositSignature',
'operatorIndex',
'used',
'moduleAddress',
];
const keys: KeyWithModuleAddress[] = await moduleInstance.getKeysByPubKeys(
module.stakingModuleAddress,
pubKeys,
Expand Down

0 comments on commit 54075d9

Please sign in to comment.