This repository has been archived by the owner on Jun 11, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 457
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #6833 from LiskHQ/6720-dpos-endpoint
- v6.1.0
- v6.1.0-rc.0
- v6.1.0-beta.1
- v6.1.0-beta.0
- v6.0.2
- v6.0.1
- v6.0.0
- v6.0.0-rc.5
- v6.0.0-rc.4
- v6.0.0-rc.3
- v6.0.0-rc.2
- v6.0.0-rc.1
- v6.0.0-rc.1-1
- v6.0.0-rc.0
- v6.0.0-beta.7
- v6.0.0-beta.6
- v6.0.0-beta.5
- v6.0.0-beta.4
- v6.0.0-beta.3
- v6.0.0-beta.2
- v6.0.0-beta.1
- v6.0.0-beta.0
- v6.0.0-alpha.22
- v6.0.0-alpha.21
- v6.0.0-alpha.20
- v6.0.0-alpha.19
- v6.0.0-alpha.18
- v6.0.0-alpha.17
- v6.0.0-alpha.16
- v6.0.0-alpha.15
- v6.0.0-alpha.14
- v6.0.0-alpha.13
- v6.0.0-alpha.12
- v6.0.0-alpha.11
- v6.0.0-alpha.10
- v6.0.0-alpha.9
- v6.0.0-alpha.8
- v6.0.0-alpha.7
- v6.0.0-alpha.6
- v6.0.0-alpha.5
- v6.0.0-alpha.4
- v6.0.0-alpha.3
- v6.0.0-alpha.2
- v6.0.0-alpha.1
- v6.0.0-alpha.0
Showing
7 changed files
with
478 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
/* | ||
* 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 { StateStore } from '@liskhq/lisk-chain'; | ||
import { getRandomBytes } from '@liskhq/lisk-cryptography'; | ||
import { InMemoryKVStore } from '@liskhq/lisk-db'; | ||
import { DPoSAPI } from '../../../../src/modules/dpos_v2/api'; | ||
import { | ||
MODULE_ID_DPOS, | ||
STORE_PREFIX_DELEGATE, | ||
STORE_PREFIX_NAME, | ||
STORE_PREFIX_VOTER, | ||
} from '../../../../src/modules/dpos_v2/constants'; | ||
import { | ||
delegateStoreSchema, | ||
nameStoreSchema, | ||
voterStoreSchema, | ||
} from '../../../../src/modules/dpos_v2/schemas'; | ||
import { APIContext } from '../../../../src/node/state_machine/api_context'; | ||
import { EventQueue } from '../../../../src/node/state_machine'; | ||
|
||
describe('DposModuleApi', () => { | ||
let dposAPI: DPoSAPI; | ||
let apiContext: APIContext; | ||
let stateStore: StateStore; | ||
let voterSubStore: StateStore; | ||
let delegateSubStore: StateStore; | ||
let nameSubStore: StateStore; | ||
const address = getRandomBytes(20); | ||
const voterData = { | ||
sentVotes: [ | ||
{ | ||
delegateAddress: getRandomBytes(20), | ||
amount: BigInt(0), | ||
}, | ||
], | ||
pendingUnlocks: [ | ||
{ | ||
delegateAddress: getRandomBytes(20), | ||
amount: BigInt(0), | ||
unvoteHeight: 0, | ||
}, | ||
], | ||
}; | ||
|
||
const delegateData = { | ||
name: 'delegate1', | ||
totalVotesReceived: BigInt(0), | ||
selfVotes: BigInt(0), | ||
lastGeneratedHeight: 0, | ||
isBanned: false, | ||
pomHeights: [0], | ||
consecutiveMissedBlocks: 0, | ||
}; | ||
|
||
beforeEach(() => { | ||
dposAPI = new DPoSAPI(MODULE_ID_DPOS); | ||
stateStore = new StateStore(new InMemoryKVStore()); | ||
voterSubStore = stateStore.getStore(dposAPI['moduleID'], STORE_PREFIX_VOTER); | ||
delegateSubStore = stateStore.getStore(dposAPI['moduleID'], STORE_PREFIX_DELEGATE); | ||
nameSubStore = stateStore.getStore(dposAPI['moduleID'], STORE_PREFIX_NAME); | ||
}); | ||
|
||
describe('isNameAvailable', () => { | ||
describe('when name already exists', () => { | ||
it('should return false', async () => { | ||
await nameSubStore.setWithSchema(Buffer.from(delegateData.name), {}, nameStoreSchema); | ||
apiContext = new APIContext({ stateStore, eventQueue: new EventQueue() }); | ||
await expect(dposAPI.isNameAvailable(apiContext, delegateData.name)).resolves.toBeFalse(); | ||
}); | ||
}); | ||
|
||
describe('when name does not exist and exceeds the maximum length', () => { | ||
it('should return false', async () => { | ||
apiContext = new APIContext({ stateStore, eventQueue: new EventQueue() }); | ||
await expect( | ||
dposAPI.isNameAvailable( | ||
apiContext, | ||
'nnwkfnwkfnkwrnfkrnfeknekerfnkjenejnfekfnekfnjkdnwknw', | ||
), | ||
).resolves.toBeFalse(); | ||
}); | ||
}); | ||
|
||
describe('when name does not exist and has length less than 1', () => { | ||
it('should return false', async () => { | ||
apiContext = new APIContext({ stateStore, eventQueue: new EventQueue() }); | ||
await expect(dposAPI.isNameAvailable(apiContext, '')).resolves.toBeFalse(); | ||
}); | ||
}); | ||
|
||
describe('when name does not exist and contains invalid symbol', () => { | ||
it('should return false', async () => { | ||
apiContext = new APIContext({ stateStore, eventQueue: new EventQueue() }); | ||
await expect( | ||
dposAPI.isNameAvailable(apiContext, 'Ajldnfdf-_.dv$%&^#'), | ||
).resolves.toBeFalse(); | ||
}); | ||
}); | ||
|
||
describe('when name does not exist and is a valid name', () => { | ||
it('should return true', async () => { | ||
apiContext = new APIContext({ stateStore, eventQueue: new EventQueue() }); | ||
await expect( | ||
dposAPI.isNameAvailable(apiContext, 'abcdefghijklmnopqrstuvwxyz0123456789!@$&_.'), | ||
).resolves.toBeFalse(); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('getVoter', () => { | ||
describe('when input address is valid', () => { | ||
it('should return correct voter data corresponding to the input address', async () => { | ||
await voterSubStore.setWithSchema(address, voterData, voterStoreSchema); | ||
apiContext = new APIContext({ stateStore, eventQueue: new EventQueue() }); | ||
const voterDataReturned = await dposAPI.getVoter(apiContext, address); | ||
|
||
expect(voterDataReturned).toStrictEqual(voterData); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('getDelegate', () => { | ||
describe('when input address is valid', () => { | ||
it('should return correct delegate data corresponding to the input address', async () => { | ||
await delegateSubStore.setWithSchema(address, delegateData, delegateStoreSchema); | ||
apiContext = new APIContext({ stateStore, eventQueue: new EventQueue() }); | ||
const delegateDataReturned = await dposAPI.getDelegate(apiContext, address); | ||
|
||
expect(delegateDataReturned).toStrictEqual(delegateData); | ||
}); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
/* | ||
* 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 { StateStore } from '@liskhq/lisk-chain'; | ||
import { getRandomBytes } from '@liskhq/lisk-cryptography'; | ||
import { InMemoryKVStore } from '@liskhq/lisk-db'; | ||
import { codec } from '@liskhq/lisk-codec'; | ||
import { Logger } from '../../../../src/logger'; | ||
import { | ||
MODULE_ID_DPOS, | ||
STORE_PREFIX_DELEGATE, | ||
STORE_PREFIX_VOTER, | ||
} from '../../../../src/modules/dpos_v2/constants'; | ||
import { DPoSEndpoint } from '../../../../src/modules/dpos_v2/endpoint'; | ||
import { delegateStoreSchema, voterStoreSchema } from '../../../../src/modules/dpos_v2/schemas'; | ||
import { fakeLogger } from '../../../utils/node'; | ||
|
||
describe('DposModuleEndpoint', () => { | ||
const logger: Logger = fakeLogger; | ||
let dposEndpoint: DPoSEndpoint; | ||
let stateStore: StateStore; | ||
let voterSubStore: StateStore; | ||
let delegateSubStore: StateStore; | ||
const address = getRandomBytes(20); | ||
const address1 = getRandomBytes(20); | ||
const address2 = getRandomBytes(20); | ||
const getStore1 = jest.fn(); | ||
const networkIdentifier = Buffer.alloc(0); | ||
const voterData = { | ||
sentVotes: [ | ||
{ | ||
delegateAddress: getRandomBytes(20), | ||
amount: BigInt(0), | ||
}, | ||
], | ||
pendingUnlocks: [ | ||
{ | ||
delegateAddress: getRandomBytes(20), | ||
amount: BigInt(0), | ||
unvoteHeight: 0, | ||
}, | ||
], | ||
}; | ||
|
||
const delegateData = { | ||
name: 'delegate1', | ||
totalVotesReceived: BigInt(0), | ||
selfVotes: BigInt(0), | ||
lastGeneratedHeight: 0, | ||
isBanned: false, | ||
pomHeights: [0], | ||
consecutiveMissedBlocks: 0, | ||
}; | ||
|
||
beforeEach(() => { | ||
dposEndpoint = new DPoSEndpoint(MODULE_ID_DPOS); | ||
stateStore = new StateStore(new InMemoryKVStore()); | ||
voterSubStore = stateStore.getStore(dposEndpoint['moduleID'], STORE_PREFIX_VOTER); | ||
delegateSubStore = stateStore.getStore(dposEndpoint['moduleID'], STORE_PREFIX_DELEGATE); | ||
}); | ||
|
||
describe('getVoter', () => { | ||
describe('when input address is valid', () => { | ||
it('should return correct voter data corresponding to the input address', async () => { | ||
await voterSubStore.setWithSchema(address, voterData, voterStoreSchema); | ||
getStore1.mockReturnValue(voterSubStore); | ||
const voterDataReturned = await dposEndpoint.getVoter({ | ||
getStore: getStore1, | ||
logger, | ||
params: { | ||
address: address.toString('hex'), | ||
}, | ||
networkIdentifier, | ||
}); | ||
|
||
expect(voterDataReturned).toStrictEqual(codec.toJSON(voterStoreSchema, voterData)); | ||
}); | ||
|
||
it('should return valid JSON output', async () => { | ||
await voterSubStore.setWithSchema(address, voterData, voterStoreSchema); | ||
getStore1.mockReturnValue(voterSubStore); | ||
const voterDataReturned = await dposEndpoint.getVoter({ | ||
getStore: getStore1, | ||
logger, | ||
params: { | ||
address: address.toString('hex'), | ||
}, | ||
networkIdentifier, | ||
}); | ||
|
||
expect(voterDataReturned.sentVotes[0].delegateAddress).toBeString(); | ||
expect(voterDataReturned.sentVotes[0].amount).toBeString(); | ||
expect(voterDataReturned.pendingUnlocks[0].delegateAddress).toBeString(); | ||
expect(voterDataReturned.pendingUnlocks[0].amount).toBeString(); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('getDelegate', () => { | ||
describe('when input address is valid', () => { | ||
it('should return correct delegate data corresponding to the input address', async () => { | ||
await delegateSubStore.setWithSchema(address, delegateData, delegateStoreSchema); | ||
getStore1.mockReturnValue(delegateSubStore); | ||
const delegateDataReturned = await dposEndpoint.getDelegate({ | ||
getStore: getStore1, | ||
logger, | ||
params: { | ||
address: address.toString('hex'), | ||
}, | ||
networkIdentifier, | ||
}); | ||
|
||
const delegateDataJSON = { | ||
...delegateData, | ||
totalVotesReceived: delegateData.totalVotesReceived.toString(), | ||
selfVotes: delegateData.selfVotes.toString(), | ||
}; | ||
|
||
expect(delegateDataReturned).toStrictEqual(delegateDataJSON); | ||
}); | ||
|
||
it('should return valid JSON output', async () => { | ||
await delegateSubStore.setWithSchema(address, delegateData, delegateStoreSchema); | ||
getStore1.mockReturnValue(delegateSubStore); | ||
const delegateDataReturned = await dposEndpoint.getDelegate({ | ||
getStore: getStore1, | ||
logger, | ||
params: { | ||
address: address.toString('hex'), | ||
}, | ||
networkIdentifier, | ||
}); | ||
|
||
expect(delegateDataReturned.totalVotesReceived).toBeString(); | ||
expect(delegateDataReturned.selfVotes).toBeString(); | ||
}); | ||
}); | ||
}); | ||
|
||
describe('getAllDelegates', () => { | ||
describe('when input address is valid', () => { | ||
it('should return correct data for all delegates', async () => { | ||
await delegateSubStore.setWithSchema(address1, delegateData, delegateStoreSchema); | ||
await delegateSubStore.setWithSchema(address2, delegateData, delegateStoreSchema); | ||
getStore1.mockReturnValue(delegateSubStore); | ||
const delegatesDataReturned = await dposEndpoint.getAllDelegates({ | ||
getStore: getStore1, | ||
logger, | ||
params: {}, | ||
networkIdentifier, | ||
}); | ||
|
||
expect(delegatesDataReturned[0]).toStrictEqual( | ||
codec.toJSON(delegateStoreSchema, delegateData), | ||
); | ||
expect(delegatesDataReturned[1]).toStrictEqual( | ||
codec.toJSON(delegateStoreSchema, delegateData), | ||
); | ||
}); | ||
|
||
it('should return valid JSON output', async () => { | ||
await delegateSubStore.setWithSchema(address, delegateData, delegateStoreSchema); | ||
await delegateSubStore.setWithSchema(address1, delegateData, delegateStoreSchema); | ||
getStore1.mockReturnValue(delegateSubStore); | ||
const delegatesDataReturned = await dposEndpoint.getAllDelegates({ | ||
getStore: getStore1, | ||
logger, | ||
params: {}, | ||
networkIdentifier, | ||
}); | ||
|
||
expect(delegatesDataReturned[0].totalVotesReceived).toBeString(); | ||
expect(delegatesDataReturned[0].selfVotes).toBeString(); | ||
expect(delegatesDataReturned[1].totalVotesReceived).toBeString(); | ||
expect(delegatesDataReturned[1].selfVotes).toBeString(); | ||
}); | ||
}); | ||
}); | ||
}); |