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

Commit

Permalink
Merge pull request #5314 from LiskHQ/5257-update_db_usage
Browse files Browse the repository at this point in the history
Update lisk-chain to use lisk-db - Closes #5257
  • Loading branch information
shuse2 authored May 14, 2020
2 parents 256d7df + 232396c commit 8fef52a
Show file tree
Hide file tree
Showing 57 changed files with 2,689 additions and 2,743 deletions.
1 change: 1 addition & 0 deletions elements/lisk-chain/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
},
"dependencies": {
"@liskhq/lisk-cryptography": "2.5.0-alpha.0",
"@liskhq/lisk-db": "0.1.0",
"@liskhq/lisk-transactions": "4.0.0-alpha.0",
"@types/node": "12.12.11",
"debug": "4.1.1",
Expand Down
173 changes: 61 additions & 112 deletions elements/lisk-chain/src/chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
* Removal or modification of this copyright notice is prohibited.
*/

import { KVStore } from '@liskhq/lisk-db';
import {
BaseTransaction,
Status as TransactionStatus,
Expand Down Expand Up @@ -56,8 +57,6 @@ import {
BlockRewardOptions,
Contexter,
MatcherTransaction,
Storage,
StorageTransaction,
GenesisBlock,
GenesisBlockJSON,
} from './types';
Expand All @@ -77,7 +76,7 @@ import {

interface ChainConstructor {
// Components
readonly storage: Storage;
readonly db: KVStore;
// Unique requirements
readonly genesisBlock: GenesisBlockJSON;
// Modules
Expand All @@ -100,27 +99,6 @@ interface ChainConstructor {

const TRANSACTION_TYPES_VOTE = [3, 11];

const saveBlock = async (
storage: Storage,
blockJSON: BlockJSON,
tx: StorageTransaction,
): Promise<void> => {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (!tx) {
throw new Error('Block should only be saved in a database tx');
}
// If there is already a running transaction use it
const promises = [storage.entities.Block.create(blockJSON, {}, tx)];

if (blockJSON.transactions.length) {
promises.push(
storage.entities.Transaction.create(blockJSON.transactions, {}, tx),
);
}

return tx.batch(promises);
};

const applyConfirmedStep = async (
blockInstance: BlockInstance,
stateStore: StateStore,
Expand Down Expand Up @@ -197,7 +175,7 @@ export class Chain {

private _lastBlock: BlockInstance;
private readonly blocksVerify: BlocksVerify;
private readonly storage: Storage;
private readonly _db: KVStore;
private readonly _networkIdentifier: string;
private readonly blockRewardArgs: BlockRewardOptions;
private readonly genesisBlock: GenesisBlock;
Expand All @@ -210,7 +188,7 @@ export class Chain {

public constructor({
// Components
storage,
db,
// Unique requirements
genesisBlock,
// Modules
Expand All @@ -230,9 +208,9 @@ export class Chain {
}: ChainConstructor) {
this.events = new EventEmitter();

this.storage = storage;
this._db = db;
this.dataAccess = new DataAccess({
dbStorage: storage,
db,
registeredTransactions,
minBlockHeaderCache,
maxBlockHeaderCache,
Expand Down Expand Up @@ -303,9 +281,10 @@ export class Chain {

public async init(): Promise<void> {
// Check mem tables
const genesisBlock = await this.dataAccess.getBlockHeaderByHeight(1);

if (!genesisBlock) {
let genesisBlock: BlockHeader;
try {
genesisBlock = await this.dataAccess.getBlockHeaderByHeight(1);
} catch (error) {
throw new Error('Failed to load genesis block');
}

Expand All @@ -315,8 +294,10 @@ export class Chain {
throw new Error('Genesis block does not match');
}

const storageLastBlock = await this.dataAccess.getLastBlock();
if (!storageLastBlock) {
let storageLastBlock: BlockInstance;
try {
storageLastBlock = await this.dataAccess.getLastBlock();
} catch (error) {
throw new Error('Failed to load last block');
}

Expand Down Expand Up @@ -347,7 +328,7 @@ export class Chain {
lastBlockHeaders[0]?.height ?? 1,
);

return new StateStore(this.storage, {
return new StateStore(this.dataAccess, {
networkIdentifier: this._networkIdentifier,
lastBlockHeaders,
lastBlockReward,
Expand Down Expand Up @@ -378,8 +359,7 @@ export class Chain {
}

public async resetState(): Promise<void> {
await this.storage.entities.Account.resetMemTables();
await this.storage.entities.ConsensusState.delete();
await this.dataAccess.resetMemTables();
this.dataAccess.resetBlockHeaderCache();
}

Expand All @@ -391,7 +371,7 @@ export class Chain {
verifyPreviousBlockId(blockInstance, this._lastBlock, this.genesisBlock);
validateBlockSlot(blockInstance, this._lastBlock, this.slots);
if (!skipExistingCheck) {
await verifyBlockNotExists(this.storage, blockInstance);
await verifyBlockNotExists(this.dataAccess, blockInstance);
const transactionsResponses = await checkPersistedTransactions(
this.dataAccess,
)(blockInstance.transactions);
Expand Down Expand Up @@ -432,26 +412,27 @@ export class Chain {
removeFromTempTable: false,
},
): Promise<void> {
return this.storage.entities.Block.begin('saveBlock', async tx => {
await stateStore.finalize(tx);
if (!saveOnlyState) {
const blockJSON = this.serialize(blockInstance);
await saveBlock(this.storage, blockJSON, tx);
}
if (removeFromTempTable) {
await this.removeBlockFromTempTable(blockInstance.id, tx);
}
this.dataAccess.addBlockHeader(blockInstance);
this._lastBlock = blockInstance;

const accounts = stateStore.account
.getUpdated()
.map(anAccount => anAccount.toJSON());
const accounts = stateStore.account
.getUpdated()
.map(anAccount => anAccount.toJSON());

if (saveOnlyState) {
const batch = this._db.batch();
stateStore.finalize(batch);
await batch.write();
} else {
await this.dataAccess.saveBlock(
blockInstance,
stateStore,
removeFromTempTable,
);
}
this.dataAccess.addBlockHeader(blockInstance);
this._lastBlock = blockInstance;

this.events.emit(EVENT_NEW_BLOCK, {
block: this.serialize(blockInstance),
accounts,
});
this.events.emit(EVENT_NEW_BLOCK, {
block: this.serialize(blockInstance),
accounts,
});
}

Expand All @@ -469,48 +450,34 @@ export class Chain {
stateStore: StateStore,
{ saveTempBlock } = { saveTempBlock: false },
): Promise<void> {
await this.storage.entities.Block.begin('revertBlock', async tx => {
const secondLastBlock = await this._deleteLastBlock(block, tx);

if (saveTempBlock) {
const blockJSON = this.serialize(block);
const blockTempEntry = {
id: blockJSON.id,
height: blockJSON.height,
fullBlock: blockJSON,
};
await this.storage.entities.TempBlock.create(blockTempEntry, {}, tx);
}
await stateStore.finalize(tx);
await this.dataAccess.removeBlockHeader(block.id);
this._lastBlock = secondLastBlock;

const accounts = stateStore.account
.getUpdated()
.map(anAccount => anAccount.toJSON());

this.events.emit(EVENT_DELETE_BLOCK, {
block: this.serialize(block),
accounts,
});
});
}
if (block.height === 1) {
throw new Error('Cannot delete genesis block');
}
let secondLastBlock: BlockInstance;
try {
secondLastBlock = await this.dataAccess.getBlockByID(
block.previousBlockId,
);
} catch (error) {
throw new Error('PreviousBlock is null');
}

public async removeBlockFromTempTable(
blockId: string,
tx: StorageTransaction,
): Promise<void> {
return this.storage.entities.TempBlock.delete({ id: blockId }, {}, tx);
await this.dataAccess.deleteBlock(block, stateStore, saveTempBlock);
await this.dataAccess.removeBlockHeader(block.id);
this._lastBlock = secondLastBlock;

const accounts = stateStore.account
.getUpdated()
.map(anAccount => anAccount.toJSON());

this.events.emit(EVENT_DELETE_BLOCK, {
block: this.serialize(block),
accounts,
});
}

public async exists(block: BlockInstance): Promise<boolean> {
try {
await verifyBlockNotExists(this.storage, block);

return false;
} catch (err) {
return true;
}
return this.dataAccess.isBlockPersisted(block.id);
}

public async getHighestCommonBlock(
Expand Down Expand Up @@ -640,22 +607,4 @@ export class Chain {
this.dataAccess.addBlockHeader(blockHeader);
}
}

private async _deleteLastBlock(
lastBlock: BlockInstance,
tx?: StorageTransaction,
): Promise<BlockInstance> {
if (lastBlock.height === 1) {
throw new Error('Cannot delete genesis block');
}
const block = await this.dataAccess.getBlockByID(lastBlock.previousBlockId);

if (!block) {
throw new Error('PreviousBlock is null');
}

await this.storage.entities.Block.delete({ id: lastBlock.id }, {}, tx);

return block;
}
}
2 changes: 1 addition & 1 deletion elements/lisk-chain/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
* Removal or modification of this copyright notice is prohibited.
*/

export const CHAIN_STATE_BURNT_FEE = 'chain:burntFee';
export const CHAIN_STATE_BURNT_FEE = 'burntFee';

export const DEFAULT_MIN_BLOCK_HEADER_CACHE = 309;
export const DEFAULT_MAX_BLOCK_HEADER_CACHE = 515;
Expand Down
22 changes: 22 additions & 0 deletions elements/lisk-chain/src/data_access/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* 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.
*/

export const DB_KEY_BLOCKS_ID = 'blocks:id';
export const DB_KEY_BLOCKS_HEIGHT = 'blocks:height';
export const DB_KEY_TRANSACTIONS_BLOCK_ID = 'transactions:blockID';
export const DB_KEY_TRANSACTIONS_ID = 'transactions:id';
export const DB_KEY_TEMPBLOCKS_HEIGHT = 'tempBlocks:height';
export const DB_KEY_ACCOUNTS_ADDRESS = 'accounts:address';
export const DB_KEY_CHAIN_STATE = 'chain';
export const DB_KEY_CONSENSUS_STATE = 'consensus';
Loading

0 comments on commit 8fef52a

Please sign in to comment.