Skip to content
This repository has been archived by the owner on Jun 11, 2024. It is now read-only.

Commit

Permalink
Update random module endpoints getHashOnionUsage and setHashOnionUsage (
Browse files Browse the repository at this point in the history
#8431)

* Update endpoints

* feedback

* Remove lower limit for count
  • Loading branch information
Incede authored May 15, 2023
1 parent 223a084 commit d124a7d
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 74 deletions.
31 changes: 19 additions & 12 deletions framework/src/modules/random/endpoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import { validator } from '@liskhq/lisk-validator';
import * as cryptography from '@liskhq/lisk-cryptography';
import { NotFoundError } from '@liskhq/lisk-db';
import { ModuleEndpointContext } from '../../types';
import { BaseEndpoint } from '../base_endpoint';
import { ADDRESS_LENGTH, EMPTY_KEY } from './constants';
Expand All @@ -33,7 +34,7 @@ import {
import { ValidatorRevealsStore } from './stores/validator_reveals';
import { getSeedRevealValidity } from './utils';
import { HashOnionStore } from './stores/hash_onion';
import { UsedHashOnionsStore } from './stores/used_hash_onions';
import { UsedHashOnionStoreObject, UsedHashOnionsStore } from './stores/used_hash_onions';

export class RandomEndpoint extends BaseEndpoint {
public async isSeedRevealValid(ctx: ModuleEndpointContext): Promise<{ valid: boolean }> {
Expand Down Expand Up @@ -141,24 +142,30 @@ export class RandomEndpoint extends BaseEndpoint {
const seed = hashOnion.hashes[hashOnion.hashes.length - 1].toString('hex');

const usedHashOnionStore = this.offchainStores.get(UsedHashOnionsStore);
const usedHashOnion = await usedHashOnionStore.getLatest(ctx, address);
if (!usedHashOnion) {
return {
count: 0,
height: 0,
seed,
};

let usedHashOnion: UsedHashOnionStoreObject;
try {
usedHashOnion = await usedHashOnionStore.get(ctx, address);
} catch (error) {
if (error instanceof NotFoundError) {
return {
usedHashOnions: [{ count: 0, height: 0 }],
seed,
};
}
throw error;
}

return { height: usedHashOnion.height, count: usedHashOnion.count, seed };
return { usedHashOnions: usedHashOnion.usedHashOnions, seed };
}

public async setHashOnionUsage(ctx: ModuleEndpointContext): Promise<void> {
validator.validate<SetHashOnionUsageRequest>(setHashOnionUsageRequest, ctx.params);
const { count, height } = ctx.params;
const address = cryptography.address.getAddressFromLisk32Address(ctx.params.address);

const { address, usedHashOnions } = ctx.params;
const generatorAddress = cryptography.address.getAddressFromLisk32Address(address);

const usedHashOnionStore = this.offchainStores.get(UsedHashOnionsStore);
await usedHashOnionStore.set(ctx, address, { usedHashOnions: [{ count, height }] });
await usedHashOnionStore.set(ctx, generatorAddress, { usedHashOnions });
}
}
57 changes: 37 additions & 20 deletions framework/src/modules/random/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
*/

import { ADDRESS_LENGTH, SEED_LENGTH } from './constants';
import { UsedHashOnion } from './stores/used_hash_onions';

interface AddressRequest {
address: string;
Expand Down Expand Up @@ -94,8 +95,7 @@ export const hasHashOnionResponseSchema = {
};

export interface GetHashOnionUsageResponse {
height: number;
count: number;
readonly usedHashOnions: UsedHashOnion[];
seed: string;
}

Expand All @@ -104,15 +104,24 @@ export type GetHashOnionUsageRequest = AddressRequest;
export const getHashOnionUsageResponse = {
$id: 'lisk/random/getHashOnionUsageResponse',
type: 'object',
required: ['count', 'height', 'seed'],
required: ['usedHashOnions', 'seed'],
properties: {
count: {
type: 'integer',
format: 'uint32',
},
height: {
type: 'integer',
format: 'uint32',
usedHashOnions: {
type: 'array',
items: {
type: 'object',
required: ['count', 'height'],
properties: {
count: {
type: 'integer',
format: 'uint32',
},
height: {
type: 'integer',
format: 'uint32',
},
},
},
},
seed: {
type: 'string',
Expand All @@ -122,26 +131,34 @@ export const getHashOnionUsageResponse = {
};

export interface SetHashOnionUsageRequest extends AddressRequest {
height: number;
count: number;
usedHashOnions: UsedHashOnion[];
}

export const setHashOnionUsageRequest = {
$id: 'lisk/random/setHashOnionUsageRequest',
type: 'object',
required: ['address', 'count', 'height'],
required: ['address', 'usedHashOnions'],
properties: {
address: {
type: 'string',
format: 'lisk32',
},
count: {
type: 'integer',
minimum: 1,
},
height: {
type: 'integer',
format: 'uint32',
usedHashOnions: {
type: 'array',
items: {
type: 'object',
required: ['count', 'height'],
properties: {
count: {
type: 'integer',
format: 'uint32',
},
height: {
type: 'integer',
format: 'uint32',
},
},
},
},
},
};
Expand Down
80 changes: 38 additions & 42 deletions framework/test/unit/modules/random/endpoint.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ import * as cryptography from '@liskhq/lisk-cryptography';
import { ModuleEndpointContext, RandomModule } from '../../../../src';
import { RandomEndpoint } from '../../../../src/modules/random/endpoint';
import { HashOnionStore } from '../../../../src/modules/random/stores/hash_onion';
import { UsedHashOnionsStore } from '../../../../src/modules/random/stores/used_hash_onions';
import {
UsedHashOnionStoreObject,
UsedHashOnionsStore,
} from '../../../../src/modules/random/stores/used_hash_onions';
import { ValidatorRevealsStore } from '../../../../src/modules/random/stores/validator_reveals';
import { PrefixedStateReadWriter } from '../../../../src/state_machine/prefixed_state_read_writer';
import { createTransientModuleEndpointContext } from '../../../../src/testing';
Expand Down Expand Up @@ -55,6 +58,22 @@ describe('RandomModuleEndpoint', () => {
];

const emptyBytes = Buffer.alloc(0);
const defaultUsedHashOnion: UsedHashOnionStoreObject = {
usedHashOnions: [
{
count: 5,
height: 9,
},
{
count: 6,
height: 12,
},
{
count: 7,
height: 15,
},
],
};

beforeEach(async () => {
const randomModule = new RandomModule();
Expand Down Expand Up @@ -410,15 +429,15 @@ describe('RandomModuleEndpoint', () => {
});

describe('getHashOnionUsage', () => {
const seed = genesisValidators.validators[0].hashOnion.hashes[1];
const count = 1000;
const distance = 10;
let address: string;
let address2: string;

beforeEach(async () => {
// Arrange
address = genesisValidators.validators[0].address;
const seed = genesisValidators.validators[0].hashOnion.hashes[1];
const count = 1000;
const distance = 10;
address2 = genesisValidators.validators[1].address;

await randomEndpoint.setHashOnion({ ...context, params: { address, seed, count, distance } });
Expand All @@ -431,9 +450,7 @@ describe('RandomModuleEndpoint', () => {
await usedHashOnionStore.set(
context,
cryptography.address.getAddressFromLisk32Address(address),
{
usedHashOnions: [{ count: 20, height: 2121 }],
},
defaultUsedHashOnion,
);
});

Expand All @@ -453,8 +470,7 @@ describe('RandomModuleEndpoint', () => {

// Assert
expect(seedUsage).toEqual({
count: 20,
height: 2121,
usedHashOnions: defaultUsedHashOnion.usedHashOnions,
seed: genesisValidators.validators[0].hashOnion.hashes[1],
});
});
Expand All @@ -468,8 +484,7 @@ describe('RandomModuleEndpoint', () => {

// Assert
expect(seedUsage).toEqual({
count: 0,
height: 0,
usedHashOnions: [{ count: 0, height: 0 }],
seed: expect.any(String),
});
});
Expand All @@ -479,9 +494,7 @@ describe('RandomModuleEndpoint', () => {
it('should store the appropriate params in the offchain store', async () => {
// Arrange
const { address } = genesisValidators.validators[0];
const count = 1000;
const height = 50;
context.params = { address, count, height };
context.params = { address, usedHashOnions: defaultUsedHashOnion.usedHashOnions };

// Act
await randomEndpoint.setHashOnionUsage(context);
Expand All @@ -494,23 +507,21 @@ describe('RandomModuleEndpoint', () => {

// Assert
expect(usedOnionData).toEqual({
usedHashOnions: [
{
count: 1000,
height: 50,
},
],
usedHashOnions: defaultUsedHashOnion.usedHashOnions,
});
});

it('should throw error when address provided in params is invalid', async () => {
// Arrange
const address = ['address'];
const seed = genesisValidators.validators[0].hashOnion.hashes[1];
const count = 1000;
const distance = 1000;
const height = 50;
context.params = { address, seed, count, distance, height };
context.params = {
address,
seed,
distance,
usedHashOnions: defaultUsedHashOnion.usedHashOnions,
};

// Act & Assert
await expect(randomEndpoint.setHashOnionUsage(context)).rejects.toThrow(
Expand All @@ -525,11 +536,11 @@ describe('RandomModuleEndpoint', () => {
const count = 'count';
const distance = 1000;
const height = 50;
context.params = { address, seed, count, distance, height };
context.params = { address, seed, distance, usedHashOnions: [{ count, height }] };

// Act & Assert
await expect(randomEndpoint.setHashOnionUsage(context)).rejects.toThrow(
"Lisk validator found 1 error[s]:\nProperty '.count' should be of type 'integer'",
"Lisk validator found 2 error[s]:\nProperty '.usedHashOnions.0.count' should be of type 'integer'\nProperty '.usedHashOnions.0.count' must match format \"uint32\"",
);
});

Expand All @@ -540,26 +551,11 @@ describe('RandomModuleEndpoint', () => {
const count = 1000;
const distance = 1000;
const height = 'height';
context.params = { address, seed, count, distance, height };
context.params = { address, seed, distance, usedHashOnions: [{ count, height }] };

// Act & Assert
await expect(randomEndpoint.setHashOnionUsage(context)).rejects.toThrow(
"Lisk validator found 2 error[s]:\nProperty '.height' should be of type 'integer'\nProperty '.height' must match format \"uint32\"",
);
});

it('should throw error when count is less than 1', async () => {
// Arrange
const { address } = genesisValidators.validators[0];
const seed = genesisValidators.validators[0].hashOnion.hashes[1];
const count = 0;
const distance = 1000;
const height = 50;
context.params = { address, seed, count, distance, height };

// Act & Assert
await expect(randomEndpoint.setHashOnionUsage(context)).rejects.toThrow(
'Lisk validator found 1 error[s]:\nmust be >= 1',
"Lisk validator found 2 error[s]:\nProperty '.usedHashOnions.0.height' should be of type 'integer'\nProperty '.usedHashOnions.0.height' must match format \"uint32\"",
);
});
});
Expand Down

0 comments on commit d124a7d

Please sign in to comment.