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

Commit

Permalink
Merge branch 'release/6.0.0' of https://github.com/LiskHQ/lisk-sdk in…
Browse files Browse the repository at this point in the history
…to development
  • Loading branch information
shuse2 committed May 12, 2023
2 parents 50c3a4b + 7dfc80d commit 475be59
Show file tree
Hide file tree
Showing 20 changed files with 325 additions and 23 deletions.
13 changes: 13 additions & 0 deletions commander/src/utils/genesis_creation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
import { Schema } from '@liskhq/lisk-codec';
import { address } from '@liskhq/lisk-cryptography';
import {
genesisInteroperabilitySchema,
MODULE_NAME_INTEROPERABILITY,
posGenesisStoreSchema,
PoSModule,
tokenGenesisStoreSchema,
Expand Down Expand Up @@ -133,6 +135,17 @@ export const generateGenesisBlockDefaultPoSAssets = (input: GenesisBlockDefaultA
} as Record<string, unknown>,
schema: posGenesisStoreSchema,
},
{
module: MODULE_NAME_INTEROPERABILITY,
data: {
ownChainName: '',
ownChainNonce: 0,
chainInfos: [],
terminatedStateAccounts: [],
terminatedOutboxAccounts: [],
},
schema: genesisInteroperabilitySchema,
},
];

return {
Expand Down
51 changes: 51 additions & 0 deletions commander/test/utils/genesis_creation.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* LiskHQ/lisk-commander
* Copyright © 2023 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 { Application } from 'lisk-framework';
import { codec } from '@liskhq/lisk-codec';
import { generateGenesisBlockDefaultPoSAssets } from '../../src/utils/genesis_creation';

describe('genesis creation', () => {
describe('generateGenesisBlockDefaultPoSAssets', () => {
const chainID = Buffer.from([2, 0, 0, 0]);
it('should create processable genesis block', async () => {
const { genesisAssets } = generateGenesisBlockDefaultPoSAssets({
chainID: chainID.toString('hex'),
keysList: [],
numberOfValidators: 101,
tokenDistribution: BigInt('100000000000000'),
});

const { app } = Application.defaultApplication({
genesis: {
chainID: chainID.toString('hex'),
},
});

const genesisBlock = await app.generateGenesisBlock({
assets: genesisAssets.map(a => ({
module: a.module,
data: codec.fromJSON(a.schema, a.data),
schema: a.schema,
})),
chainID,
});
const assetsJSON = genesisBlock.assets.toJSON();
expect(assetsJSON.map(a => a.module)).toEqual(['interoperability', 'pos', 'token']);
expect(assetsJSON.map(a => a.data).every(d => typeof d === 'string')).toBe(true);
});
});
});
18 changes: 17 additions & 1 deletion elements/lisk-chain/src/block_header.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,13 @@ import { ed, utils } from '@liskhq/lisk-cryptography';
import { codec } from '@liskhq/lisk-codec';
import { validator, LiskValidationError } from '@liskhq/lisk-validator';
import { LiskErrorObject } from '@liskhq/lisk-validator/dist-node/types';
import { EMPTY_BUFFER, EMPTY_HASH, SIGNATURE_LENGTH_BYTES, TAG_BLOCK_HEADER } from './constants';
import {
EMPTY_BUFFER,
EMPTY_HASH,
LENGTH_ADDRESS,
SIGNATURE_LENGTH_BYTES,
TAG_BLOCK_HEADER,
} from './constants';
import { blockHeaderSchema, blockHeaderSchemaWithId, signingBlockHeaderSchema } from './schema';
import { JSONObject } from './types';

Expand Down Expand Up @@ -205,6 +211,16 @@ export class BlockHeader {
});
}

