From a22fee06622c0dde377dc8d989e25ff7cab98620 Mon Sep 17 00:00:00 2001 From: Mehmet Egemen Albayrak Date: Wed, 8 Sep 2021 14:32:48 +0300 Subject: [PATCH 1/9] Add endpoint --- framework/src/modules/reward/endpoint.ts | 39 ++++++++- framework/src/modules/reward/module.ts | 8 ++ framework/src/modules/reward/schemas.ts | 17 +++- framework/src/modules/reward/types.ts | 19 +++++ .../test/unit/modules/reward/endpoint.spec.ts | 81 +++++++++++++++++++ .../unit/modules/reward/reward_module.spec.ts | 49 +++++++++++ 6 files changed, 211 insertions(+), 2 deletions(-) create mode 100644 framework/test/unit/modules/reward/endpoint.spec.ts create mode 100644 framework/test/unit/modules/reward/reward_module.spec.ts diff --git a/framework/src/modules/reward/endpoint.ts b/framework/src/modules/reward/endpoint.ts index ffbca81bc99..cc276d82b9a 100644 --- a/framework/src/modules/reward/endpoint.ts +++ b/framework/src/modules/reward/endpoint.ts @@ -12,6 +12,43 @@ * Removal or modification of this copyright notice is prohibited. */ +import { ModuleEndpointContext } from '../..'; import { BaseEndpoint } from '../base_endpoint'; +import { DefaultReward, EndpointInitArgs, GetDefaultRewardParams } from './types'; -export class RewardEndpoint extends BaseEndpoint {} +export class RewardEndpoint extends BaseEndpoint { + private _brackets!: ReadonlyArray; + private _offset!: number; + private _distance!: number; + + public init(args: EndpointInitArgs) { + this._brackets = args.config.brackets; + this._offset = args.config.offset; + this._distance = args.config.distance; + } + + public getDefaultRewardAtHeight(ctx: ModuleEndpointContext): DefaultReward { + const { height } = (ctx.params as unknown) as GetDefaultRewardParams; + + if (height < this._offset) { + return { + reward: BigInt(0), + }; + } + + const distance = Math.floor(this._distance); + const location = Math.trunc((height - this._offset) / distance); + const lastBracket = this._brackets[this._brackets.length - 1]; + + let bracket; + if (location > this._brackets.length - 1) { + bracket = this._brackets.lastIndexOf(lastBracket); + } else { + bracket = location; + } + + return { + reward: this._brackets[bracket], + }; + } +} diff --git a/framework/src/modules/reward/module.ts b/framework/src/modules/reward/module.ts index 3f0180184bf..4d603718c6f 100644 --- a/framework/src/modules/reward/module.ts +++ b/framework/src/modules/reward/module.ts @@ -44,6 +44,14 @@ export class RewardModule extends BaseModule { const { moduleConfig } = args; this._moduleConfig = (moduleConfig as unknown) as ModuleConfig; this._tokenIDReward = this._moduleConfig.tokenIDReward; + + this.endpoint.init({ + config: { + brackets: this._moduleConfig.brackets.map(bracket => BigInt(bracket)), + offset: this._moduleConfig.offset, + distance: this._moduleConfig.distance, + }, + }); } // eslint-disable-next-line @typescript-eslint/require-await diff --git a/framework/src/modules/reward/schemas.ts b/framework/src/modules/reward/schemas.ts index e23f74c83e3..34d1bcdfdb6 100644 --- a/framework/src/modules/reward/schemas.ts +++ b/framework/src/modules/reward/schemas.ts @@ -28,6 +28,21 @@ export const configSchema = { }, required: ['chainID', 'localID'], }, + offset: { + type: 'integer', + minimum: 1, + }, + distance: { + type: 'integer', + minimum: 1, + }, + brackets: { + type: 'array', + items: { + type: 'string', + format: 'uint64', + }, + }, }, - required: ['tokenIDReward'], + required: ['tokenIDReward', 'offset', 'distance', 'brackets'], }; diff --git a/framework/src/modules/reward/types.ts b/framework/src/modules/reward/types.ts index 2f022f20b43..1fd02f0a5bb 100644 --- a/framework/src/modules/reward/types.ts +++ b/framework/src/modules/reward/types.ts @@ -22,6 +22,9 @@ export interface TokenIDReward { export interface ModuleConfig { tokenIDReward: TokenIDReward; + brackets: ReadonlyArray; + offset: number; + distance: number; } export interface TokenAPI { @@ -44,3 +47,19 @@ export interface RandomAPI { export interface LiskBFTAPI { impliesMaximalPrevotes(apiContext: APIContext, blockHeader: BlockHeader): Promise; } + +export interface GetDefaultRewardParams { + height: number; +} + +export interface DefaultReward { + reward: bigint; +} + +export interface EndpointInitArgs { + config: { + brackets: ReadonlyArray; + offset: number; + distance: number; + }; +} diff --git a/framework/test/unit/modules/reward/endpoint.spec.ts b/framework/test/unit/modules/reward/endpoint.spec.ts new file mode 100644 index 00000000000..29f9970994d --- /dev/null +++ b/framework/test/unit/modules/reward/endpoint.spec.ts @@ -0,0 +1,81 @@ +/* + * Copyright © 2021 Lisk Foundation + * + * See the LICENSE file at the top-level directory of this distribution + * for licensing information. + * + * Unless otherwise agreed in a custom licensing agreement with the Lisk Foundation, + * no part of this software, including this file, may be copied, modified, + * propagated, or distributed except according to the terms contained in the + * LICENSE file. + * + * Removal or modification of this copyright notice is prohibited. + */ +import { Logger } from '../../../../src/logger'; +import { RewardModule } from '../../../../src/modules/reward'; +import { fakeLogger } from '../../../utils/node'; + +describe('RewardModule', () => { + const genesisConfig: any = {}; + const moduleConfig: any = { + distance: 3000000, + offset: 2160, + brackets: [ + BigInt('500000000'), // Initial Reward + BigInt('400000000'), // Milestone 1 + BigInt('300000000'), // Milestone 2 + BigInt('200000000'), // Milestone 3 + BigInt('100000000'), // Milestone 4 + ], + tokenIDReward: { chainID: 0, localID: 0 }, + }; + const generatorConfig: any = {}; + + const logger: Logger = fakeLogger; + let rewardModule: RewardModule; + + beforeAll(async () => { + rewardModule = new RewardModule(); + await rewardModule.init({ genesisConfig, moduleConfig, generatorConfig }); + rewardModule.addDependencies( + { mint: jest.fn() } as any, + { isValidSeedReveal: jest.fn() } as any, + { impliesMaximalPrevotes: jest.fn() } as any, + ); + }); + + describe('endpoint', () => { + const { brackets, offset, distance } = moduleConfig as { + brackets: ReadonlyArray; + offset: number; + distance: number; + }; + + for (const [index, rewardFromConfig] of Object.entries(brackets)) { + const nthBracket = +index; + const currentHeight = offset + nthBracket * distance; + // eslint-disable-next-line no-loop-func + it(`should getDefaultRewardAtHeight work for the ${nthBracket}th bracket`, () => { + const rewardFromEndpoint = rewardModule.endpoint.getDefaultRewardAtHeight({ + getStore: jest.fn(), + logger, + params: { + height: currentHeight, + }, + }); + expect(rewardFromEndpoint).toEqual({ reward: rewardFromConfig }); + }); + } + + it(`should getDefaultRewardAtHeight work for the height below offset`, () => { + const rewardFromEndpoint = rewardModule.endpoint.getDefaultRewardAtHeight({ + getStore: jest.fn(), + logger, + params: { + height: offset - 1, + }, + }); + expect(rewardFromEndpoint).toEqual({ reward: BigInt(0) }); + }); + }); +}); diff --git a/framework/test/unit/modules/reward/reward_module.spec.ts b/framework/test/unit/modules/reward/reward_module.spec.ts new file mode 100644 index 00000000000..ead770d6e20 --- /dev/null +++ b/framework/test/unit/modules/reward/reward_module.spec.ts @@ -0,0 +1,49 @@ +/* + * Copyright © 2021 Lisk Foundation + * + * See the LICENSE file at the top-level directory of this distribution + * for licensing information. + * + * Unless otherwise agreed in a custom licensing agreement with the Lisk Foundation, + * no part of this software, including this file, may be copied, modified, + * propagated, or distributed except according to the terms contained in the + * LICENSE file. + * + * Removal or modification of this copyright notice is prohibited. + */ +import { RewardModule } from '../../../../src/modules/reward'; + +describe('RewardModule', () => { + const genesisConfig: any = {}; + const moduleConfig: any = { + distance: 3000000, + offset: 2160, + brackets: [ + BigInt('500000000'), // Initial Reward + BigInt('400000000'), // Milestone 1 + BigInt('300000000'), // Milestone 2 + BigInt('200000000'), // Milestone 3 + BigInt('100000000'), // Milestone 4 + ], + tokenIDReward: { chainID: 0, localID: 0 }, + }; + const generatorConfig: any = {}; + + let rewardModule: RewardModule; + + beforeAll(async () => { + rewardModule = new RewardModule(); + await rewardModule.init({ genesisConfig, moduleConfig, generatorConfig }); + rewardModule.addDependencies( + { mint: jest.fn() } as any, + { isValidSeedReveal: jest.fn() } as any, + { impliesMaximalPrevotes: jest.fn() } as any, + ); + }); + + describe('init', () => { + it('should set the moduleConfig property', () => { + expect(rewardModule['_moduleConfig']).toEqual(moduleConfig); + }); + }); +}); From 18eb7550eb0c20aab8d34945e7070c5c6c3b6f87 Mon Sep 17 00:00:00 2001 From: Mehmet Egemen Albayrak Date: Wed, 8 Sep 2021 18:23:18 +0300 Subject: [PATCH 2/9] Convert reward representation to string --- framework/src/modules/reward/endpoint.ts | 4 ++-- framework/src/modules/reward/types.ts | 2 +- framework/test/unit/modules/reward/endpoint.spec.ts | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/framework/src/modules/reward/endpoint.ts b/framework/src/modules/reward/endpoint.ts index cc276d82b9a..2f99960a99b 100644 --- a/framework/src/modules/reward/endpoint.ts +++ b/framework/src/modules/reward/endpoint.ts @@ -32,7 +32,7 @@ export class RewardEndpoint extends BaseEndpoint { if (height < this._offset) { return { - reward: BigInt(0), + reward: '0', }; } @@ -48,7 +48,7 @@ export class RewardEndpoint extends BaseEndpoint { } return { - reward: this._brackets[bracket], + reward: this._brackets[bracket].toString(), }; } } diff --git a/framework/src/modules/reward/types.ts b/framework/src/modules/reward/types.ts index 1fd02f0a5bb..ba87fc38117 100644 --- a/framework/src/modules/reward/types.ts +++ b/framework/src/modules/reward/types.ts @@ -53,7 +53,7 @@ export interface GetDefaultRewardParams { } export interface DefaultReward { - reward: bigint; + reward: string; } export interface EndpointInitArgs { diff --git a/framework/test/unit/modules/reward/endpoint.spec.ts b/framework/test/unit/modules/reward/endpoint.spec.ts index 29f9970994d..76aac777150 100644 --- a/framework/test/unit/modules/reward/endpoint.spec.ts +++ b/framework/test/unit/modules/reward/endpoint.spec.ts @@ -63,7 +63,7 @@ describe('RewardModule', () => { height: currentHeight, }, }); - expect(rewardFromEndpoint).toEqual({ reward: rewardFromConfig }); + expect(rewardFromEndpoint).toEqual({ reward: rewardFromConfig.toString() }); }); } @@ -75,7 +75,7 @@ describe('RewardModule', () => { height: offset - 1, }, }); - expect(rewardFromEndpoint).toEqual({ reward: BigInt(0) }); + expect(rewardFromEndpoint).toEqual({ reward: '0' }); }); }); }); From c74ae2fd852456f5a2674da2c91ede661ebaa01e Mon Sep 17 00:00:00 2001 From: Mehmet Egemen Albayrak Date: Wed, 8 Sep 2021 18:54:53 +0300 Subject: [PATCH 3/9] Add validation for parameter height --- framework/src/modules/reward/endpoint.ts | 12 ++++++++-- framework/src/modules/reward/types.ts | 4 ---- .../test/unit/modules/reward/endpoint.spec.ts | 24 +++++++++++++++++++ 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/framework/src/modules/reward/endpoint.ts b/framework/src/modules/reward/endpoint.ts index 2f99960a99b..0d1edd06bf7 100644 --- a/framework/src/modules/reward/endpoint.ts +++ b/framework/src/modules/reward/endpoint.ts @@ -14,7 +14,7 @@ import { ModuleEndpointContext } from '../..'; import { BaseEndpoint } from '../base_endpoint'; -import { DefaultReward, EndpointInitArgs, GetDefaultRewardParams } from './types'; +import { DefaultReward, EndpointInitArgs } from './types'; export class RewardEndpoint extends BaseEndpoint { private _brackets!: ReadonlyArray; @@ -28,7 +28,15 @@ export class RewardEndpoint extends BaseEndpoint { } public getDefaultRewardAtHeight(ctx: ModuleEndpointContext): DefaultReward { - const { height } = (ctx.params as unknown) as GetDefaultRewardParams; + const { height } = ctx.params; + + if (typeof height !== 'number') { + throw new Error('Parameter height must be a number'); + } + + if (height < 0) { + throw new Error('Parameter height cannot be smaller than 0'); + } if (height < this._offset) { return { diff --git a/framework/src/modules/reward/types.ts b/framework/src/modules/reward/types.ts index ba87fc38117..c92e0c288f6 100644 --- a/framework/src/modules/reward/types.ts +++ b/framework/src/modules/reward/types.ts @@ -48,10 +48,6 @@ export interface LiskBFTAPI { impliesMaximalPrevotes(apiContext: APIContext, blockHeader: BlockHeader): Promise; } -export interface GetDefaultRewardParams { - height: number; -} - export interface DefaultReward { reward: string; } diff --git a/framework/test/unit/modules/reward/endpoint.spec.ts b/framework/test/unit/modules/reward/endpoint.spec.ts index 76aac777150..b2b53eb5278 100644 --- a/framework/test/unit/modules/reward/endpoint.spec.ts +++ b/framework/test/unit/modules/reward/endpoint.spec.ts @@ -77,5 +77,29 @@ describe('RewardModule', () => { }); expect(rewardFromEndpoint).toEqual({ reward: '0' }); }); + + it('should throw an error when parameter height is not a number', () => { + expect(() => + rewardModule.endpoint.getDefaultRewardAtHeight({ + getStore: jest.fn(), + logger, + params: { + height: 'Not a number', + }, + }), + ).toThrow('Parameter height must be a number'); + }); + + it('should throw an error when parameter height is below 0', () => { + expect(() => + rewardModule.endpoint.getDefaultRewardAtHeight({ + getStore: jest.fn(), + logger, + params: { + height: -1, + }, + }), + ).toThrow('Parameter height cannot be smaller than 0'); + }); }); }); From bd21b32b28d76c72d1938656abb04c115cb711ba Mon Sep 17 00:00:00 2001 From: Mehmet Egemen Albayrak Date: Thu, 9 Sep 2021 08:15:19 +0300 Subject: [PATCH 4/9] Add dots to error messages --- framework/src/modules/reward/endpoint.ts | 4 ++-- framework/test/unit/modules/reward/endpoint.spec.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/framework/src/modules/reward/endpoint.ts b/framework/src/modules/reward/endpoint.ts index 0d1edd06bf7..9d7859f6b5a 100644 --- a/framework/src/modules/reward/endpoint.ts +++ b/framework/src/modules/reward/endpoint.ts @@ -31,11 +31,11 @@ export class RewardEndpoint extends BaseEndpoint { const { height } = ctx.params; if (typeof height !== 'number') { - throw new Error('Parameter height must be a number'); + throw new Error('Parameter height must be a number.'); } if (height < 0) { - throw new Error('Parameter height cannot be smaller than 0'); + throw new Error('Parameter height cannot be smaller than 0.'); } if (height < this._offset) { diff --git a/framework/test/unit/modules/reward/endpoint.spec.ts b/framework/test/unit/modules/reward/endpoint.spec.ts index b2b53eb5278..67d482b2265 100644 --- a/framework/test/unit/modules/reward/endpoint.spec.ts +++ b/framework/test/unit/modules/reward/endpoint.spec.ts @@ -87,7 +87,7 @@ describe('RewardModule', () => { height: 'Not a number', }, }), - ).toThrow('Parameter height must be a number'); + ).toThrow('Parameter height must be a number.'); }); it('should throw an error when parameter height is below 0', () => { @@ -99,7 +99,7 @@ describe('RewardModule', () => { height: -1, }, }), - ).toThrow('Parameter height cannot be smaller than 0'); + ).toThrow('Parameter height cannot be smaller than 0.'); }); }); }); From e7e7d4adb69f74b4b711d098bbb2393a4e670fa9 Mon Sep 17 00:00:00 2001 From: Mehmet Egemen Albayrak Date: Thu, 9 Sep 2021 08:17:54 +0300 Subject: [PATCH 5/9] Simplify bracket index determination --- framework/src/modules/reward/endpoint.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/framework/src/modules/reward/endpoint.ts b/framework/src/modules/reward/endpoint.ts index 9d7859f6b5a..7c04acf5aec 100644 --- a/framework/src/modules/reward/endpoint.ts +++ b/framework/src/modules/reward/endpoint.ts @@ -48,12 +48,8 @@ export class RewardEndpoint extends BaseEndpoint { const location = Math.trunc((height - this._offset) / distance); const lastBracket = this._brackets[this._brackets.length - 1]; - let bracket; - if (location > this._brackets.length - 1) { - bracket = this._brackets.lastIndexOf(lastBracket); - } else { - bracket = location; - } + const bracket = + location > this._brackets.length - 1 ? this._brackets.lastIndexOf(lastBracket) : location; return { reward: this._brackets[bracket].toString(), From e2a30e47ea7256c17f877590b2d4e61ed53d46bd Mon Sep 17 00:00:00 2001 From: Mehmet Egemen Albayrak Date: Thu, 9 Sep 2021 08:21:02 +0300 Subject: [PATCH 6/9] Remove redundant nesting in endpoint test --- .../test/unit/modules/reward/endpoint.spec.ts | 92 +++++++++---------- 1 file changed, 45 insertions(+), 47 deletions(-) diff --git a/framework/test/unit/modules/reward/endpoint.spec.ts b/framework/test/unit/modules/reward/endpoint.spec.ts index 67d482b2265..0c923b5e710 100644 --- a/framework/test/unit/modules/reward/endpoint.spec.ts +++ b/framework/test/unit/modules/reward/endpoint.spec.ts @@ -15,7 +15,7 @@ import { Logger } from '../../../../src/logger'; import { RewardModule } from '../../../../src/modules/reward'; import { fakeLogger } from '../../../utils/node'; -describe('RewardModule', () => { +describe('RewardModuleEndpoint', () => { const genesisConfig: any = {}; const moduleConfig: any = { distance: 3000000, @@ -44,62 +44,60 @@ describe('RewardModule', () => { ); }); - describe('endpoint', () => { - const { brackets, offset, distance } = moduleConfig as { - brackets: ReadonlyArray; - offset: number; - distance: number; - }; - - for (const [index, rewardFromConfig] of Object.entries(brackets)) { - const nthBracket = +index; - const currentHeight = offset + nthBracket * distance; - // eslint-disable-next-line no-loop-func - it(`should getDefaultRewardAtHeight work for the ${nthBracket}th bracket`, () => { - const rewardFromEndpoint = rewardModule.endpoint.getDefaultRewardAtHeight({ - getStore: jest.fn(), - logger, - params: { - height: currentHeight, - }, - }); - expect(rewardFromEndpoint).toEqual({ reward: rewardFromConfig.toString() }); - }); - } + const { brackets, offset, distance } = moduleConfig as { + brackets: ReadonlyArray; + offset: number; + distance: number; + }; - it(`should getDefaultRewardAtHeight work for the height below offset`, () => { + for (const [index, rewardFromConfig] of Object.entries(brackets)) { + const nthBracket = +index; + const currentHeight = offset + nthBracket * distance; + // eslint-disable-next-line no-loop-func + it(`should getDefaultRewardAtHeight work for the ${nthBracket}th bracket`, () => { const rewardFromEndpoint = rewardModule.endpoint.getDefaultRewardAtHeight({ getStore: jest.fn(), logger, params: { - height: offset - 1, + height: currentHeight, }, }); - expect(rewardFromEndpoint).toEqual({ reward: '0' }); + expect(rewardFromEndpoint).toEqual({ reward: rewardFromConfig.toString() }); }); + } - it('should throw an error when parameter height is not a number', () => { - expect(() => - rewardModule.endpoint.getDefaultRewardAtHeight({ - getStore: jest.fn(), - logger, - params: { - height: 'Not a number', - }, - }), - ).toThrow('Parameter height must be a number.'); + it(`should getDefaultRewardAtHeight work for the height below offset`, () => { + const rewardFromEndpoint = rewardModule.endpoint.getDefaultRewardAtHeight({ + getStore: jest.fn(), + logger, + params: { + height: offset - 1, + }, }); + expect(rewardFromEndpoint).toEqual({ reward: '0' }); + }); - it('should throw an error when parameter height is below 0', () => { - expect(() => - rewardModule.endpoint.getDefaultRewardAtHeight({ - getStore: jest.fn(), - logger, - params: { - height: -1, - }, - }), - ).toThrow('Parameter height cannot be smaller than 0.'); - }); + it('should throw an error when parameter height is not a number', () => { + expect(() => + rewardModule.endpoint.getDefaultRewardAtHeight({ + getStore: jest.fn(), + logger, + params: { + height: 'Not a number', + }, + }), + ).toThrow('Parameter height must be a number.'); + }); + + it('should throw an error when parameter height is below 0', () => { + expect(() => + rewardModule.endpoint.getDefaultRewardAtHeight({ + getStore: jest.fn(), + logger, + params: { + height: -1, + }, + }), + ).toThrow('Parameter height cannot be smaller than 0.'); }); }); From 2234c9ea337315a92db4b865b35f295c141ee0d4 Mon Sep 17 00:00:00 2001 From: Mehmet Egemen Albayrak Date: Thu, 9 Sep 2021 08:23:39 +0300 Subject: [PATCH 7/9] Redact test name quotes --- framework/test/unit/modules/reward/endpoint.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/test/unit/modules/reward/endpoint.spec.ts b/framework/test/unit/modules/reward/endpoint.spec.ts index 0c923b5e710..b3eec698b0c 100644 --- a/framework/test/unit/modules/reward/endpoint.spec.ts +++ b/framework/test/unit/modules/reward/endpoint.spec.ts @@ -66,7 +66,7 @@ describe('RewardModuleEndpoint', () => { }); } - it(`should getDefaultRewardAtHeight work for the height below offset`, () => { + it('should getDefaultRewardAtHeight work for the height below offset', () => { const rewardFromEndpoint = rewardModule.endpoint.getDefaultRewardAtHeight({ getStore: jest.fn(), logger, From 1ce8fd23a6d4a54c2fa18b1bd0019a043a4a2533 Mon Sep 17 00:00:00 2001 From: Mehmet Egemen Albayrak Date: Thu, 9 Sep 2021 10:44:27 +0300 Subject: [PATCH 8/9] Separate reward calculation logic from endpoint Reward calculation logic will also be used by the API. We prefered config injection to endpoint and then passing injected configs to separated function instead of passing a function to endpoint that is bound to config variables. That way we preserved type safety and flexibility of using config vars later in the different places of the endpoint. --- .../src/modules/reward/calculate_reward.ts | 31 +++++++++++++++++++ framework/src/modules/reward/endpoint.ts | 23 +++++--------- framework/src/modules/reward/types.ts | 7 +++++ 3 files changed, 46 insertions(+), 15 deletions(-) create mode 100644 framework/src/modules/reward/calculate_reward.ts diff --git a/framework/src/modules/reward/calculate_reward.ts b/framework/src/modules/reward/calculate_reward.ts new file mode 100644 index 00000000000..ab02ed260df --- /dev/null +++ b/framework/src/modules/reward/calculate_reward.ts @@ -0,0 +1,31 @@ +/* + * Copyright © 2020 Lisk Foundation + * + * See the LICENSE file at the top-level directory of this distribution + * for licensing information. + * + * Unless otherwise agreed in a custom licensing agreement with the Lisk Foundation, + * no part of this software, including this file, may be copied, modified, + * propagated, or distributed except according to the terms contained in the + * LICENSE file. + * + * Removal or modification of this copyright notice is prohibited. + */ + +import { CalculateDefaultRewardArgs } from './types'; + +export const calculateDefaultReward = (args: CalculateDefaultRewardArgs): bigint => { + const { height, distance, offset, brackets } = args; + + if (height < offset) { + return BigInt(0); + } + + const rewardDistance = Math.floor(distance); + const location = Math.trunc((height - offset) / rewardDistance); + const lastBracket = brackets[brackets.length - 1]; + + const bracket = location > brackets.length - 1 ? brackets.lastIndexOf(lastBracket) : location; + + return brackets[bracket]; +}; diff --git a/framework/src/modules/reward/endpoint.ts b/framework/src/modules/reward/endpoint.ts index 7c04acf5aec..4d4ac5d9f0b 100644 --- a/framework/src/modules/reward/endpoint.ts +++ b/framework/src/modules/reward/endpoint.ts @@ -14,6 +14,7 @@ import { ModuleEndpointContext } from '../..'; import { BaseEndpoint } from '../base_endpoint'; +import { calculateDefaultReward } from './calculate_reward'; import { DefaultReward, EndpointInitArgs } from './types'; export class RewardEndpoint extends BaseEndpoint { @@ -38,21 +39,13 @@ export class RewardEndpoint extends BaseEndpoint { throw new Error('Parameter height cannot be smaller than 0.'); } - if (height < this._offset) { - return { - reward: '0', - }; - } - - const distance = Math.floor(this._distance); - const location = Math.trunc((height - this._offset) / distance); - const lastBracket = this._brackets[this._brackets.length - 1]; - - const bracket = - location > this._brackets.length - 1 ? this._brackets.lastIndexOf(lastBracket) : location; + const reward = calculateDefaultReward({ + height, + brackets: this._brackets, + distance: this._distance, + offset: this._offset, + }); - return { - reward: this._brackets[bracket].toString(), - }; + return { reward: reward.toString() }; } } diff --git a/framework/src/modules/reward/types.ts b/framework/src/modules/reward/types.ts index c92e0c288f6..799fd3bfb94 100644 --- a/framework/src/modules/reward/types.ts +++ b/framework/src/modules/reward/types.ts @@ -59,3 +59,10 @@ export interface EndpointInitArgs { distance: number; }; } + +export interface CalculateDefaultRewardArgs { + brackets: ReadonlyArray; + offset: number; + distance: number; + height: number; +} From b356ac7079b62ca5580ea306cce5febfa3736f88 Mon Sep 17 00:00:00 2001 From: Mehmet Egemen Albayrak Date: Thu, 9 Sep 2021 11:32:33 +0300 Subject: [PATCH 9/9] Fix copyright date --- framework/src/modules/reward/calculate_reward.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/framework/src/modules/reward/calculate_reward.ts b/framework/src/modules/reward/calculate_reward.ts index ab02ed260df..d581f9fc7de 100644 --- a/framework/src/modules/reward/calculate_reward.ts +++ b/framework/src/modules/reward/calculate_reward.ts @@ -1,5 +1,5 @@ /* - * Copyright © 2020 Lisk Foundation + * Copyright © 2021 Lisk Foundation * * See the LICENSE file at the top-level directory of this distribution * for licensing information.