if (!header.generatorAddress.equals(Buffer.alloc(LENGTH_ADDRESS))) {
errors.push({
message: 'Genesis block header generator address must only contain zero bytes',
keyword: 'const',
dataPath: 'header.generatorAddress',
schemaPath: 'properties.generatorAddress',
params: { allowedValue: Buffer.alloc(LENGTH_ADDRESS) },
});
}

if (!header.transactionRoot.equals(EMPTY_HASH)) {
errors.push({
message: 'Genesis block header transaction root must be empty hash',
Expand Down
1 change: 1 addition & 0 deletions elements/lisk-chain/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const DEFAULT_MAX_BLOCK_HEADER_CACHE = 515;

export const EMPTY_BUFFER = Buffer.alloc(0);
export const EMPTY_HASH = utils.hash(EMPTY_BUFFER);
export const LENGTH_ADDRESS = 20;
export const MAX_UINT32 = 4294967295;

export const GENESIS_BLOCK_VERSION = 0;
Expand Down
12 changes: 12 additions & 0 deletions elements/lisk-chain/test/unit/block_header.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,18 @@ describe('block_header', () => {
);
});

it('should throw error if generatorAddress is not zero bytes', () => {
const block = getGenesisBlockAttrs();
const blockHeader = new BlockHeader({
...block,
generatorAddress: utils.getRandomBytes(20),
});

expect(() => blockHeader.validateGenesis()).toThrow(
'Genesis block header generator address must only contain zero bytes',
);
});

it('should throw error if transactionRoot is not empty hash', () => {
const block = getGenesisBlockAttrs();
const blockHeader = new BlockHeader({
Expand Down
12 changes: 6 additions & 6 deletions elements/lisk-p2p/src/utils/network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,14 +142,14 @@ export const expirePeerFromBucket = (
thresholdTime: number,
): P2PEnhancedPeerInfo | undefined => {
for (const [peerId, peer] of bucket) {
const timeDifference = Math.round(
Math.abs((peer.dateAdded as Date).getTime() - new Date().getTime()),
);
if (peer.dateAdded) {
const timeDifference = Math.round(Math.abs(new Date().getTime() - peer.dateAdded.getTime()));

if (timeDifference >= thresholdTime) {
bucket.delete(peerId);
if (timeDifference >= thresholdTime) {
bucket.delete(peerId);

return peer;
return peer;
}
}
}

Expand Down
53 changes: 48 additions & 5 deletions elements/lisk-p2p/test/unit/utils/network.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@ import {
NETWORK,
getBucketId,
PEER_TYPE,
expirePeerFromBucket,
} from '../../../src/utils';
import { DEFAULT_RANDOM_SECRET } from '../../../src/constants';
import { DEFAULT_EVICTION_THRESHOLD_TIME, DEFAULT_RANDOM_SECRET } from '../../../src/constants';
import { initPeerInfoList } from '../../utils/peers';
import { P2PEnhancedPeerInfo } from '../../../src/types';

describe('utils/network', () => {
const MAX_GROUP_NUM = 255;
Expand Down Expand Up @@ -140,11 +143,51 @@ describe('utils/network', () => {
});

describe('#expirePeerFromBucket', () => {
describe('when bucket contains old peers', () => {
it.todo('should return the evicted peer info');
let peerBucket: Map<string, P2PEnhancedPeerInfo>;
const peers = initPeerInfoList();

beforeEach(() => {
peerBucket = new Map<string, P2PEnhancedPeerInfo>();

for (const p of peers) {
peerBucket.set(p?.peerId, {
...p,
dateAdded: new Date(),
});
}
});

it('should return the evicted peer info when bucket contains old peers', () => {
const peer1 = peerBucket.get(peers[0].peerId) as P2PEnhancedPeerInfo;
const timeNow = new Date();
const oneDayOldTime = new Date(timeNow.getTime() - (DEFAULT_EVICTION_THRESHOLD_TIME + 1000));
const oldPeer = {
...peer1,
dateAdded: oneDayOldTime,
};
peerBucket.set(peer1?.peerId, oldPeer);
expect(expirePeerFromBucket(peerBucket, DEFAULT_EVICTION_THRESHOLD_TIME)).toEqual(oldPeer);
});

it('should return undefined when bucket does not contains old peers', () => {
for (const p of peers) {
peerBucket.set(p?.peerId, {
...p,
dateAdded: new Date(),
});
}
expect(expirePeerFromBucket(peerBucket, DEFAULT_EVICTION_THRESHOLD_TIME)).toBeUndefined();
});
describe('when bucket does not contains old peers', () => {
it.todo('should return undefined');

it("should return undefined when peers don't have dateAdded field", () => {
const peerBucketWithoutDateAdded = new Map<string, P2PEnhancedPeerInfo>();
const peerInfoList = initPeerInfoList();
for (const p of peerInfoList) {
peerBucketWithoutDateAdded.set(p?.peerId, p);
}
expect(
expirePeerFromBucket(peerBucketWithoutDateAdded, DEFAULT_EVICTION_THRESHOLD_TIME),
).toBeUndefined();
});
});

Expand Down
16 changes: 8 additions & 8 deletions framework/src/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ export class Application {
const authModule = new AuthModule();
const tokenModule = new TokenModule();
const feeModule = new FeeModule();
const rewardModule = new DynamicRewardModule();
const dynamicRewardModule = new DynamicRewardModule();
const randomModule = new RandomModule();
const validatorModule = new ValidatorsModule();
const posModule = new PoSModule();
Expand All @@ -179,7 +179,7 @@ export class Application {

// resolve dependencies
feeModule.addDependencies(tokenModule.method, interoperabilityModule.method);
rewardModule.addDependencies(
dynamicRewardModule.addDependencies(
tokenModule.method,
randomModule.method,
validatorModule.method,
Expand All @@ -197,15 +197,15 @@ export class Application {
interoperabilityModule.registerInteroperableModule(tokenModule);
interoperabilityModule.registerInteroperableModule(feeModule);

// register modules
application._registerModule(feeModule); // fee should be registered first to call beforeTransactionsExecute first
// Register modules in the sequence defined in LIP0063 https://github.com/LiskHQ/lips/blob/main/proposals/lip-0063.md#modules
application._registerModule(authModule);
application._registerModule(validatorModule);
application._registerModule(tokenModule);
application._registerModule(rewardModule);
application._registerModule(randomModule);
application._registerModule(posModule);
application._registerModule(feeModule);
application._registerModule(interoperabilityModule);
application._registerModule(posModule);
application._registerModule(randomModule);
application._registerModule(dynamicRewardModule);

return {
app: application,
Expand All @@ -216,7 +216,7 @@ export class Application {
fee: feeModule.method,
pos: posModule.method,
random: randomModule.method,
reward: rewardModule.method,
reward: dynamicRewardModule.method,
interoperability: interoperabilityModule.method,
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export class CommitPool {
private readonly _gossipedCommits: CommitList;
private readonly _blockTime: number;
private readonly _bftMethod: BFTMethod;
private readonly _minCertifyHeight: number;
private readonly _chain: Chain;
private readonly _network: Network;
private readonly _db: Database;
Expand All @@ -56,6 +57,7 @@ export class CommitPool {
public constructor(config: CommitPoolConfig) {
this._blockTime = config.blockTime;
this._bftMethod = config.bftMethod;
this._minCertifyHeight = config.minCertifyHeight;
this._chain = config.chain;
this._network = config.network;
this._db = config.db;
Expand Down Expand Up @@ -209,11 +211,17 @@ export class CommitPool {
return false;
}

// The heights of aggregate commits must be greater than or equal to MIN_CERTIFY_HEIGHT.
if (aggregateCommit.height < this._minCertifyHeight) {
return false;
}

try {
const heightNextBFTParameters = await this._bftMethod.getNextHeightBFTParameters(
let heightNextBFTParameters = await this._bftMethod.getNextHeightBFTParameters(
stateStore,
maxHeightCertified + 1,
);
heightNextBFTParameters = Math.max(heightNextBFTParameters, this._minCertifyHeight + 1);

if (aggregateCommit.height > heightNextBFTParameters - 1) {
return false;
Expand Down Expand Up @@ -307,15 +315,16 @@ export class CommitPool {
methodContext,
maxHeightCertified + 1,
);
heightNextBFTParameters = Math.max(heightNextBFTParameters, this._minCertifyHeight + 1);
nextHeight = Math.min(heightNextBFTParameters - 1, maxHeightPrecommitted);
} catch (err) {
if (!(err instanceof BFTParameterNotFoundError)) {
throw err;
}
nextHeight = maxHeightPrecommitted;
}

while (nextHeight > maxHeightCertified) {
const certifyUptoHeight = Math.max(maxHeightCertified, this._minCertifyHeight - 1);
while (nextHeight > certifyUptoHeight) {
const singleCommits = [
...this._nonGossipedCommits.getByHeight(nextHeight),
...this._nonGossipedCommitsLocal.getByHeight(nextHeight),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export interface SingleCommit {
export interface CommitPoolConfig {
readonly network: Network;
readonly blockTime: number;
readonly minCertifyHeight: number;
readonly bftMethod: BFTMethod;
readonly chain: Chain;
readonly db: Database;
Expand Down
2 changes: 2 additions & 0 deletions framework/src/engine/consensus/consensus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ export class Consensus {
this._commitPool = new CommitPool({
db: this._db,
blockTime: this._genesisConfig.blockTime,
minCertifyHeight: this._genesisConfig.minimumCertifyHeight,
bftMethod: this._bft.method,
chain: this._chain,
network: this._network,
Expand Down Expand Up @@ -234,6 +235,7 @@ export class Consensus {
) {
throw new Error('Genesis block validators hash is invalid');
}
await this._verifyValidatorsHash(stateStore, args.genesisBlock);
await this._verifyEventRoot(args.genesisBlock, genesisEvents);

const batch = new Batch();
Expand Down
3 changes: 3 additions & 0 deletions framework/src/modules/pos/schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
BLS_PUBLIC_KEY_LENGTH,
BLS_POP_LENGTH,
ED25519_PUBLIC_KEY_LENGTH,
MAX_LENGTH_NAME,
} from './constants';

export const validatorRegistrationCommandParamsSchema = {
Expand All @@ -29,6 +30,8 @@ export const validatorRegistrationCommandParamsSchema = {
name: {
dataType: 'string',
fieldNumber: 1,
minLength: 1,
maxLength: MAX_LENGTH_NAME,
},
blsKey: {
dataType: 'bytes',
Expand Down
6 changes: 6 additions & 0 deletions framework/src/schema/application_config_schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,11 @@ export const applicationConfigSchema = {
maximum: 30 * 1024, // Kilo Bytes
description: 'Maximum number of transactions allowed per block',
},
minimumCertifyHeight: {
type: 'integer',
minimum: 1,
description: 'Minimum block height which can be certified',
},
},
additionalProperties: false,
},
Expand Down Expand Up @@ -321,6 +326,7 @@ export const applicationConfigSchema = {
blockTime: 10,
bftBatchSize: 103,
maxTransactionsSize: 15 * 1024, // Kilo Bytes
minimumCertifyHeight: 1,
},
generator: {
keys: {},
Expand Down
1 change: 1 addition & 0 deletions framework/src/testing/fixtures/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const defaultConfig: ApplicationConfig = {
genesis: {
block: {},
bftBatchSize: 103,
minimumCertifyHeight: 0,
blockTime: 10,
chainID: '10000000',
maxTransactionsSize: 15 * 1024, // Kilo Bytes
Expand Down
Loading

0 comments on commit 475be59

Please sign in to comment.