@liskhq/lisk-chain
Advanced tools
Comparing version 0.3.4 to 0.4.0-beta.0
/// <reference types="node" /> | ||
import { Schema } from '@liskhq/lisk-codec'; | ||
import { KVStore } from '@liskhq/lisk-db'; | ||
import { EventEmitter } from 'events'; | ||
import { Database } from '@liskhq/lisk-db'; | ||
import { DataAccess } from './data_access'; | ||
import { Slots } from './slots'; | ||
import { StateStore } from './state_store'; | ||
import { Block, BlockHeader, GenesisBlock, AccountSchema, Validator } from './types'; | ||
import { Transaction } from './transaction'; | ||
import { Block } from './block'; | ||
import { Event } from './event'; | ||
import { CurrentState } from './state_store/smt_store'; | ||
interface ChainConstructor { | ||
readonly db: KVStore; | ||
readonly genesisBlock: GenesisBlock; | ||
readonly accountSchemas: { | ||
[name: string]: AccountSchema; | ||
}; | ||
readonly networkIdentifier: Buffer; | ||
readonly blockTime: number; | ||
readonly maxPayloadLength: number; | ||
readonly rewardDistance: number; | ||
readonly rewardOffset: number; | ||
readonly minFeePerByte: number; | ||
readonly roundLength: number; | ||
readonly baseFees: { | ||
readonly moduleID: number; | ||
readonly assetID: number; | ||
readonly baseFee: string; | ||
}[]; | ||
readonly rewardMilestones: ReadonlyArray<bigint>; | ||
readonly keepEventsForHeights: number; | ||
readonly maxTransactionsSize: number; | ||
readonly minBlockHeaderCache?: number; | ||
readonly maxBlockHeaderCache?: number; | ||
} | ||
interface ChainInitArgs { | ||
readonly db: Database; | ||
readonly chainID: Buffer; | ||
readonly genesisBlock: Block; | ||
} | ||
interface BlockValidationInput { | ||
readonly version: number; | ||
} | ||
export declare class Chain { | ||
readonly dataAccess: DataAccess; | ||
readonly events: EventEmitter; | ||
readonly slots: Slots; | ||
dataAccess: DataAccess; | ||
readonly constants: { | ||
readonly blockTime: number; | ||
readonly maxPayloadLength: number; | ||
readonly rewardDistance: number; | ||
readonly rewardOffset: number; | ||
readonly rewardMilestones: ReadonlyArray<bigint>; | ||
readonly networkIdentifier: Buffer; | ||
readonly minFeePerByte: number; | ||
readonly roundLength: number; | ||
readonly baseFees: { | ||
readonly moduleID: number; | ||
readonly assetID: number; | ||
readonly baseFee: string; | ||
}[]; | ||
readonly maxTransactionsSize: number; | ||
readonly minBlockHeaderCache: number; | ||
readonly maxBlockHeaderCache: number; | ||
readonly keepEventsForHeights: number; | ||
}; | ||
private _lastBlock; | ||
private readonly _genesisHeight; | ||
private readonly _networkIdentifier; | ||
private readonly _blockRewardArgs; | ||
private readonly _accountSchema; | ||
private readonly _blockAssetSchema; | ||
private readonly _defaultAccount; | ||
constructor({ db, genesisBlock, accountSchemas, blockTime, networkIdentifier, maxPayloadLength, rewardDistance, rewardOffset, rewardMilestones, minFeePerByte, baseFees, roundLength, minBlockHeaderCache, maxBlockHeaderCache, }: ChainConstructor); | ||
private _lastBlock?; | ||
private _finalizedHeight?; | ||
private _chainID; | ||
private _genesisHeight; | ||
constructor({ maxTransactionsSize, keepEventsForHeights, minBlockHeaderCache, maxBlockHeaderCache, }: ChainConstructor); | ||
get genesisHeight(): number; | ||
get lastBlock(): Block; | ||
get roundLength(): number; | ||
get accountSchema(): Schema; | ||
get blockAssetSchema(): { | ||
[key: number]: Schema; | ||
}; | ||
init(genesisBlock: GenesisBlock): Promise<void>; | ||
calculateDefaultReward(height: number): bigint; | ||
calculateExpectedReward(blockHeader: BlockHeader, stateStore: StateStore): bigint; | ||
get finalizedHeight(): number; | ||
get chainID(): Buffer; | ||
init(args: ChainInitArgs): void; | ||
loadLastBlocks(genesisBlock: Block): Promise<void>; | ||
resetBlockHeaderCache(): void; | ||
newStateStore(skipLastHeights?: number): Promise<StateStore>; | ||
genesisBlockExist(genesisBlock: GenesisBlock): Promise<boolean>; | ||
isValidSeedReveal(blockHeader: BlockHeader, stateStore: StateStore): boolean; | ||
validateGenesisBlockHeader(block: GenesisBlock): void; | ||
applyGenesisBlock(block: GenesisBlock, stateStore: StateStore): Promise<void>; | ||
validateTransaction(transaction: Transaction): void; | ||
validateBlockHeader(block: Block): void; | ||
verifyBlockHeader(block: Block, stateStore: StateStore): Promise<void>; | ||
saveBlock(block: Block, stateStore: StateStore, finalizedHeight: number, { removeFromTempTable }?: { | ||
genesisBlockExist(genesisBlock: Block): Promise<boolean>; | ||
validateBlock(block: Block, inputs: BlockValidationInput): void; | ||
saveBlock(block: Block, events: Event[], state: CurrentState, finalizedHeight: number, { removeFromTempTable }?: { | ||
removeFromTempTable: boolean; | ||
}): Promise<void>; | ||
removeBlock(block: Block, stateStore: StateStore, { saveTempBlock }?: { | ||
removeBlock(block: Block, state: CurrentState, { saveTempBlock }?: { | ||
saveTempBlock: boolean; | ||
}): Promise<void>; | ||
getValidator(timestamp: number): Promise<Validator>; | ||
getValidators(): Promise<Validator[]>; | ||
setValidators(validators: { | ||
address: Buffer; | ||
isConsensusParticipant: boolean; | ||
}[], stateStore: StateStore, blockHeader: BlockHeader): Promise<void>; | ||
private _cacheBlockHeaders; | ||
private _getLastBootstrapHeight; | ||
private _getGenesisInfo; | ||
} | ||
export {}; |
@@ -7,59 +7,19 @@ "use strict"; | ||
const createDebug = require("debug"); | ||
const events_1 = require("events"); | ||
const lisk_validator_1 = require("@liskhq/lisk-validator"); | ||
const block_reward_1 = require("./block_reward"); | ||
const lisk_tree_1 = require("@liskhq/lisk-tree"); | ||
const constants_1 = require("./constants"); | ||
const data_access_1 = require("./data_access"); | ||
const slots_1 = require("./slots"); | ||
const state_store_1 = require("./state_store"); | ||
const account_1 = require("./utils/account"); | ||
const validate_1 = require("./validate"); | ||
const verify_1 = require("./verify"); | ||
const schema_1 = require("./schema"); | ||
const debug = createDebug('lisk:chain'); | ||
class Chain { | ||
constructor({ db, genesisBlock, accountSchemas, blockTime, networkIdentifier, maxPayloadLength, rewardDistance, rewardOffset, rewardMilestones, minFeePerByte, baseFees, roundLength, minBlockHeaderCache = constants_1.DEFAULT_MIN_BLOCK_HEADER_CACHE, maxBlockHeaderCache = constants_1.DEFAULT_MAX_BLOCK_HEADER_CACHE, }) { | ||
this.events = new events_1.EventEmitter(); | ||
const { default: defaultAccount, ...schema } = account_1.getAccountSchemaWithDefault(accountSchemas); | ||
this._defaultAccount = defaultAccount; | ||
this._accountSchema = schema; | ||
this._blockAssetSchema = schema_1.getRegisteredBlockAssetSchema(this._accountSchema); | ||
constructor({ maxTransactionsSize, keepEventsForHeights = constants_1.DEFAULT_KEEP_EVENTS_FOR_HEIGHTS, minBlockHeaderCache = constants_1.DEFAULT_MIN_BLOCK_HEADER_CACHE, maxBlockHeaderCache = constants_1.DEFAULT_MAX_BLOCK_HEADER_CACHE, }) { | ||
lisk_codec_1.codec.addSchema(schema_1.blockSchema); | ||
lisk_codec_1.codec.addSchema(schema_1.blockHeaderSchema); | ||
lisk_codec_1.codec.addSchema(schema_1.signingBlockHeaderSchema); | ||
for (const assetSchema of Object.values(this._blockAssetSchema)) { | ||
lisk_codec_1.codec.addSchema(assetSchema); | ||
} | ||
lisk_codec_1.codec.addSchema(this._accountSchema); | ||
lisk_codec_1.codec.addSchema(schema_1.stateDiffSchema); | ||
this.dataAccess = new data_access_1.DataAccess({ | ||
db, | ||
registeredBlockHeaders: this._blockAssetSchema, | ||
accountSchema: this._accountSchema, | ||
this.constants = { | ||
maxTransactionsSize, | ||
maxBlockHeaderCache, | ||
minBlockHeaderCache, | ||
maxBlockHeaderCache, | ||
}); | ||
this._lastBlock = genesisBlock; | ||
this._networkIdentifier = networkIdentifier; | ||
this.slots = new slots_1.Slots({ | ||
genesisBlockTimestamp: genesisBlock.header.timestamp, | ||
interval: blockTime, | ||
}); | ||
this._genesisHeight = genesisBlock.header.height; | ||
this._blockRewardArgs = { | ||
distance: rewardDistance, | ||
rewardOffset, | ||
milestones: rewardMilestones, | ||
keepEventsForHeights, | ||
}; | ||
this.constants = { | ||
blockTime, | ||
maxPayloadLength, | ||
rewardDistance, | ||
rewardOffset, | ||
rewardMilestones, | ||
networkIdentifier, | ||
minFeePerByte, | ||
baseFees, | ||
roundLength, | ||
}; | ||
} | ||
@@ -70,14 +30,26 @@ get genesisHeight() { | ||
get lastBlock() { | ||
if (this._lastBlock === undefined) { | ||
throw new Error('Chain has not been initialized.'); | ||
} | ||
return this._lastBlock; | ||
} | ||
get roundLength() { | ||
return this.constants.roundLength; | ||
get finalizedHeight() { | ||
if (this._finalizedHeight === undefined) { | ||
throw new Error('Chain has not been initialized.'); | ||
} | ||
return this._finalizedHeight; | ||
} | ||
get accountSchema() { | ||
return this._accountSchema; | ||
get chainID() { | ||
return this._chainID; | ||
} | ||
get blockAssetSchema() { | ||
return this._blockAssetSchema; | ||
init(args) { | ||
this._chainID = args.chainID; | ||
this.dataAccess = new data_access_1.DataAccess({ | ||
db: args.db, | ||
minBlockHeaderCache: this.constants.minBlockHeaderCache, | ||
maxBlockHeaderCache: this.constants.maxBlockHeaderCache, | ||
keepEventsForHeights: this.constants.keepEventsForHeights, | ||
}); | ||
} | ||
async init(genesisBlock) { | ||
async loadLastBlocks(genesisBlock) { | ||
let storageLastBlock; | ||
@@ -88,3 +60,3 @@ try { | ||
catch (error) { | ||
throw new Error('Failed to load last block'); | ||
throw new Error('Failed to load last block.'); | ||
} | ||
@@ -94,38 +66,19 @@ if (storageLastBlock.header.height !== genesisBlock.header.height) { | ||
} | ||
const genesisInfo = await this._getGenesisInfo(); | ||
if (!genesisInfo) { | ||
await this.dataAccess.setConsensusState(constants_1.CONSENSUS_STATE_GENESIS_INFO, lisk_codec_1.codec.encode(schema_1.genesisInfoSchema, { | ||
height: genesisBlock.header.height, | ||
initRounds: genesisBlock.header.asset.initRounds, | ||
})); | ||
} | ||
this._lastBlock = storageLastBlock; | ||
this._genesisHeight = genesisBlock.header.height; | ||
this._finalizedHeight = await this.dataAccess.getFinalizedHeight(); | ||
} | ||
calculateDefaultReward(height) { | ||
return block_reward_1.calculateDefaultReward(height, this._blockRewardArgs); | ||
} | ||
calculateExpectedReward(blockHeader, stateStore) { | ||
const defaultReward = this.calculateDefaultReward(blockHeader.height); | ||
const isValid = this.isValidSeedReveal(blockHeader, stateStore); | ||
return isValid ? defaultReward : BigInt(0); | ||
} | ||
resetBlockHeaderCache() { | ||
this.dataAccess.resetBlockHeaderCache(); | ||
} | ||
async newStateStore(skipLastHeights = 0) { | ||
var _a, _b, _c; | ||
const genesisInfo = await this._getGenesisInfo(); | ||
const fromHeight = Math.max((_a = genesisInfo === null || genesisInfo === void 0 ? void 0 : genesisInfo.height) !== null && _a !== void 0 ? _a : 0, this._lastBlock.header.height - this.constants.roundLength * 3 - skipLastHeights); | ||
const toHeight = Math.max(this._lastBlock.header.height - skipLastHeights, 1); | ||
const lastBlockHeaders = await this.dataAccess.getBlockHeadersByHeightBetween(fromHeight, toHeight); | ||
const lastBlockReward = this.calculateDefaultReward((_c = (_b = lastBlockHeaders[0]) === null || _b === void 0 ? void 0 : _b.height) !== null && _c !== void 0 ? _c : 1); | ||
return new state_store_1.StateStore(this.dataAccess, { | ||
networkIdentifier: this._networkIdentifier, | ||
lastBlockHeaders, | ||
lastBlockReward, | ||
defaultAccount: this._defaultAccount, | ||
}); | ||
} | ||
async genesisBlockExist(genesisBlock) { | ||
const matchingGenesisBlock = await this.dataAccess.blockHeaderExists(genesisBlock.header.id); | ||
let matchingGenesisBlock; | ||
try { | ||
matchingGenesisBlock = await this.dataAccess.getBlockHeaderByID(genesisBlock.header.id); | ||
} | ||
catch (error) { | ||
if (!(error instanceof lisk_db_1.NotFoundError)) { | ||
throw error; | ||
} | ||
} | ||
let lastBlockHeader; | ||
@@ -141,3 +94,3 @@ try { | ||
if (lastBlockHeader && !matchingGenesisBlock) { | ||
throw new Error('Genesis block does not match'); | ||
throw new Error('Genesis block does not match.'); | ||
} | ||
@@ -149,69 +102,32 @@ if (!lastBlockHeader && !matchingGenesisBlock) { | ||
} | ||
isValidSeedReveal(blockHeader, stateStore) { | ||
return verify_1.isValidSeedReveal(blockHeader, stateStore, this.constants.roundLength); | ||
} | ||
validateGenesisBlockHeader(block) { | ||
validate_1.validateGenesisBlockHeader(block, this._accountSchema); | ||
} | ||
async applyGenesisBlock(block, stateStore) { | ||
for (const account of block.header.asset.accounts) { | ||
await stateStore.account.set(account.address, account); | ||
validateBlock(block, inputs) { | ||
block.validate(); | ||
if (block.header.version !== inputs.version) { | ||
throw new Error(`Block version must be ${inputs.version}.`); | ||
} | ||
const initialValidators = block.header.asset.initDelegates.map(address => ({ | ||
address, | ||
minActiveHeight: block.header.height + 1, | ||
isConsensusParticipant: false, | ||
})); | ||
await stateStore.consensus.set(constants_1.CONSENSUS_STATE_VALIDATORS_KEY, lisk_codec_1.codec.encode(schema_1.validatorsSchema, { validators: initialValidators })); | ||
await stateStore.consensus.set(constants_1.CONSENSUS_STATE_GENESIS_INFO, lisk_codec_1.codec.encode(schema_1.genesisInfoSchema, { | ||
height: block.header.height, | ||
initRounds: block.header.asset.initRounds, | ||
})); | ||
} | ||
validateTransaction(transaction) { | ||
transaction.validate({ | ||
minFeePerByte: this.constants.minFeePerByte, | ||
baseFees: this.constants.baseFees, | ||
}); | ||
} | ||
validateBlockHeader(block) { | ||
const headerWithoutAsset = { | ||
...block.header, | ||
asset: Buffer.alloc(0), | ||
}; | ||
const errors = lisk_validator_1.validator.validate(schema_1.blockHeaderSchema, headerWithoutAsset); | ||
if (errors.length) { | ||
throw new lisk_validator_1.LiskValidationError(errors); | ||
const transactionIDs = []; | ||
let transactionsSize = 0; | ||
for (const tx of block.transactions) { | ||
transactionIDs.push(tx.id); | ||
transactionsSize += tx.getBytes().length; | ||
} | ||
const assetSchema = this.dataAccess.getBlockHeaderAssetSchema(block.header.version); | ||
const assetErrors = lisk_validator_1.validator.validate(assetSchema, block.header.asset); | ||
if (assetErrors.length) { | ||
throw new lisk_validator_1.LiskValidationError(assetErrors); | ||
if (transactionsSize > this.constants.maxTransactionsSize) { | ||
throw new Error(`Transactions length is longer than configured length: ${this.constants.maxTransactionsSize}.`); | ||
} | ||
const encodedBlockHeaderWithoutSignature = this.dataAccess.encodeBlockHeader(block.header, true); | ||
validate_1.validateSignature(block.header.generatorPublicKey, encodedBlockHeaderWithoutSignature, block.header.signature, this._networkIdentifier); | ||
validate_1.validateReward(block, this.calculateDefaultReward(block.header.height)); | ||
const encodedPayload = Buffer.concat(block.payload.map(tx => this.dataAccess.encodeTransaction(tx))); | ||
validate_1.validateBlockProperties(block, encodedPayload, this.constants.maxPayloadLength); | ||
const transactionRoot = lisk_tree_1.regularMerkleTree.calculateMerkleRootWithLeaves(transactionIDs); | ||
if (!transactionRoot.equals(block.header.transactionRoot)) { | ||
throw new Error('Invalid transaction root.'); | ||
} | ||
} | ||
async verifyBlockHeader(block, stateStore) { | ||
verify_1.verifyPreviousBlockId(block, this._lastBlock); | ||
validate_1.validateBlockSlot(block, this._lastBlock, this.slots); | ||
verify_1.verifyReward(block.header, stateStore, this.constants.roundLength); | ||
await verify_1.verifyBlockGenerator(block.header, this.slots, stateStore); | ||
} | ||
async saveBlock(block, stateStore, finalizedHeight, { removeFromTempTable } = { | ||
async saveBlock(block, events, state, finalizedHeight, { removeFromTempTable } = { | ||
removeFromTempTable: false, | ||
}) { | ||
await this.dataAccess.saveBlock(block, stateStore, finalizedHeight, removeFromTempTable); | ||
await this.dataAccess.saveBlock(block, events, state, finalizedHeight, removeFromTempTable); | ||
this.dataAccess.addBlockHeader(block.header); | ||
this._finalizedHeight = finalizedHeight; | ||
this._lastBlock = block; | ||
this.events.emit(constants_1.EVENT_NEW_BLOCK, { | ||
block, | ||
accounts: stateStore.account.getUpdated(), | ||
}); | ||
} | ||
async removeBlock(block, stateStore, { saveTempBlock } = { saveTempBlock: false }) { | ||
async removeBlock(block, state, { saveTempBlock } = { saveTempBlock: false }) { | ||
if (block.header.version === constants_1.GENESIS_BLOCK_VERSION) { | ||
throw new Error('Cannot delete genesis block'); | ||
throw new Error('Cannot delete genesis block.'); | ||
} | ||
@@ -223,48 +139,8 @@ let secondLastBlock; | ||
catch (error) { | ||
throw new Error('PreviousBlock is null'); | ||
throw new Error('PreviousBlock is null.'); | ||
} | ||
const updatedAccounts = await this.dataAccess.deleteBlock(block, stateStore, saveTempBlock); | ||
await this.dataAccess.deleteBlock(block, state, saveTempBlock); | ||
await this.dataAccess.removeBlockHeader(block.header.id); | ||
this._lastBlock = secondLastBlock; | ||
this.events.emit(constants_1.EVENT_DELETE_BLOCK, { | ||
block, | ||
accounts: updatedAccounts, | ||
}); | ||
} | ||
async getValidator(timestamp) { | ||
const validators = await this.getValidators(); | ||
const currentSlot = this.slots.getSlotNumber(timestamp); | ||
return validators[currentSlot % validators.length]; | ||
} | ||
async getValidators() { | ||
const validatorsBuffer = await this.dataAccess.getConsensusState(constants_1.CONSENSUS_STATE_VALIDATORS_KEY); | ||
if (!validatorsBuffer) { | ||
return []; | ||
} | ||
const { validators } = lisk_codec_1.codec.decode(schema_1.validatorsSchema, validatorsBuffer); | ||
return validators; | ||
} | ||
async setValidators(validators, stateStore, blockHeader) { | ||
const lastBootstrapHeight = await this._getLastBootstrapHeight(); | ||
if (lastBootstrapHeight > blockHeader.height) { | ||
debug(`Skipping updating validator since current height ${blockHeader.height} is lower than last bootstrap height ${lastBootstrapHeight}`); | ||
return; | ||
} | ||
const validatorsBuffer = await stateStore.consensus.get(constants_1.CONSENSUS_STATE_VALIDATORS_KEY); | ||
if (!validatorsBuffer) { | ||
throw new Error('Previous validator set must exist'); | ||
} | ||
const { validators: previousValidators } = lisk_codec_1.codec.decode(schema_1.validatorsSchema, validatorsBuffer); | ||
const nextValidatorSet = []; | ||
for (const nextValidator of validators) { | ||
const previousInfo = previousValidators.find(pv => pv.address.equals(nextValidator.address)); | ||
nextValidatorSet.push({ | ||
...nextValidator, | ||
minActiveHeight: previousInfo !== undefined ? previousInfo.minActiveHeight : blockHeader.height + 1, | ||
}); | ||
} | ||
const encodedValidators = lisk_codec_1.codec.encode(schema_1.validatorsSchema, { validators: nextValidatorSet }); | ||
await stateStore.consensus.set(constants_1.CONSENSUS_STATE_VALIDATORS_KEY, encodedValidators); | ||
this.events.emit(constants_1.EVENT_VALIDATORS_CHANGED, { validators: nextValidatorSet }); | ||
} | ||
async _cacheBlockHeaders(storageLastBlock) { | ||
@@ -281,18 +157,4 @@ const fromHeight = Math.max(storageLastBlock.header.height - constants_1.DEFAULT_MAX_BLOCK_HEADER_CACHE, 0); | ||
} | ||
async _getLastBootstrapHeight() { | ||
const genesisInfo = await this._getGenesisInfo(); | ||
if (!genesisInfo) { | ||
throw new Error('genesis info not stored'); | ||
} | ||
return this.constants.roundLength * genesisInfo.initRounds + genesisInfo.height; | ||
} | ||
async _getGenesisInfo() { | ||
const genesisInfoBytes = await this.dataAccess.getConsensusState(constants_1.CONSENSUS_STATE_GENESIS_INFO); | ||
if (!genesisInfoBytes) { | ||
return undefined; | ||
} | ||
return lisk_codec_1.codec.decode(schema_1.genesisInfoSchema, genesisInfoBytes); | ||
} | ||
} | ||
exports.Chain = Chain; | ||
//# sourceMappingURL=chain.js.map |
/// <reference types="node" /> | ||
export declare const CHAIN_STATE_BURNT_FEE = "burntFee"; | ||
export declare const CONSENSUS_STATE_FINALIZED_HEIGHT_KEY = "finalizedHeight"; | ||
export declare const CONSENSUS_STATE_VALIDATORS_KEY = "validators"; | ||
export declare const CONSENSUS_STATE_GENESIS_INFO = "genesisInfo"; | ||
export declare const DEFAULT_KEEP_EVENTS_FOR_HEIGHTS = 300; | ||
export declare const DEFAULT_MIN_BLOCK_HEADER_CACHE = 309; | ||
export declare const DEFAULT_MAX_BLOCK_HEADER_CACHE = 515; | ||
export declare const EVENT_NEW_BLOCK = "EVENT_NEW_BLOCK"; | ||
export declare const EVENT_DELETE_BLOCK = "EVENT_DELETE_BLOCK"; | ||
export declare const EVENT_VALIDATORS_CHANGED = "EVENT_VALIDATORS_CHANGED"; | ||
export declare const EMPTY_BUFFER: Buffer; | ||
export declare const EMPTY_HASH: Buffer; | ||
export declare const MAX_UINT32 = 4294967295; | ||
export declare const GENESIS_BLOCK_VERSION = 0; | ||
export declare const GENESIS_BLOCK_GENERATOR_PUBLIC_KEY: Buffer; | ||
export declare const GENESIS_BLOCK_GENERATOR_ADDRESS: Buffer; | ||
export declare const GENESIS_BLOCK_REWARD: bigint; | ||
export declare const GENESIS_BLOCK_SIGNATURE: Buffer; | ||
export declare const GENESIS_BLOCK_TRANSACTION_ROOT: Buffer; | ||
export declare const TAG_BLOCK_HEADER: string; | ||
export declare const TAG_TRANSACTION: string; | ||
export declare const MAX_ASSET_DATA_SIZE_BYTES = 64; | ||
export declare const SIGNATURE_LENGTH_BYTES = 64; | ||
export declare const MIN_MODULE_NAME_LENGTH = 1; | ||
export declare const MAX_MODULE_NAME_LENGTH = 32; | ||
export declare const MIN_EVENT_NAME_LENGTH = 1; | ||
export declare const MAX_EVENT_NAME_LENGTH = 32; | ||
export declare const MIN_CROSS_CHAIN_COMMAND_NAME_LENGTH = 1; | ||
export declare const MAX_CROSS_CHAIN_COMMAND_NAME_LENGTH = 32; | ||
export declare const SMT_PREFIX_SIZE = 6; | ||
export declare const EVENT_TOPIC_HASH_LENGTH_BYTES = 8; | ||
export declare const EVENT_INDEX_LENGTH_BITS = 30; | ||
export declare const EVENT_TOPIC_INDEX_LENGTH_BITS = 2; | ||
export declare const EVENT_MAX_EVENT_SIZE_BYTES: number; | ||
export declare const TRANSACTION_MAX_PARAMS_SIZE: number; | ||
export declare const EVENT_TOTAL_INDEX_LENGTH_BYTES: number; | ||
export declare const EVENT_MAX_TOPICS_PER_EVENT: number; | ||
export declare const EVENT_KEY_LENGTH: number; | ||
export declare const MAX_EVENTS_PER_BLOCK: number; | ||
export declare const EVENT_ID_LENGTH_BYTES: number; | ||
export declare const NAME_REGEX: RegExp; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.GENESIS_BLOCK_TRANSACTION_ROOT = exports.GENESIS_BLOCK_SIGNATURE = exports.GENESIS_BLOCK_REWARD = exports.GENESIS_BLOCK_GENERATOR_PUBLIC_KEY = exports.GENESIS_BLOCK_VERSION = exports.EMPTY_HASH = exports.EMPTY_BUFFER = exports.EVENT_VALIDATORS_CHANGED = exports.EVENT_DELETE_BLOCK = exports.EVENT_NEW_BLOCK = exports.DEFAULT_MAX_BLOCK_HEADER_CACHE = exports.DEFAULT_MIN_BLOCK_HEADER_CACHE = exports.CONSENSUS_STATE_GENESIS_INFO = exports.CONSENSUS_STATE_VALIDATORS_KEY = exports.CONSENSUS_STATE_FINALIZED_HEIGHT_KEY = exports.CHAIN_STATE_BURNT_FEE = void 0; | ||
exports.NAME_REGEX = exports.EVENT_ID_LENGTH_BYTES = exports.MAX_EVENTS_PER_BLOCK = exports.EVENT_KEY_LENGTH = exports.EVENT_MAX_TOPICS_PER_EVENT = exports.EVENT_TOTAL_INDEX_LENGTH_BYTES = exports.TRANSACTION_MAX_PARAMS_SIZE = exports.EVENT_MAX_EVENT_SIZE_BYTES = exports.EVENT_TOPIC_INDEX_LENGTH_BITS = exports.EVENT_INDEX_LENGTH_BITS = exports.EVENT_TOPIC_HASH_LENGTH_BYTES = exports.SMT_PREFIX_SIZE = exports.MAX_CROSS_CHAIN_COMMAND_NAME_LENGTH = exports.MIN_CROSS_CHAIN_COMMAND_NAME_LENGTH = exports.MAX_EVENT_NAME_LENGTH = exports.MIN_EVENT_NAME_LENGTH = exports.MAX_MODULE_NAME_LENGTH = exports.MIN_MODULE_NAME_LENGTH = exports.SIGNATURE_LENGTH_BYTES = exports.MAX_ASSET_DATA_SIZE_BYTES = exports.TAG_TRANSACTION = exports.TAG_BLOCK_HEADER = exports.GENESIS_BLOCK_TRANSACTION_ROOT = exports.GENESIS_BLOCK_SIGNATURE = exports.GENESIS_BLOCK_REWARD = exports.GENESIS_BLOCK_GENERATOR_ADDRESS = exports.GENESIS_BLOCK_VERSION = exports.MAX_UINT32 = exports.EMPTY_HASH = exports.EMPTY_BUFFER = exports.DEFAULT_MAX_BLOCK_HEADER_CACHE = exports.DEFAULT_MIN_BLOCK_HEADER_CACHE = exports.DEFAULT_KEEP_EVENTS_FOR_HEIGHTS = void 0; | ||
const lisk_cryptography_1 = require("@liskhq/lisk-cryptography"); | ||
exports.CHAIN_STATE_BURNT_FEE = 'burntFee'; | ||
exports.CONSENSUS_STATE_FINALIZED_HEIGHT_KEY = 'finalizedHeight'; | ||
exports.CONSENSUS_STATE_VALIDATORS_KEY = 'validators'; | ||
exports.CONSENSUS_STATE_GENESIS_INFO = 'genesisInfo'; | ||
exports.DEFAULT_KEEP_EVENTS_FOR_HEIGHTS = 300; | ||
exports.DEFAULT_MIN_BLOCK_HEADER_CACHE = 309; | ||
exports.DEFAULT_MAX_BLOCK_HEADER_CACHE = 515; | ||
exports.EVENT_NEW_BLOCK = 'EVENT_NEW_BLOCK'; | ||
exports.EVENT_DELETE_BLOCK = 'EVENT_DELETE_BLOCK'; | ||
exports.EVENT_VALIDATORS_CHANGED = 'EVENT_VALIDATORS_CHANGED'; | ||
exports.EMPTY_BUFFER = Buffer.alloc(0); | ||
exports.EMPTY_HASH = lisk_cryptography_1.hash(exports.EMPTY_BUFFER); | ||
exports.EMPTY_HASH = lisk_cryptography_1.utils.hash(exports.EMPTY_BUFFER); | ||
exports.MAX_UINT32 = 4294967295; | ||
exports.GENESIS_BLOCK_VERSION = 0; | ||
exports.GENESIS_BLOCK_GENERATOR_PUBLIC_KEY = exports.EMPTY_BUFFER; | ||
exports.GENESIS_BLOCK_GENERATOR_ADDRESS = exports.EMPTY_BUFFER; | ||
exports.GENESIS_BLOCK_REWARD = BigInt(0); | ||
exports.GENESIS_BLOCK_SIGNATURE = exports.EMPTY_BUFFER; | ||
exports.GENESIS_BLOCK_TRANSACTION_ROOT = exports.EMPTY_HASH; | ||
exports.TAG_BLOCK_HEADER = lisk_cryptography_1.utils.createMessageTag('BH'); | ||
exports.TAG_TRANSACTION = lisk_cryptography_1.utils.createMessageTag('TX'); | ||
exports.MAX_ASSET_DATA_SIZE_BYTES = 64; | ||
exports.SIGNATURE_LENGTH_BYTES = 64; | ||
exports.MIN_MODULE_NAME_LENGTH = 1; | ||
exports.MAX_MODULE_NAME_LENGTH = 32; | ||
exports.MIN_EVENT_NAME_LENGTH = 1; | ||
exports.MAX_EVENT_NAME_LENGTH = 32; | ||
exports.MIN_CROSS_CHAIN_COMMAND_NAME_LENGTH = 1; | ||
exports.MAX_CROSS_CHAIN_COMMAND_NAME_LENGTH = 32; | ||
exports.SMT_PREFIX_SIZE = 6; | ||
exports.EVENT_TOPIC_HASH_LENGTH_BYTES = 8; | ||
exports.EVENT_INDEX_LENGTH_BITS = 30; | ||
exports.EVENT_TOPIC_INDEX_LENGTH_BITS = 2; | ||
exports.EVENT_MAX_EVENT_SIZE_BYTES = 10 * 1024; | ||
exports.TRANSACTION_MAX_PARAMS_SIZE = 14 * 1024; | ||
exports.EVENT_TOTAL_INDEX_LENGTH_BYTES = (exports.EVENT_INDEX_LENGTH_BITS + exports.EVENT_TOPIC_INDEX_LENGTH_BITS) / 8; | ||
exports.EVENT_MAX_TOPICS_PER_EVENT = 2 ** exports.EVENT_TOPIC_INDEX_LENGTH_BITS; | ||
exports.EVENT_KEY_LENGTH = exports.EVENT_TOPIC_HASH_LENGTH_BYTES + exports.EVENT_TOTAL_INDEX_LENGTH_BYTES; | ||
exports.MAX_EVENTS_PER_BLOCK = 2 ** exports.EVENT_INDEX_LENGTH_BITS; | ||
exports.EVENT_ID_LENGTH_BYTES = 4 + exports.EVENT_TOTAL_INDEX_LENGTH_BYTES; | ||
exports.NAME_REGEX = /^[a-zA-Z0-9]*$/; | ||
//# sourceMappingURL=constants.js.map |
/// <reference types="node" /> | ||
import { BlockHeader } from '../../types'; | ||
import { BlockHeader } from '../../block_header'; | ||
import { Base } from './base'; | ||
@@ -4,0 +4,0 @@ export declare class BlockCache extends Base<BlockHeader> { |
/// <reference types="node" /> | ||
import { KVStore } from '@liskhq/lisk-db'; | ||
import { Schema } from '@liskhq/lisk-codec'; | ||
import { Database } from '@liskhq/lisk-db'; | ||
import { Transaction } from '../transaction'; | ||
import { BlockHeader, Block, Account, BlockHeaderAsset } from '../types'; | ||
import { StateStore } from '../state_store'; | ||
import { BlockHeader } from '../block_header'; | ||
import { Block } from '../block'; | ||
import { Event } from '../event'; | ||
import { CurrentState } from '../state_store'; | ||
interface DAConstructor { | ||
readonly db: KVStore; | ||
readonly registeredBlockHeaders: { | ||
readonly [key: number]: Schema; | ||
}; | ||
readonly accountSchema: Schema; | ||
readonly db: Database; | ||
readonly minBlockHeaderCache: number; | ||
readonly maxBlockHeaderCache: number; | ||
readonly keepEventsForHeights: number; | ||
} | ||
@@ -19,11 +17,7 @@ export declare class DataAccess { | ||
private readonly _blocksCache; | ||
private readonly _accountSchema; | ||
private readonly _blockHeaderAdapter; | ||
constructor({ db, registeredBlockHeaders, accountSchema, minBlockHeaderCache, maxBlockHeaderCache, }: DAConstructor); | ||
constructor({ db, minBlockHeaderCache, maxBlockHeaderCache, keepEventsForHeights, }: DAConstructor); | ||
addBlockHeader(blockHeader: BlockHeader): BlockHeader[]; | ||
removeBlockHeader(id: Buffer): Promise<BlockHeader[]>; | ||
resetBlockHeaderCache(): void; | ||
getBlockHeaderAssetSchema(version: number): Schema; | ||
getBlockHeaderByID(id: Buffer): Promise<BlockHeader>; | ||
getRawBlockHeaderByID(id: Buffer): Promise<BlockHeader>; | ||
blockHeaderExists(id: Buffer): Promise<boolean>; | ||
@@ -36,3 +30,3 @@ getBlockHeadersByIDs(arrayOfBlockIds: ReadonlyArray<Buffer>): Promise<BlockHeader[]>; | ||
getHighestCommonBlockID(arrayOfBlockIds: ReadonlyArray<Buffer>): Promise<Buffer | undefined>; | ||
getBlockByID<T>(id: Buffer): Promise<Block<T>>; | ||
getBlockByID(id: Buffer): Promise<Block>; | ||
getBlocksByIDs(arrayOfBlockIds: ReadonlyArray<Buffer>): Promise<Block[]>; | ||
@@ -42,2 +36,3 @@ getBlockByHeight(height: number): Promise<Block>; | ||
getLastBlock(): Promise<Block>; | ||
getEvents(height: number): Promise<Event[]>; | ||
isBlockPersisted(blockId: Buffer): Promise<boolean>; | ||
@@ -47,25 +42,10 @@ getTempBlocks(): Promise<Block[]>; | ||
clearTempBlocks(): Promise<void>; | ||
getChainState(key: string): Promise<Buffer | undefined>; | ||
getConsensusState(key: string): Promise<Buffer | undefined>; | ||
setConsensusState(key: string, val: Buffer): Promise<void>; | ||
getAccountsByPublicKey(arrayOfPublicKeys: ReadonlyArray<Buffer>): Promise<Account[]>; | ||
getAccountByAddress<T>(address: Buffer): Promise<Account<T>>; | ||
getEncodedAccountByAddress(address: Buffer): Promise<Buffer>; | ||
getAccountsByAddress<T>(arrayOfAddresses: ReadonlyArray<Buffer>): Promise<Account<T>[]>; | ||
getTransactionByID(id: Buffer): Promise<Transaction>; | ||
getTransactionsByIDs(arrayOfTransactionIds: ReadonlyArray<Buffer>): Promise<Transaction[]>; | ||
isTransactionPersisted(transactionId: Buffer): Promise<boolean>; | ||
decode<T = BlockHeaderAsset>(buffer: Buffer): Block<T>; | ||
encode(block: Block<unknown>): Buffer; | ||
decodeBlockHeader<T = BlockHeaderAsset>(buffer: Buffer): BlockHeader<T>; | ||
encodeBlockHeader<T = BlockHeaderAsset>(blockHeader: BlockHeader<T>, skipSignature?: boolean): Buffer; | ||
decodeAccount<T>(buffer: Buffer): Account<T>; | ||
encodeAccount<T>(account: Account<T>): Buffer; | ||
decodeTransaction(buffer: Buffer): Transaction; | ||
encodeTransaction(tx: Transaction): Buffer; | ||
saveBlock(block: Block, stateStore: StateStore, finalizedHeight: number, removeFromTemp?: boolean): Promise<void>; | ||
deleteBlock(block: Block, stateStore: StateStore, saveToTemp?: boolean): Promise<Account[]>; | ||
getFinalizedHeight(): Promise<number>; | ||
saveBlock(block: Block, events: Event[], state: CurrentState, finalizedHeight: number, removeFromTemp?: boolean): Promise<void>; | ||
deleteBlock(block: Block, state: CurrentState, saveToTemp?: boolean): Promise<void>; | ||
private _decodeRawBlock; | ||
private _getRawBlockHeaderByID; | ||
} | ||
export {}; |
@@ -5,15 +5,12 @@ "use strict"; | ||
const lisk_db_1 = require("@liskhq/lisk-db"); | ||
const lisk_codec_1 = require("@liskhq/lisk-codec"); | ||
const transaction_1 = require("../transaction"); | ||
const block_header_1 = require("../block_header"); | ||
const block_1 = require("../block"); | ||
const cache_1 = require("./cache"); | ||
const storage_1 = require("./storage"); | ||
const block_header_interface_adapter_1 = require("./block_header_interface_adapter"); | ||
const schema_1 = require("../schema"); | ||
const constants_1 = require("./constants"); | ||
const block_assets_1 = require("../block_assets"); | ||
class DataAccess { | ||
constructor({ db, registeredBlockHeaders, accountSchema, minBlockHeaderCache, maxBlockHeaderCache, }) { | ||
this._storage = new storage_1.Storage(db); | ||
constructor({ db, minBlockHeaderCache, maxBlockHeaderCache, keepEventsForHeights, }) { | ||
this._storage = new storage_1.Storage(db, { keepEventsForHeights }); | ||
this._blocksCache = new cache_1.BlockCache(minBlockHeaderCache, maxBlockHeaderCache); | ||
this._accountSchema = accountSchema; | ||
this._blockHeaderAdapter = new block_header_interface_adapter_1.BlockHeaderInterfaceAdapter(registeredBlockHeaders); | ||
} | ||
@@ -40,5 +37,2 @@ addBlockHeader(blockHeader) { | ||
} | ||
getBlockHeaderAssetSchema(version) { | ||
return this._blockHeaderAdapter.getSchema(version); | ||
} | ||
async getBlockHeaderByID(id) { | ||
@@ -50,7 +44,4 @@ const cachedBlock = this._blocksCache.getByID(id); | ||
const blockHeaderBuffer = await this._storage.getBlockHeaderByID(id); | ||
return this._blockHeaderAdapter.decode(blockHeaderBuffer); | ||
return block_header_1.BlockHeader.fromBytes(blockHeaderBuffer); | ||
} | ||
async getRawBlockHeaderByID(id) { | ||
return this._getRawBlockHeaderByID(id); | ||
} | ||
async blockHeaderExists(id) { | ||
@@ -75,3 +66,3 @@ const cachedBlock = this._blocksCache.getByID(id); | ||
const blocks = await this._storage.getBlockHeadersByIDs(arrayOfBlockIds); | ||
return blocks.map(block => this._blockHeaderAdapter.decode(block)); | ||
return blocks.map(block => block_header_1.BlockHeader.fromBytes(block)); | ||
} | ||
@@ -84,3 +75,3 @@ async getBlockHeaderByHeight(height) { | ||
const header = await this._storage.getBlockHeaderByHeight(height); | ||
return this._blockHeaderAdapter.decode(header); | ||
return block_header_1.BlockHeader.fromBytes(header); | ||
} | ||
@@ -93,3 +84,3 @@ async getBlockHeadersByHeightBetween(fromHeight, toHeight) { | ||
const blocks = await this._storage.getBlockHeadersByHeightBetween(fromHeight, toHeight); | ||
return blocks.map(block => this._blockHeaderAdapter.decode(block)); | ||
return blocks.map(block => block_header_1.BlockHeader.fromBytes(block)); | ||
} | ||
@@ -102,3 +93,3 @@ async getBlockHeadersWithHeights(heightList) { | ||
const blocks = await this._storage.getBlockHeadersWithHeights(heightList); | ||
return blocks.map(block => this._blockHeaderAdapter.decode(block)); | ||
return blocks.map(block => block_header_1.BlockHeader.fromBytes(block)); | ||
} | ||
@@ -111,3 +102,3 @@ async getLastBlockHeader() { | ||
const block = await this._storage.getLastBlockHeader(); | ||
return this._blockHeaderAdapter.decode(block); | ||
return block_header_1.BlockHeader.fromBytes(block); | ||
} | ||
@@ -125,3 +116,3 @@ async getHighestCommonBlockID(arrayOfBlockIds) { | ||
try { | ||
const blockHeader = await this._getRawBlockHeaderByID(id); | ||
const blockHeader = await this.getBlockHeaderByID(id); | ||
storageBlockHeaders.push(blockHeader); | ||
@@ -158,2 +149,6 @@ } | ||
} | ||
async getEvents(height) { | ||
const events = await this._storage.getEvents(height); | ||
return events; | ||
} | ||
async isBlockPersisted(blockId) { | ||
@@ -165,3 +160,3 @@ const isPersisted = await this._storage.isBlockPersisted(blockId); | ||
const blocks = await this._storage.getTempBlocks(); | ||
return blocks.map(block => this.decode(block)); | ||
return blocks.map(block => block_1.Block.fromBytes(block)); | ||
} | ||
@@ -175,34 +170,9 @@ async isTempBlockEmpty() { | ||
} | ||
async getChainState(key) { | ||
return this._storage.getChainState(key); | ||
} | ||
async getConsensusState(key) { | ||
return this._storage.getConsensusState(key); | ||
} | ||
async setConsensusState(key, val) { | ||
return this._storage.setConsensusState(key, val); | ||
} | ||
async getAccountsByPublicKey(arrayOfPublicKeys) { | ||
const accounts = await this._storage.getAccountsByPublicKey(arrayOfPublicKeys); | ||
return accounts.map(account => this.decodeAccount(account)); | ||
} | ||
async getAccountByAddress(address) { | ||
const account = await this._storage.getAccountByAddress(address); | ||
return this.decodeAccount(account); | ||
} | ||
async getEncodedAccountByAddress(address) { | ||
const account = await this._storage.getAccountByAddress(address); | ||
return account; | ||
} | ||
async getAccountsByAddress(arrayOfAddresses) { | ||
const accounts = await this._storage.getAccountsByAddress(arrayOfAddresses); | ||
return accounts.map(account => this.decodeAccount(account)); | ||
} | ||
async getTransactionByID(id) { | ||
const transaction = await this._storage.getTransactionByID(id); | ||
return transaction_1.Transaction.decode(transaction); | ||
return transaction_1.Transaction.fromBytes(transaction); | ||
} | ||
async getTransactionsByIDs(arrayOfTransactionIds) { | ||
const transactions = await this._storage.getTransactionsByIDs(arrayOfTransactionIds); | ||
return transactions.map(transaction => transaction_1.Transaction.decode(transaction)); | ||
return transactions.map(transaction => transaction_1.Transaction.fromBytes(transaction)); | ||
} | ||
@@ -213,96 +183,31 @@ async isTransactionPersisted(transactionId) { | ||
} | ||
decode(buffer) { | ||
const block = lisk_codec_1.codec.decode(schema_1.blockSchema, buffer); | ||
const header = this._blockHeaderAdapter.decode(block.header); | ||
const payload = []; | ||
for (const rawTx of block.payload) { | ||
const tx = transaction_1.Transaction.decode(rawTx); | ||
payload.push(tx); | ||
} | ||
return { | ||
header, | ||
payload, | ||
}; | ||
async getFinalizedHeight() { | ||
return this._storage.getFinalizedHeight(); | ||
} | ||
encode(block) { | ||
const header = this.encodeBlockHeader(block.header); | ||
const payload = []; | ||
for (const rawTx of block.payload) { | ||
const tx = rawTx.getBytes(); | ||
payload.push(tx); | ||
} | ||
return lisk_codec_1.codec.encode(schema_1.blockSchema, { header, payload }); | ||
} | ||
decodeBlockHeader(buffer) { | ||
return this._blockHeaderAdapter.decode(buffer); | ||
} | ||
encodeBlockHeader(blockHeader, skipSignature = false) { | ||
return this._blockHeaderAdapter.encode(blockHeader, skipSignature); | ||
} | ||
decodeAccount(buffer) { | ||
return lisk_codec_1.codec.decode(this._accountSchema, buffer); | ||
} | ||
encodeAccount(account) { | ||
return lisk_codec_1.codec.encode(this._accountSchema, account); | ||
} | ||
decodeTransaction(buffer) { | ||
return transaction_1.Transaction.decode(buffer); | ||
} | ||
encodeTransaction(tx) { | ||
return tx.getBytes(); | ||
} | ||
async saveBlock(block, stateStore, finalizedHeight, removeFromTemp = false) { | ||
async saveBlock(block, events, state, finalizedHeight, removeFromTemp = false) { | ||
const { id: blockID, height } = block.header; | ||
const encodedHeader = this._blockHeaderAdapter.encode(block.header); | ||
const encodedPayload = []; | ||
for (const tx of block.payload) { | ||
const encodedHeader = block.header.getBytes(); | ||
const encodedTransactions = []; | ||
for (const tx of block.transactions) { | ||
const txID = tx.id; | ||
const encodedTx = tx.getBytes(); | ||
encodedPayload.push({ id: txID, value: encodedTx }); | ||
encodedTransactions.push({ id: txID, value: encodedTx }); | ||
} | ||
await this._storage.saveBlock(blockID, height, finalizedHeight, encodedHeader, encodedPayload, stateStore, removeFromTemp); | ||
const encodedEvents = events.map(e => e.getBytes()); | ||
await this._storage.saveBlock(blockID, height, finalizedHeight, encodedHeader, encodedTransactions, encodedEvents, block.assets.getBytes(), state, removeFromTemp); | ||
} | ||
async deleteBlock(block, stateStore, saveToTemp = false) { | ||
async deleteBlock(block, state, saveToTemp = false) { | ||
const { id: blockID, height } = block.header; | ||
const txIDs = block.payload.map(tx => tx.id); | ||
const encodedBlock = this.encode(block); | ||
const diff = await this._storage.deleteBlock(blockID, height, txIDs, encodedBlock, stateStore, saveToTemp); | ||
const updatedAccounts = []; | ||
for (const created of diff.deleted) { | ||
if (created.key.includes(constants_1.DB_KEY_ACCOUNTS_ADDRESS)) { | ||
updatedAccounts.push(this.decodeAccount(created.value)); | ||
} | ||
} | ||
for (const updated of diff.updated) { | ||
if (updated.key.includes(constants_1.DB_KEY_ACCOUNTS_ADDRESS)) { | ||
updatedAccounts.push(this.decodeAccount(updated.value)); | ||
} | ||
} | ||
return updatedAccounts; | ||
const txIDs = block.transactions.map(tx => tx.id); | ||
const encodedBlock = block.getBytes(); | ||
await this._storage.deleteBlock(blockID, height, txIDs, block.assets.getBytes(), encodedBlock, state, saveToTemp); | ||
} | ||
_decodeRawBlock(block) { | ||
const header = this._blockHeaderAdapter.decode(block.header); | ||
const payload = []; | ||
for (const rawTx of block.payload) { | ||
const tx = transaction_1.Transaction.decode(rawTx); | ||
payload.push(tx); | ||
} | ||
return { | ||
header, | ||
payload, | ||
}; | ||
const header = block_header_1.BlockHeader.fromBytes(block.header); | ||
const transactions = block.transactions.map(txBytes => transaction_1.Transaction.fromBytes(txBytes)); | ||
const assets = block_assets_1.BlockAssets.fromBytes(block.assets); | ||
return new block_1.Block(header, transactions, assets); | ||
} | ||
async _getRawBlockHeaderByID(id) { | ||
const cachedBlock = this._blocksCache.getByID(id); | ||
if (cachedBlock) { | ||
return cachedBlock; | ||
} | ||
const blockHeaderBuffer = await this._storage.getBlockHeaderByID(id); | ||
return { | ||
...lisk_codec_1.codec.decode(schema_1.blockHeaderSchema, blockHeaderBuffer), | ||
id, | ||
}; | ||
} | ||
} | ||
exports.DataAccess = DataAccess; | ||
//# sourceMappingURL=data_access.js.map |
/// <reference types="node" /> | ||
import { KVStore } from '@liskhq/lisk-db'; | ||
import { Database } from '@liskhq/lisk-db'; | ||
import { RawBlock, StateDiff } from '../types'; | ||
import { StateStore } from '../state_store'; | ||
import { Event } from '../event'; | ||
import { CurrentState } from '../state_store'; | ||
export declare const encodeByteArray: (val: Buffer[]) => Buffer; | ||
interface StorageOption { | ||
keepEventsForHeights?: number; | ||
} | ||
export declare class Storage { | ||
private readonly _db; | ||
constructor(db: KVStore); | ||
private readonly _keepEventsForHeights; | ||
constructor(db: Database, options?: StorageOption); | ||
getBlockHeaderByID(id: Buffer): Promise<Buffer>; | ||
@@ -19,2 +25,3 @@ getBlockHeadersByIDs(arrayOfBlockIds: ReadonlyArray<Buffer>): Promise<Buffer[]>; | ||
getLastBlock(): Promise<RawBlock>; | ||
getEvents(height: number): Promise<Event[]>; | ||
getTempBlocks(): Promise<Buffer[]>; | ||
@@ -24,18 +31,16 @@ isTempBlockEmpty(): Promise<boolean>; | ||
isBlockPersisted(blockID: Buffer): Promise<boolean>; | ||
getChainState(key: string): Promise<Buffer | undefined>; | ||
getConsensusState(key: string): Promise<Buffer | undefined>; | ||
setConsensusState(key: string, val: Buffer): Promise<void>; | ||
getAccountByAddress(address: Buffer): Promise<Buffer>; | ||
getAccountsByPublicKey(arrayOfPublicKeys: ReadonlyArray<Buffer>): Promise<Buffer[]>; | ||
getAccountsByAddress(arrayOfAddresses: ReadonlyArray<Buffer>): Promise<Buffer[]>; | ||
getTransactionByID(id: Buffer): Promise<Buffer>; | ||
getTransactionsByIDs(arrayOfTransactionIds: ReadonlyArray<Buffer>): Promise<Buffer[]>; | ||
isTransactionPersisted(transactionId: Buffer): Promise<boolean>; | ||
saveBlock(id: Buffer, height: number, finalizedHeight: number, header: Buffer, payload: { | ||
getFinalizedHeight(): Promise<number>; | ||
saveBlock(id: Buffer, height: number, finalizedHeight: number, header: Buffer, transactions: { | ||
id: Buffer; | ||
value: Buffer; | ||
}[], stateStore: StateStore, removeFromTemp?: boolean): Promise<void>; | ||
deleteBlock(id: Buffer, height: number, txIDs: Buffer[], fullBlock: Buffer, stateStore: StateStore, saveToTemp?: boolean): Promise<StateDiff>; | ||
}[], events: Buffer[], assets: Buffer[], state: CurrentState, removeFromTemp?: boolean): Promise<void>; | ||
deleteBlock(id: Buffer, height: number, txIDs: Buffer[], assets: Buffer[], fullBlock: Buffer, state: CurrentState, saveToTemp?: boolean): Promise<StateDiff>; | ||
private _cleanUntil; | ||
private _getBlockAssets; | ||
private _getTransactions; | ||
private _clear; | ||
} | ||
export {}; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Storage = void 0; | ||
exports.Storage = exports.encodeByteArray = void 0; | ||
const lisk_db_1 = require("@liskhq/lisk-db"); | ||
const lisk_codec_1 = require("@liskhq/lisk-codec"); | ||
const lisk_cryptography_1 = require("@liskhq/lisk-cryptography"); | ||
const constants_1 = require("./constants"); | ||
const event_1 = require("../event"); | ||
const db_keys_1 = require("../db_keys"); | ||
const utils_1 = require("../utils"); | ||
const schema_1 = require("../schema"); | ||
const constants_1 = require("../constants"); | ||
const bytesArraySchema = { | ||
$id: '/liskChain/bytesarray', | ||
type: 'object', | ||
required: ['list'], | ||
properties: { | ||
list: { | ||
type: 'array', | ||
fieldNumber: 1, | ||
items: { | ||
dataType: 'bytes', | ||
}, | ||
}, | ||
}, | ||
}; | ||
const decodeByteArray = (val) => { | ||
const decoded = lisk_codec_1.codec.decode(bytesArraySchema, val); | ||
return decoded.list; | ||
}; | ||
const encodeByteArray = (val) => lisk_codec_1.codec.encode(bytesArraySchema, { list: val }); | ||
exports.encodeByteArray = encodeByteArray; | ||
class Storage { | ||
constructor(db) { | ||
constructor(db, options) { | ||
var _a; | ||
this._db = db; | ||
this._keepEventsForHeights = (_a = options === null || options === void 0 ? void 0 : options.keepEventsForHeights) !== null && _a !== void 0 ? _a : constants_1.DEFAULT_KEEP_EVENTS_FOR_HEIGHTS; | ||
} | ||
async getBlockHeaderByID(id) { | ||
const block = await this._db.get(`${constants_1.DB_KEY_BLOCKS_ID}:${utils_1.keyString(id)}`); | ||
const block = await this._db.get((0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_BLOCKS_ID, id)); | ||
return block; | ||
@@ -22,3 +46,3 @@ } | ||
try { | ||
const block = await this._db.get(`${constants_1.DB_KEY_BLOCKS_ID}:${utils_1.keyString(id)}`); | ||
const block = await this._db.get((0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_BLOCKS_ID, id)); | ||
blocks.push(block); | ||
@@ -36,4 +60,3 @@ } | ||
async getBlockHeaderByHeight(height) { | ||
const stringHeight = lisk_db_1.formatInt(height); | ||
const id = await this._db.get(`${constants_1.DB_KEY_BLOCKS_HEIGHT}:${stringHeight}`); | ||
const id = await this._db.get((0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_BLOCKS_HEIGHT, (0, utils_1.uint32BE)(height))); | ||
return this.getBlockHeaderByID(id); | ||
@@ -43,4 +66,4 @@ } | ||
const stream = this._db.createReadStream({ | ||
gte: `${constants_1.DB_KEY_BLOCKS_HEIGHT}:${lisk_db_1.formatInt(fromHeight)}`, | ||
lte: `${constants_1.DB_KEY_BLOCKS_HEIGHT}:${lisk_db_1.formatInt(toHeight)}`, | ||
gte: (0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_BLOCKS_HEIGHT, (0, utils_1.uint32BE)(fromHeight)), | ||
lte: (0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_BLOCKS_HEIGHT, (0, utils_1.uint32BE)(toHeight)), | ||
reverse: true, | ||
@@ -81,4 +104,4 @@ }); | ||
const stream = this._db.createReadStream({ | ||
gte: lisk_db_1.getFirstPrefix(constants_1.DB_KEY_BLOCKS_HEIGHT), | ||
lte: lisk_db_1.getLastPrefix(constants_1.DB_KEY_BLOCKS_HEIGHT), | ||
gte: (0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_BLOCKS_HEIGHT, (0, utils_1.uint32BE)(0)), | ||
lte: (0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_BLOCKS_HEIGHT, (0, utils_1.uint32BE)(constants_1.MAX_UINT32)), | ||
reverse: true, | ||
@@ -108,5 +131,7 @@ limit: 1, | ||
const transactions = await this._getTransactions(id); | ||
const assets = await this._getBlockAssets(id); | ||
return { | ||
header: blockHeader, | ||
payload: transactions, | ||
transactions, | ||
assets, | ||
}; | ||
@@ -132,7 +157,9 @@ } | ||
const header = await this.getBlockHeaderByHeight(height); | ||
const blockID = lisk_cryptography_1.hash(header); | ||
const blockID = lisk_cryptography_1.utils.hash(header); | ||
const transactions = await this._getTransactions(blockID); | ||
const assets = await this._getBlockAssets(blockID); | ||
return { | ||
header, | ||
payload: transactions, | ||
transactions, | ||
assets, | ||
}; | ||
@@ -144,5 +171,6 @@ } | ||
for (const header of headers) { | ||
const blockID = lisk_cryptography_1.hash(header); | ||
const blockID = lisk_cryptography_1.utils.hash(header); | ||
const transactions = await this._getTransactions(blockID); | ||
blocks.push({ header, payload: transactions }); | ||
const assets = await this._getBlockAssets(blockID); | ||
blocks.push({ header, transactions, assets }); | ||
} | ||
@@ -153,13 +181,28 @@ return blocks; | ||
const header = await this.getLastBlockHeader(); | ||
const blockID = lisk_cryptography_1.hash(header); | ||
const blockID = lisk_cryptography_1.utils.hash(header); | ||
const transactions = await this._getTransactions(blockID); | ||
const assets = await this._getBlockAssets(blockID); | ||
return { | ||
header, | ||
payload: transactions, | ||
transactions, | ||
assets, | ||
}; | ||
} | ||
async getEvents(height) { | ||
try { | ||
const eventsByte = await this._db.get((0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_BLOCK_EVENTS, (0, utils_1.uint32BE)(height))); | ||
const events = decodeByteArray(eventsByte); | ||
return events.map(e => event_1.Event.fromBytes(e)); | ||
} | ||
catch (error) { | ||
if (!(error instanceof lisk_db_1.NotFoundError)) { | ||
throw error; | ||
} | ||
return []; | ||
} | ||
} | ||
async getTempBlocks() { | ||
const stream = this._db.createReadStream({ | ||
gte: lisk_db_1.getFirstPrefix(constants_1.DB_KEY_TEMPBLOCKS_HEIGHT), | ||
lte: lisk_db_1.getLastPrefix(constants_1.DB_KEY_TEMPBLOCKS_HEIGHT), | ||
gte: (0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_TEMPBLOCKS_HEIGHT, (0, utils_1.uint32BE)(0)), | ||
lte: (0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_TEMPBLOCKS_HEIGHT, (0, utils_1.uint32BE)(constants_1.MAX_UINT32)), | ||
reverse: true, | ||
@@ -184,4 +227,4 @@ }); | ||
const stream = this._db.createReadStream({ | ||
gte: lisk_db_1.getFirstPrefix(constants_1.DB_KEY_TEMPBLOCKS_HEIGHT), | ||
lte: lisk_db_1.getLastPrefix(constants_1.DB_KEY_TEMPBLOCKS_HEIGHT), | ||
gte: (0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_TEMPBLOCKS_HEIGHT, (0, utils_1.uint32BE)(0)), | ||
lte: (0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_TEMPBLOCKS_HEIGHT, (0, utils_1.uint32BE)(constants_1.MAX_UINT32)), | ||
limit: 1, | ||
@@ -205,63 +248,9 @@ }); | ||
async clearTempBlocks() { | ||
await this._db.clear({ | ||
gte: lisk_db_1.getFirstPrefix(constants_1.DB_KEY_TEMPBLOCKS_HEIGHT), | ||
lte: lisk_db_1.getLastPrefix(constants_1.DB_KEY_TEMPBLOCKS_HEIGHT), | ||
}); | ||
await this._clear((0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_TEMPBLOCKS_HEIGHT, (0, utils_1.uint32BE)(0)), (0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_TEMPBLOCKS_HEIGHT, (0, utils_1.uint32BE)(constants_1.MAX_UINT32))); | ||
} | ||
async isBlockPersisted(blockID) { | ||
return this._db.exists(`${constants_1.DB_KEY_BLOCKS_ID}:${utils_1.keyString(blockID)}`); | ||
return this._db.has((0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_BLOCKS_ID, blockID)); | ||
} | ||
async getChainState(key) { | ||
try { | ||
const value = await this._db.get(`${constants_1.DB_KEY_CHAIN_STATE}:${key}`); | ||
return value; | ||
} | ||
catch (error) { | ||
if (error instanceof lisk_db_1.NotFoundError) { | ||
return undefined; | ||
} | ||
throw error; | ||
} | ||
} | ||
async getConsensusState(key) { | ||
try { | ||
const value = await this._db.get(`${constants_1.DB_KEY_CONSENSUS_STATE}:${key}`); | ||
return value; | ||
} | ||
catch (error) { | ||
if (error instanceof lisk_db_1.NotFoundError) { | ||
return undefined; | ||
} | ||
throw error; | ||
} | ||
} | ||
async setConsensusState(key, val) { | ||
await this._db.put(`${constants_1.DB_KEY_CONSENSUS_STATE}:${key}`, val); | ||
} | ||
async getAccountByAddress(address) { | ||
const account = await this._db.get(`${constants_1.DB_KEY_ACCOUNTS_ADDRESS}:${utils_1.keyString(address)}`); | ||
return account; | ||
} | ||
async getAccountsByPublicKey(arrayOfPublicKeys) { | ||
const addresses = arrayOfPublicKeys.map(lisk_cryptography_1.getAddressFromPublicKey); | ||
return this.getAccountsByAddress(addresses); | ||
} | ||
async getAccountsByAddress(arrayOfAddresses) { | ||
const accounts = []; | ||
for (const address of arrayOfAddresses) { | ||
try { | ||
const account = await this.getAccountByAddress(address); | ||
accounts.push(account); | ||
} | ||
catch (dbError) { | ||
if (dbError instanceof lisk_db_1.NotFoundError) { | ||
continue; | ||
} | ||
throw dbError; | ||
} | ||
} | ||
return accounts; | ||
} | ||
async getTransactionByID(id) { | ||
const transaction = await this._db.get(`${constants_1.DB_KEY_TRANSACTIONS_ID}:${utils_1.keyString(id)}`); | ||
const transaction = await this._db.get((0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_TRANSACTIONS_ID, id)); | ||
return transaction; | ||
@@ -286,39 +275,59 @@ } | ||
async isTransactionPersisted(transactionId) { | ||
return this._db.exists(`${constants_1.DB_KEY_TRANSACTIONS_ID}:${utils_1.keyString(transactionId)}`); | ||
return this._db.has((0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_TRANSACTIONS_ID, transactionId)); | ||
} | ||
async saveBlock(id, height, finalizedHeight, header, payload, stateStore, removeFromTemp = false) { | ||
const heightStr = lisk_db_1.formatInt(height); | ||
const batch = this._db.batch(); | ||
batch.put(`${constants_1.DB_KEY_BLOCKS_ID}:${utils_1.keyString(id)}`, header); | ||
batch.put(`${constants_1.DB_KEY_BLOCKS_HEIGHT}:${heightStr}`, id); | ||
if (payload.length > 0) { | ||
async getFinalizedHeight() { | ||
const finalizedHeightBytes = await this._db.get(db_keys_1.DB_KEY_FINALIZED_HEIGHT); | ||
return finalizedHeightBytes.readUInt32BE(0); | ||
} | ||
async saveBlock(id, height, finalizedHeight, header, transactions, events, assets, state, removeFromTemp = false) { | ||
const heightBuf = (0, utils_1.uint32BE)(height); | ||
const { batch, diff } = state; | ||
batch.set((0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_BLOCKS_ID, id), header); | ||
batch.set((0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_BLOCKS_HEIGHT, heightBuf), id); | ||
if (transactions.length > 0) { | ||
const ids = []; | ||
for (const { id: txID, value } of payload) { | ||
for (const { id: txID, value } of transactions) { | ||
ids.push(txID); | ||
batch.put(`${constants_1.DB_KEY_TRANSACTIONS_ID}:${utils_1.keyString(txID)}`, value); | ||
batch.set((0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_TRANSACTIONS_ID, txID), value); | ||
} | ||
batch.put(`${constants_1.DB_KEY_TRANSACTIONS_BLOCK_ID}:${utils_1.keyString(id)}`, Buffer.concat(ids)); | ||
batch.set((0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_TRANSACTIONS_BLOCK_ID, id), Buffer.concat(ids)); | ||
} | ||
if (events.length > 0) { | ||
const encodedEvents = (0, exports.encodeByteArray)(events); | ||
batch.set((0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_BLOCK_EVENTS, heightBuf), encodedEvents); | ||
} | ||
if (assets.length > 0) { | ||
const encodedAsset = (0, exports.encodeByteArray)(assets); | ||
batch.set((0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_BLOCK_ASSETS_BLOCK_ID, id), encodedAsset); | ||
} | ||
if (removeFromTemp) { | ||
batch.del(`${constants_1.DB_KEY_TEMPBLOCKS_HEIGHT}:${heightStr}`); | ||
batch.del((0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_TEMPBLOCKS_HEIGHT, heightBuf)); | ||
} | ||
stateStore.finalize(heightStr, batch); | ||
await batch.write(); | ||
await this._cleanUntil(finalizedHeight); | ||
const encodedDiff = lisk_codec_1.codec.encode(schema_1.stateDiffSchema, diff); | ||
batch.set((0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_DIFF_STATE, (0, utils_1.uint32BE)(height)), encodedDiff); | ||
const finalizedHeightBytes = Buffer.alloc(4); | ||
finalizedHeightBytes.writeUInt32BE(finalizedHeight, 0); | ||
batch.set(db_keys_1.DB_KEY_FINALIZED_HEIGHT, finalizedHeightBytes); | ||
await this._db.write(batch); | ||
await this._cleanUntil(height, finalizedHeight); | ||
} | ||
async deleteBlock(id, height, txIDs, fullBlock, stateStore, saveToTemp = false) { | ||
const batch = this._db.batch(); | ||
const heightStr = lisk_db_1.formatInt(height); | ||
batch.del(`${constants_1.DB_KEY_BLOCKS_ID}:${utils_1.keyString(id)}`); | ||
batch.del(`${constants_1.DB_KEY_BLOCKS_HEIGHT}:${heightStr}`); | ||
async deleteBlock(id, height, txIDs, assets, fullBlock, state, saveToTemp = false) { | ||
const { batch } = state; | ||
const heightBuf = (0, utils_1.uint32BE)(height); | ||
batch.del((0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_BLOCKS_ID, id)); | ||
batch.del((0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_BLOCKS_HEIGHT, heightBuf)); | ||
if (txIDs.length > 0) { | ||
for (const txID of txIDs) { | ||
batch.del(`${constants_1.DB_KEY_TRANSACTIONS_ID}:${utils_1.keyString(txID)}`); | ||
batch.del((0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_TRANSACTIONS_ID, txID)); | ||
} | ||
batch.del(`${constants_1.DB_KEY_TRANSACTIONS_BLOCK_ID}:${utils_1.keyString(id)}`); | ||
batch.del((0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_TRANSACTIONS_BLOCK_ID, id)); | ||
} | ||
batch.del((0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_BLOCK_EVENTS, heightBuf)); | ||
if (assets.length > 0) { | ||
batch.del((0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_BLOCK_ASSETS_BLOCK_ID, id)); | ||
} | ||
if (saveToTemp) { | ||
batch.put(`${constants_1.DB_KEY_TEMPBLOCKS_HEIGHT}:${heightStr}`, fullBlock); | ||
batch.set((0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_TEMPBLOCKS_HEIGHT, heightBuf), fullBlock); | ||
} | ||
const diffKey = `${constants_1.DB_KEY_DIFF_STATE}:${heightStr}`; | ||
const diffKey = (0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_DIFF_STATE, heightBuf); | ||
const stateDiff = await this._db.get(diffKey); | ||
@@ -330,10 +339,9 @@ const { created: createdStates, updated: updatedStates, deleted: deletedStates, } = lisk_codec_1.codec.decode(schema_1.stateDiffSchema, stateDiff); | ||
for (const { key, value: previousValue } of deletedStates) { | ||
batch.put(key, previousValue); | ||
batch.set(key, previousValue); | ||
} | ||
for (const { key, value: previousValue } of updatedStates) { | ||
batch.put(key, previousValue); | ||
batch.set(key, previousValue); | ||
} | ||
stateStore.finalize(heightStr, batch); | ||
batch.del(diffKey); | ||
await batch.write(); | ||
await this._db.write(batch); | ||
return { | ||
@@ -345,12 +353,31 @@ deleted: deletedStates, | ||
} | ||
async _cleanUntil(height) { | ||
await this._db.clear({ | ||
gte: `${constants_1.DB_KEY_DIFF_STATE}:${lisk_db_1.formatInt(0)}`, | ||
lt: `${constants_1.DB_KEY_DIFF_STATE}:${lisk_db_1.formatInt(height)}`, | ||
}); | ||
async _cleanUntil(currentHeight, finalizedHeight) { | ||
if (finalizedHeight > 0) { | ||
await this._clear((0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_DIFF_STATE, (0, utils_1.uint32BE)(0)), (0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_DIFF_STATE, (0, utils_1.uint32BE)(finalizedHeight - 1))); | ||
} | ||
if (this._keepEventsForHeights > -1) { | ||
const minEventDeleteHeight = Math.min(finalizedHeight, Math.max(0, currentHeight - this._keepEventsForHeights)); | ||
if (minEventDeleteHeight > 0) { | ||
const endHeight = Buffer.alloc(4); | ||
endHeight.writeUInt32BE(minEventDeleteHeight - 1, 0); | ||
await this._clear(Buffer.concat([db_keys_1.DB_KEY_BLOCK_EVENTS, Buffer.alloc(4, 0)]), Buffer.concat([db_keys_1.DB_KEY_BLOCK_EVENTS, endHeight])); | ||
} | ||
} | ||
} | ||
async _getBlockAssets(blockID) { | ||
try { | ||
const encodedAssets = await this._db.get((0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_BLOCK_ASSETS_BLOCK_ID, blockID)); | ||
return decodeByteArray(encodedAssets); | ||
} | ||
catch (error) { | ||
if (!(error instanceof lisk_db_1.NotFoundError)) { | ||
throw error; | ||
} | ||
return []; | ||
} | ||
} | ||
async _getTransactions(blockID) { | ||
const txIDs = []; | ||
try { | ||
const ids = await this._db.get(`${constants_1.DB_KEY_TRANSACTIONS_BLOCK_ID}:${utils_1.keyString(blockID)}`); | ||
const ids = await this._db.get((0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_TRANSACTIONS_BLOCK_ID, blockID)); | ||
const idLength = 32; | ||
@@ -371,3 +398,3 @@ for (let i = 0; i < ids.length; i += idLength) { | ||
for (const txID of txIDs) { | ||
const tx = await this._db.get(`${constants_1.DB_KEY_TRANSACTIONS_ID}:${utils_1.keyString(txID)}`); | ||
const tx = await this._db.get((0, utils_1.concatDBKeys)(db_keys_1.DB_KEY_TRANSACTIONS_ID, txID)); | ||
transactions.push(tx); | ||
@@ -377,4 +404,25 @@ } | ||
} | ||
async _clear(gte, lte) { | ||
const stream = this._db.createReadStream({ | ||
gte, | ||
lte, | ||
}); | ||
const batch = new lisk_db_1.Batch(); | ||
await new Promise((resolve, reject) => { | ||
const ids = []; | ||
stream | ||
.on('data', ({ key }) => { | ||
batch.del(key); | ||
}) | ||
.on('error', error => { | ||
reject(error); | ||
}) | ||
.on('end', () => { | ||
resolve(ids); | ||
}); | ||
}); | ||
await this._db.write(batch); | ||
} | ||
} | ||
exports.Storage = Storage; | ||
//# sourceMappingURL=storage.js.map |
@@ -1,16 +0,13 @@ | ||
declare const events: { | ||
EVENT_DELETE_BLOCK: string; | ||
EVENT_NEW_BLOCK: string; | ||
EVENT_VALIDATORS_CHANGED: string; | ||
}; | ||
export { events }; | ||
export { Chain } from './chain'; | ||
export { Transaction, TransactionInput, transactionSchema, calculateMinFee } from './transaction'; | ||
export { blockHeaderAssetSchema, blockHeaderSchema, blockSchema, signingBlockHeaderSchema, validatorsSchema, getGenesisBlockHeaderAssetSchema, stateDiffSchema, getRegisteredBlockAssetSchema, } from './schema'; | ||
export { CONSENSUS_STATE_VALIDATORS_KEY, CONSENSUS_STATE_FINALIZED_HEIGHT_KEY } from './constants'; | ||
export type { Account, AccountDefaultProps, RawBlock, RawBlockHeader, GenesisBlock, GenesisBlockHeader, Block, BlockHeader, BlockHeaderAsset, Validator, AccountSchema, } from './types'; | ||
export { Slots } from './slots'; | ||
export { readGenesisBlockJSON, getValidators, getAccountSchemaWithDefault } from './utils'; | ||
export * as testing from './testing'; | ||
export type { StateStore } from './state_store'; | ||
export type { DataAccess } from './data_access'; | ||
export { Transaction, TransactionAttrs, transactionSchema, TransactionJSON } from './transaction'; | ||
export { blockHeaderSchema, blockSchema, signingBlockHeaderSchema, stateDiffSchema, blockAssetSchema, eventSchema, standardEventDataSchema, } from './schema'; | ||
export { TAG_BLOCK_HEADER, TAG_TRANSACTION, EVENT_MAX_TOPICS_PER_EVENT, EVENT_MAX_EVENT_SIZE_BYTES, MAX_EVENTS_PER_BLOCK, EVENT_KEY_LENGTH, NAME_REGEX, MAX_CROSS_CHAIN_COMMAND_NAME_LENGTH, MAX_MODULE_NAME_LENGTH, MIN_CROSS_CHAIN_COMMAND_NAME_LENGTH, MIN_MODULE_NAME_LENGTH, } from './constants'; | ||
export * from './db_keys'; | ||
export type { RawBlock } from './types'; | ||
export { concatDBKeys } from './utils'; | ||
export { StateStore, NotFoundError, CurrentState, SMTStore, IterateOptions } from './state_store'; | ||
export { Block, BlockJSON } from './block'; | ||
export { BlockAsset, BlockAssets, BlockAssetJSON } from './block_assets'; | ||
export { BlockHeader, BlockHeaderAttrs, BlockHeaderJSON } from './block_header'; | ||
export { DataAccess } from './data_access'; | ||
export { Event, EventAttr } from './event'; |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __exportStar = (this && this.__exportStar) || function(m, exports) { | ||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.testing = exports.getAccountSchemaWithDefault = exports.getValidators = exports.readGenesisBlockJSON = exports.Slots = exports.CONSENSUS_STATE_FINALIZED_HEIGHT_KEY = exports.CONSENSUS_STATE_VALIDATORS_KEY = exports.getRegisteredBlockAssetSchema = exports.stateDiffSchema = exports.getGenesisBlockHeaderAssetSchema = exports.validatorsSchema = exports.signingBlockHeaderSchema = exports.blockSchema = exports.blockHeaderSchema = exports.blockHeaderAssetSchema = exports.calculateMinFee = exports.transactionSchema = exports.Transaction = exports.Chain = exports.events = void 0; | ||
const constants_1 = require("./constants"); | ||
const events = { EVENT_DELETE_BLOCK: constants_1.EVENT_DELETE_BLOCK, EVENT_NEW_BLOCK: constants_1.EVENT_NEW_BLOCK, EVENT_VALIDATORS_CHANGED: constants_1.EVENT_VALIDATORS_CHANGED }; | ||
exports.events = events; | ||
exports.Event = exports.DataAccess = exports.BlockHeader = exports.BlockAssets = exports.Block = exports.SMTStore = exports.NotFoundError = exports.StateStore = exports.concatDBKeys = exports.MIN_MODULE_NAME_LENGTH = exports.MIN_CROSS_CHAIN_COMMAND_NAME_LENGTH = exports.MAX_MODULE_NAME_LENGTH = exports.MAX_CROSS_CHAIN_COMMAND_NAME_LENGTH = exports.NAME_REGEX = exports.EVENT_KEY_LENGTH = exports.MAX_EVENTS_PER_BLOCK = exports.EVENT_MAX_EVENT_SIZE_BYTES = exports.EVENT_MAX_TOPICS_PER_EVENT = exports.TAG_TRANSACTION = exports.TAG_BLOCK_HEADER = exports.standardEventDataSchema = exports.eventSchema = exports.blockAssetSchema = exports.stateDiffSchema = exports.signingBlockHeaderSchema = exports.blockSchema = exports.blockHeaderSchema = exports.transactionSchema = exports.Transaction = exports.Chain = void 0; | ||
var chain_1 = require("./chain"); | ||
@@ -12,22 +23,39 @@ Object.defineProperty(exports, "Chain", { enumerable: true, get: function () { return chain_1.Chain; } }); | ||
Object.defineProperty(exports, "transactionSchema", { enumerable: true, get: function () { return transaction_1.transactionSchema; } }); | ||
Object.defineProperty(exports, "calculateMinFee", { enumerable: true, get: function () { return transaction_1.calculateMinFee; } }); | ||
var schema_1 = require("./schema"); | ||
Object.defineProperty(exports, "blockHeaderAssetSchema", { enumerable: true, get: function () { return schema_1.blockHeaderAssetSchema; } }); | ||
Object.defineProperty(exports, "blockHeaderSchema", { enumerable: true, get: function () { return schema_1.blockHeaderSchema; } }); | ||
Object.defineProperty(exports, "blockSchema", { enumerable: true, get: function () { return schema_1.blockSchema; } }); | ||
Object.defineProperty(exports, "signingBlockHeaderSchema", { enumerable: true, get: function () { return schema_1.signingBlockHeaderSchema; } }); | ||
Object.defineProperty(exports, "validatorsSchema", { enumerable: true, get: function () { return schema_1.validatorsSchema; } }); | ||
Object.defineProperty(exports, "getGenesisBlockHeaderAssetSchema", { enumerable: true, get: function () { return schema_1.getGenesisBlockHeaderAssetSchema; } }); | ||
Object.defineProperty(exports, "stateDiffSchema", { enumerable: true, get: function () { return schema_1.stateDiffSchema; } }); | ||
Object.defineProperty(exports, "getRegisteredBlockAssetSchema", { enumerable: true, get: function () { return schema_1.getRegisteredBlockAssetSchema; } }); | ||
var constants_2 = require("./constants"); | ||
Object.defineProperty(exports, "CONSENSUS_STATE_VALIDATORS_KEY", { enumerable: true, get: function () { return constants_2.CONSENSUS_STATE_VALIDATORS_KEY; } }); | ||
Object.defineProperty(exports, "CONSENSUS_STATE_FINALIZED_HEIGHT_KEY", { enumerable: true, get: function () { return constants_2.CONSENSUS_STATE_FINALIZED_HEIGHT_KEY; } }); | ||
var slots_1 = require("./slots"); | ||
Object.defineProperty(exports, "Slots", { enumerable: true, get: function () { return slots_1.Slots; } }); | ||
Object.defineProperty(exports, "blockAssetSchema", { enumerable: true, get: function () { return schema_1.blockAssetSchema; } }); | ||
Object.defineProperty(exports, "eventSchema", { enumerable: true, get: function () { return schema_1.eventSchema; } }); | ||
Object.defineProperty(exports, "standardEventDataSchema", { enumerable: true, get: function () { return schema_1.standardEventDataSchema; } }); | ||
var constants_1 = require("./constants"); | ||
Object.defineProperty(exports, "TAG_BLOCK_HEADER", { enumerable: true, get: function () { return constants_1.TAG_BLOCK_HEADER; } }); | ||
Object.defineProperty(exports, "TAG_TRANSACTION", { enumerable: true, get: function () { return constants_1.TAG_TRANSACTION; } }); | ||
Object.defineProperty(exports, "EVENT_MAX_TOPICS_PER_EVENT", { enumerable: true, get: function () { return constants_1.EVENT_MAX_TOPICS_PER_EVENT; } }); | ||
Object.defineProperty(exports, "EVENT_MAX_EVENT_SIZE_BYTES", { enumerable: true, get: function () { return constants_1.EVENT_MAX_EVENT_SIZE_BYTES; } }); | ||
Object.defineProperty(exports, "MAX_EVENTS_PER_BLOCK", { enumerable: true, get: function () { return constants_1.MAX_EVENTS_PER_BLOCK; } }); | ||
Object.defineProperty(exports, "EVENT_KEY_LENGTH", { enumerable: true, get: function () { return constants_1.EVENT_KEY_LENGTH; } }); | ||
Object.defineProperty(exports, "NAME_REGEX", { enumerable: true, get: function () { return constants_1.NAME_REGEX; } }); | ||
Object.defineProperty(exports, "MAX_CROSS_CHAIN_COMMAND_NAME_LENGTH", { enumerable: true, get: function () { return constants_1.MAX_CROSS_CHAIN_COMMAND_NAME_LENGTH; } }); | ||
Object.defineProperty(exports, "MAX_MODULE_NAME_LENGTH", { enumerable: true, get: function () { return constants_1.MAX_MODULE_NAME_LENGTH; } }); | ||
Object.defineProperty(exports, "MIN_CROSS_CHAIN_COMMAND_NAME_LENGTH", { enumerable: true, get: function () { return constants_1.MIN_CROSS_CHAIN_COMMAND_NAME_LENGTH; } }); | ||
Object.defineProperty(exports, "MIN_MODULE_NAME_LENGTH", { enumerable: true, get: function () { return constants_1.MIN_MODULE_NAME_LENGTH; } }); | ||
__exportStar(require("./db_keys"), exports); | ||
var utils_1 = require("./utils"); | ||
Object.defineProperty(exports, "readGenesisBlockJSON", { enumerable: true, get: function () { return utils_1.readGenesisBlockJSON; } }); | ||
Object.defineProperty(exports, "getValidators", { enumerable: true, get: function () { return utils_1.getValidators; } }); | ||
Object.defineProperty(exports, "getAccountSchemaWithDefault", { enumerable: true, get: function () { return utils_1.getAccountSchemaWithDefault; } }); | ||
exports.testing = require("./testing"); | ||
Object.defineProperty(exports, "concatDBKeys", { enumerable: true, get: function () { return utils_1.concatDBKeys; } }); | ||
var state_store_1 = require("./state_store"); | ||
Object.defineProperty(exports, "StateStore", { enumerable: true, get: function () { return state_store_1.StateStore; } }); | ||
Object.defineProperty(exports, "NotFoundError", { enumerable: true, get: function () { return state_store_1.NotFoundError; } }); | ||
Object.defineProperty(exports, "SMTStore", { enumerable: true, get: function () { return state_store_1.SMTStore; } }); | ||
var block_1 = require("./block"); | ||
Object.defineProperty(exports, "Block", { enumerable: true, get: function () { return block_1.Block; } }); | ||
var block_assets_1 = require("./block_assets"); | ||
Object.defineProperty(exports, "BlockAssets", { enumerable: true, get: function () { return block_assets_1.BlockAssets; } }); | ||
var block_header_1 = require("./block_header"); | ||
Object.defineProperty(exports, "BlockHeader", { enumerable: true, get: function () { return block_header_1.BlockHeader; } }); | ||
var data_access_1 = require("./data_access"); | ||
Object.defineProperty(exports, "DataAccess", { enumerable: true, get: function () { return data_access_1.DataAccess; } }); | ||
var event_1 = require("./event"); | ||
Object.defineProperty(exports, "Event", { enumerable: true, get: function () { return event_1.Event; } }); | ||
//# sourceMappingURL=index.js.map |
@@ -1,2 +0,1 @@ | ||
import { Schema } from '@liskhq/lisk-codec'; | ||
export declare const blockSchema: { | ||
@@ -10,3 +9,3 @@ $id: string; | ||
}; | ||
payload: { | ||
transactions: { | ||
type: string; | ||
@@ -18,2 +17,9 @@ items: { | ||
}; | ||
assets: { | ||
type: string; | ||
items: { | ||
dataType: string; | ||
}; | ||
fieldNumber: number; | ||
}; | ||
}; | ||
@@ -42,2 +48,7 @@ required: string[]; | ||
}; | ||
generatorAddress: { | ||
dataType: string; | ||
fieldNumber: number; | ||
format: string; | ||
}; | ||
transactionRoot: { | ||
@@ -47,14 +58,49 @@ dataType: string; | ||
}; | ||
generatorPublicKey: { | ||
assetRoot: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
reward: { | ||
eventRoot: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
asset: { | ||
stateRoot: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
maxHeightPrevoted: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
maxHeightGenerated: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
impliesMaxPrevotes: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
validatorsHash: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
aggregateCommit: { | ||
type: string; | ||
fieldNumber: number; | ||
required: string[]; | ||
properties: { | ||
height: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
aggregationBits: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
certificateSignature: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
}; | ||
}; | ||
}; | ||
@@ -65,2 +111,3 @@ required: string[]; | ||
$id: string; | ||
required: string[]; | ||
properties: { | ||
@@ -87,2 +134,7 @@ signature: { | ||
}; | ||
generatorAddress: { | ||
dataType: string; | ||
fieldNumber: number; | ||
format: string; | ||
}; | ||
transactionRoot: { | ||
@@ -92,73 +144,153 @@ dataType: string; | ||
}; | ||
generatorPublicKey: { | ||
assetRoot: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
reward: { | ||
eventRoot: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
asset: { | ||
stateRoot: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
maxHeightPrevoted: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
maxHeightGenerated: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
impliesMaxPrevotes: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
validatorsHash: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
aggregateCommit: { | ||
type: string; | ||
fieldNumber: number; | ||
required: string[]; | ||
properties: { | ||
height: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
aggregationBits: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
certificateSignature: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
}; | ||
}; | ||
}; | ||
type: string; | ||
required: string[]; | ||
}; | ||
export declare const baseGenesisBlockHeaderAssetSchema: { | ||
export declare const blockHeaderSchemaWithId: { | ||
$id: string; | ||
type: string; | ||
required: string[]; | ||
properties: { | ||
accounts: { | ||
type: string; | ||
id: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
initDelegates: { | ||
type: string; | ||
items: { | ||
dataType: string; | ||
}; | ||
signature: { | ||
dataType: string; | ||
fieldNumber: number; | ||
minItems: number; | ||
}; | ||
initRounds: { | ||
version: { | ||
dataType: string; | ||
fieldNumber: number; | ||
minimum: number; | ||
}; | ||
}; | ||
}; | ||
export declare const baseAccountSchema: { | ||
$id: string; | ||
type: string; | ||
properties: { | ||
address: { | ||
timestamp: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
height: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
previousBlockID: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
generatorAddress: { | ||
dataType: string; | ||
fieldNumber: number; | ||
format: string; | ||
}; | ||
transactionRoot: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
assetRoot: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
eventRoot: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
stateRoot: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
maxHeightPrevoted: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
maxHeightGenerated: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
impliesMaxPrevotes: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
validatorsHash: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
aggregateCommit: { | ||
type: string; | ||
fieldNumber: number; | ||
required: string[]; | ||
properties: { | ||
height: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
aggregationBits: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
certificateSignature: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
}; | ||
}; | ||
}; | ||
required: string[]; | ||
type: string; | ||
}; | ||
export declare const blockHeaderAssetSchema: { | ||
export declare const blockAssetSchema: { | ||
$id: string; | ||
type: string; | ||
required: string[]; | ||
properties: { | ||
maxHeightPreviouslyForged: { | ||
module: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
maxHeightPrevoted: { | ||
data: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
seedReveal: { | ||
dataType: string; | ||
minLength: number; | ||
maxLength: number; | ||
fieldNumber: number; | ||
}; | ||
}; | ||
required: string[]; | ||
}; | ||
@@ -213,3 +345,3 @@ export declare const stateDiffSchema: { | ||
}; | ||
export declare const validatorsSchema: { | ||
export declare const eventSchema: { | ||
$id: string; | ||
@@ -219,44 +351,45 @@ type: string; | ||
properties: { | ||
validators: { | ||
module: { | ||
dataType: string; | ||
minLength: number; | ||
maxLength: number; | ||
fieldNumber: number; | ||
}; | ||
name: { | ||
dataType: string; | ||
minLength: number; | ||
maxLength: number; | ||
fieldNumber: number; | ||
}; | ||
data: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
topics: { | ||
type: string; | ||
fieldNumber: number; | ||
items: { | ||
type: string; | ||
properties: { | ||
address: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
minActiveHeight: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
isConsensusParticipant: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
}; | ||
required: string[]; | ||
dataType: string; | ||
}; | ||
}; | ||
height: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
index: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
}; | ||
}; | ||
export declare const genesisInfoSchema: { | ||
export declare const standardEventDataSchema: { | ||
$id: string; | ||
type: string; | ||
required: string[]; | ||
properties: { | ||
height: { | ||
success: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
initRounds: { | ||
dataType: string; | ||
fieldNumber: number; | ||
}; | ||
}; | ||
required: string[]; | ||
}; | ||
export declare const getGenesisBlockHeaderAssetSchema: (accountSchema: Schema) => Schema; | ||
export declare const getRegisteredBlockAssetSchema: (accountSchema: Schema) => { | ||
readonly [key: number]: Schema; | ||
}; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getRegisteredBlockAssetSchema = exports.getGenesisBlockHeaderAssetSchema = exports.genesisInfoSchema = exports.validatorsSchema = exports.stateDiffSchema = exports.blockHeaderAssetSchema = exports.baseAccountSchema = exports.baseGenesisBlockHeaderAssetSchema = exports.blockHeaderSchema = exports.signingBlockHeaderSchema = exports.blockSchema = void 0; | ||
const lisk_utils_1 = require("@liskhq/lisk-utils"); | ||
exports.standardEventDataSchema = exports.eventSchema = exports.stateDiffSchema = exports.blockAssetSchema = exports.blockHeaderSchemaWithId = exports.blockHeaderSchema = exports.signingBlockHeaderSchema = exports.blockSchema = void 0; | ||
const constants_1 = require("./constants"); | ||
exports.blockSchema = { | ||
@@ -13,3 +13,3 @@ $id: '/block', | ||
}, | ||
payload: { | ||
transactions: { | ||
type: 'array', | ||
@@ -21,7 +21,14 @@ items: { | ||
}, | ||
assets: { | ||
type: 'array', | ||
items: { | ||
dataType: 'bytes', | ||
}, | ||
fieldNumber: 3, | ||
}, | ||
}, | ||
required: ['header', 'payload'], | ||
required: ['header', 'transactions', 'assets'], | ||
}; | ||
exports.signingBlockHeaderSchema = { | ||
$id: '/block/header/signing', | ||
$id: '/block/header/signing/3', | ||
type: 'object', | ||
@@ -33,6 +40,30 @@ properties: { | ||
previousBlockID: { dataType: 'bytes', fieldNumber: 4 }, | ||
transactionRoot: { dataType: 'bytes', fieldNumber: 5 }, | ||
generatorPublicKey: { dataType: 'bytes', fieldNumber: 6 }, | ||
reward: { dataType: 'uint64', fieldNumber: 7 }, | ||
asset: { dataType: 'bytes', fieldNumber: 8 }, | ||
generatorAddress: { dataType: 'bytes', fieldNumber: 5, format: 'lisk32' }, | ||
transactionRoot: { dataType: 'bytes', fieldNumber: 6 }, | ||
assetRoot: { dataType: 'bytes', fieldNumber: 7 }, | ||
eventRoot: { dataType: 'bytes', fieldNumber: 8 }, | ||
stateRoot: { dataType: 'bytes', fieldNumber: 9 }, | ||
maxHeightPrevoted: { dataType: 'uint32', fieldNumber: 10 }, | ||
maxHeightGenerated: { dataType: 'uint32', fieldNumber: 11 }, | ||
impliesMaxPrevotes: { dataType: 'boolean', fieldNumber: 12 }, | ||
validatorsHash: { dataType: 'bytes', fieldNumber: 13 }, | ||
aggregateCommit: { | ||
type: 'object', | ||
fieldNumber: 14, | ||
required: ['height', 'aggregationBits', 'certificateSignature'], | ||
properties: { | ||
height: { | ||
dataType: 'uint32', | ||
fieldNumber: 1, | ||
}, | ||
aggregationBits: { | ||
dataType: 'bytes', | ||
fieldNumber: 2, | ||
}, | ||
certificateSignature: { | ||
dataType: 'bytes', | ||
fieldNumber: 3, | ||
}, | ||
}, | ||
}, | ||
}, | ||
@@ -44,6 +75,12 @@ required: [ | ||
'previousBlockID', | ||
'generatorAddress', | ||
'transactionRoot', | ||
'generatorPublicKey', | ||
'reward', | ||
'asset', | ||
'assetRoot', | ||
'eventRoot', | ||
'stateRoot', | ||
'maxHeightPrevoted', | ||
'maxHeightGenerated', | ||
'impliesMaxPrevotes', | ||
'validatorsHash', | ||
'aggregateCommit', | ||
], | ||
@@ -53,60 +90,32 @@ }; | ||
...exports.signingBlockHeaderSchema, | ||
$id: '/block/header', | ||
$id: '/block/header/3', | ||
required: [...exports.signingBlockHeaderSchema.required, 'signature'], | ||
properties: { | ||
...exports.signingBlockHeaderSchema.properties, | ||
signature: { dataType: 'bytes', fieldNumber: 9 }, | ||
signature: { dataType: 'bytes', fieldNumber: 15 }, | ||
}, | ||
}; | ||
exports.baseGenesisBlockHeaderAssetSchema = { | ||
$id: '/genesisBlock/header/asset', | ||
type: 'object', | ||
required: ['accounts', 'initDelegates', 'initRounds'], | ||
exports.blockHeaderSchemaWithId = { | ||
...exports.blockHeaderSchema, | ||
$id: '/block/header/3', | ||
required: [...exports.blockHeaderSchema.required, 'id'], | ||
properties: { | ||
accounts: { | ||
type: 'array', | ||
fieldNumber: 1, | ||
}, | ||
initDelegates: { | ||
type: 'array', | ||
items: { | ||
dataType: 'bytes', | ||
}, | ||
fieldNumber: 2, | ||
minItems: 1, | ||
}, | ||
initRounds: { | ||
dataType: 'uint32', | ||
fieldNumber: 3, | ||
minimum: 3, | ||
}, | ||
...exports.blockHeaderSchema.properties, | ||
id: { dataType: 'bytes', fieldNumber: 16 }, | ||
}, | ||
}; | ||
exports.baseAccountSchema = { | ||
$id: '/account/base', | ||
exports.blockAssetSchema = { | ||
$id: '/block/asset/3', | ||
type: 'object', | ||
required: ['module', 'data'], | ||
properties: { | ||
address: { dataType: 'bytes', fieldNumber: 1 }, | ||
}, | ||
required: ['address'], | ||
}; | ||
exports.blockHeaderAssetSchema = { | ||
$id: '/blockHeader/asset/v2', | ||
type: 'object', | ||
properties: { | ||
maxHeightPreviouslyForged: { | ||
dataType: 'uint32', | ||
module: { | ||
dataType: 'string', | ||
fieldNumber: 1, | ||
}, | ||
maxHeightPrevoted: { | ||
dataType: 'uint32', | ||
data: { | ||
dataType: 'bytes', | ||
fieldNumber: 2, | ||
}, | ||
seedReveal: { | ||
dataType: 'bytes', | ||
minLength: 16, | ||
maxLength: 16, | ||
fieldNumber: 3, | ||
}, | ||
}, | ||
required: ['maxHeightPreviouslyForged', 'maxHeightPrevoted', 'seedReveal'], | ||
}; | ||
@@ -125,3 +134,3 @@ exports.stateDiffSchema = { | ||
key: { | ||
dataType: 'string', | ||
dataType: 'bytes', | ||
fieldNumber: 1, | ||
@@ -140,3 +149,3 @@ }, | ||
items: { | ||
dataType: 'string', | ||
dataType: 'bytes', | ||
}, | ||
@@ -151,3 +160,3 @@ }, | ||
key: { | ||
dataType: 'string', | ||
dataType: 'bytes', | ||
fieldNumber: 1, | ||
@@ -164,61 +173,51 @@ }, | ||
}; | ||
exports.validatorsSchema = { | ||
$id: '/state/validators', | ||
exports.eventSchema = { | ||
$id: '/block/event', | ||
type: 'object', | ||
required: ['validators'], | ||
required: ['module', 'name', 'data', 'topics', 'height', 'index'], | ||
properties: { | ||
validators: { | ||
module: { | ||
dataType: 'string', | ||
minLength: constants_1.MIN_MODULE_NAME_LENGTH, | ||
maxLength: constants_1.MAX_MODULE_NAME_LENGTH, | ||
fieldNumber: 1, | ||
}, | ||
name: { | ||
dataType: 'string', | ||
minLength: constants_1.MIN_EVENT_NAME_LENGTH, | ||
maxLength: constants_1.MAX_EVENT_NAME_LENGTH, | ||
fieldNumber: 2, | ||
}, | ||
data: { | ||
dataType: 'bytes', | ||
fieldNumber: 3, | ||
}, | ||
topics: { | ||
type: 'array', | ||
fieldNumber: 1, | ||
fieldNumber: 4, | ||
items: { | ||
type: 'object', | ||
properties: { | ||
address: { | ||
dataType: 'bytes', | ||
fieldNumber: 1, | ||
}, | ||
minActiveHeight: { | ||
dataType: 'uint32', | ||
fieldNumber: 2, | ||
}, | ||
isConsensusParticipant: { | ||
dataType: 'boolean', | ||
fieldNumber: 3, | ||
}, | ||
}, | ||
required: ['address', 'minActiveHeight', 'isConsensusParticipant'], | ||
dataType: 'bytes', | ||
}, | ||
}, | ||
}, | ||
}; | ||
exports.genesisInfoSchema = { | ||
$id: '/state/genesisInfo', | ||
type: 'object', | ||
properties: { | ||
height: { | ||
dataType: 'uint32', | ||
fieldNumber: 1, | ||
fieldNumber: 5, | ||
}, | ||
initRounds: { | ||
index: { | ||
dataType: 'uint32', | ||
fieldNumber: 2, | ||
fieldNumber: 6, | ||
}, | ||
}, | ||
required: ['height', 'initRounds'], | ||
}; | ||
const getGenesisBlockHeaderAssetSchema = (accountSchema) => lisk_utils_1.objects.mergeDeep({}, exports.baseGenesisBlockHeaderAssetSchema, { | ||
exports.standardEventDataSchema = { | ||
$id: '/block/event/standard', | ||
type: 'object', | ||
required: ['success'], | ||
properties: { | ||
accounts: { | ||
items: { | ||
...accountSchema, | ||
}, | ||
success: { | ||
dataType: 'boolean', | ||
fieldNumber: 1, | ||
}, | ||
}, | ||
}); | ||
exports.getGenesisBlockHeaderAssetSchema = getGenesisBlockHeaderAssetSchema; | ||
const getRegisteredBlockAssetSchema = (accountSchema) => ({ | ||
0: exports.getGenesisBlockHeaderAssetSchema(accountSchema), | ||
2: exports.blockHeaderAssetSchema, | ||
}); | ||
exports.getRegisteredBlockAssetSchema = getRegisteredBlockAssetSchema; | ||
}; | ||
//# sourceMappingURL=schema.js.map |
@@ -1,1 +0,3 @@ | ||
export { StateStore } from './state_store'; | ||
export { NotFoundError } from './errors'; | ||
export { CurrentState, SMTStore } from './smt_store'; | ||
export { StateStore, IterateOptions } from './state_store'; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.StateStore = void 0; | ||
exports.StateStore = exports.SMTStore = exports.NotFoundError = void 0; | ||
var errors_1 = require("./errors"); | ||
Object.defineProperty(exports, "NotFoundError", { enumerable: true, get: function () { return errors_1.NotFoundError; } }); | ||
var smt_store_1 = require("./smt_store"); | ||
Object.defineProperty(exports, "SMTStore", { enumerable: true, get: function () { return smt_store_1.SMTStore; } }); | ||
var state_store_1 = require("./state_store"); | ||
Object.defineProperty(exports, "StateStore", { enumerable: true, get: function () { return state_store_1.StateStore; } }); | ||
//# sourceMappingURL=index.js.map |
/// <reference types="node" /> | ||
import { BatchChain } from '@liskhq/lisk-db'; | ||
import { BlockHeader } from '../types'; | ||
import { AccountStore } from './account_store'; | ||
import { ChainStateStore } from './chain_state_store'; | ||
import { ConsensusStateStore } from './consensus_state_store'; | ||
import { DataAccess } from '../data_access'; | ||
interface AdditionalInformation { | ||
readonly lastBlockHeaders: ReadonlyArray<BlockHeader>; | ||
readonly networkIdentifier: Buffer; | ||
readonly lastBlockReward: bigint; | ||
readonly defaultAccount: Record<string, unknown>; | ||
import { Schema } from '@liskhq/lisk-codec'; | ||
import { IterateOptions } from '@liskhq/lisk-db'; | ||
import { StateDiff } from '../types'; | ||
import { CacheDB } from './cache_db'; | ||
import { DatabaseReader, DatabaseWriter } from './types'; | ||
export { IterateOptions }; | ||
export interface KeyValue { | ||
key: Buffer; | ||
value: Buffer; | ||
} | ||
export interface DecodedKeyValue<T> { | ||
key: Buffer; | ||
value: T; | ||
} | ||
export declare class StateStore { | ||
readonly account: AccountStore; | ||
readonly chain: ChainStateStore; | ||
readonly consensus: ConsensusStateStore; | ||
constructor(dataAccess: DataAccess, additionalInformation: AdditionalInformation); | ||
createSnapshot(): void; | ||
restoreSnapshot(): void; | ||
finalize(height: string, batch: BatchChain): void; | ||
private readonly _db; | ||
private readonly _prefix; | ||
private _cache; | ||
private _snapshot; | ||
constructor(db: DatabaseReader, prefix?: Buffer, cache?: CacheDB); | ||
getStore(storePrefix: Buffer, subStorePrefix: Buffer | number): StateStore; | ||
get(key: Buffer): Promise<Buffer>; | ||
getWithSchema<T>(key: Buffer, schema: Schema): Promise<T>; | ||
has(key: Buffer): Promise<boolean>; | ||
set(key: Buffer, value: Buffer): Promise<void>; | ||
setWithSchema(key: Buffer, value: object, schema: Schema): Promise<void>; | ||
del(key: Buffer): Promise<void>; | ||
iterate(options: IterateOptions): Promise<KeyValue[]>; | ||
iterateWithSchema<T>(options: IterateOptions, schema: Schema): Promise<DecodedKeyValue<T>[]>; | ||
createSnapshot(): number; | ||
restoreSnapshot(_id: number): void; | ||
finalize(batch: DatabaseWriter): StateDiff; | ||
private _ensureCache; | ||
private _getKey; | ||
} | ||
export {}; |
@@ -5,51 +5,192 @@ "use strict"; | ||
const lisk_codec_1 = require("@liskhq/lisk-codec"); | ||
const account_store_1 = require("./account_store"); | ||
const chain_state_store_1 = require("./chain_state_store"); | ||
const consensus_state_store_1 = require("./consensus_state_store"); | ||
const constants_1 = require("../data_access/constants"); | ||
const schema_1 = require("../schema"); | ||
const saveDiff = (height, stateDiffs, batch) => { | ||
const diffToEncode = { | ||
updated: [], | ||
created: [], | ||
deleted: [], | ||
}; | ||
for (const diff of stateDiffs) { | ||
diffToEncode.updated = diffToEncode.updated.concat(diff.updated); | ||
diffToEncode.created = diffToEncode.created.concat(diff.created); | ||
diffToEncode.deleted = diffToEncode.deleted.concat(diff.deleted); | ||
const lisk_db_1 = require("@liskhq/lisk-db"); | ||
const db_keys_1 = require("../db_keys"); | ||
const cache_db_1 = require("./cache_db"); | ||
const errors_1 = require("./errors"); | ||
const utils_1 = require("./utils"); | ||
class StateStore { | ||
constructor(db, prefix, cache) { | ||
this._db = db; | ||
this._prefix = prefix !== null && prefix !== void 0 ? prefix : db_keys_1.DB_KEY_STATE_STORE; | ||
this._cache = cache !== null && cache !== void 0 ? cache : new cache_db_1.CacheDB(); | ||
} | ||
const encodedDiff = lisk_codec_1.codec.encode(schema_1.stateDiffSchema, diffToEncode); | ||
batch.put(`${constants_1.DB_KEY_DIFF_STATE}:${height}`, encodedDiff); | ||
}; | ||
class StateStore { | ||
constructor(dataAccess, additionalInformation) { | ||
this.account = new account_store_1.AccountStore(dataAccess, { | ||
defaultAccount: additionalInformation.defaultAccount, | ||
getStore(storePrefix, subStorePrefix) { | ||
let storePrefixBuffer; | ||
if (typeof subStorePrefix === 'number') { | ||
storePrefixBuffer = Buffer.alloc(2); | ||
storePrefixBuffer.writeUInt16BE(subStorePrefix, 0); | ||
} | ||
else { | ||
storePrefixBuffer = subStorePrefix; | ||
} | ||
const subStore = new StateStore(this._db, Buffer.concat([db_keys_1.DB_KEY_STATE_STORE, storePrefix, storePrefixBuffer]), this._cache); | ||
return subStore; | ||
} | ||
async get(key) { | ||
const prefixedKey = this._getKey(key); | ||
const { value, deleted } = this._cache.get(prefixedKey); | ||
if (value) { | ||
return (0, utils_1.copyBuffer)(value); | ||
} | ||
if (deleted) { | ||
throw new errors_1.NotFoundError(`Specified key ${prefixedKey.toString('hex')} does not exist`); | ||
} | ||
let persistedValue; | ||
try { | ||
persistedValue = await this._db.get(prefixedKey); | ||
} | ||
catch (error) { | ||
if (error instanceof lisk_db_1.NotFoundError) { | ||
throw new errors_1.NotFoundError(`Specified key ${prefixedKey.toString('hex')} does not exist`); | ||
} | ||
throw error; | ||
} | ||
this._cache.cache(prefixedKey, persistedValue); | ||
return (0, utils_1.copyBuffer)(persistedValue); | ||
} | ||
async getWithSchema(key, schema) { | ||
const value = await this.get(key); | ||
return lisk_codec_1.codec.decode(schema, value); | ||
} | ||
async has(key) { | ||
try { | ||
await this.get(key); | ||
return true; | ||
} | ||
catch (error) { | ||
if (!(error instanceof errors_1.NotFoundError)) { | ||
throw error; | ||
} | ||
return false; | ||
} | ||
} | ||
async set(key, value) { | ||
const prefixedKey = this._getKey(key); | ||
if (this._cache.existAny(prefixedKey)) { | ||
this._cache.set(prefixedKey, value); | ||
return; | ||
} | ||
const dataExist = await this._ensureCache(prefixedKey); | ||
if (dataExist) { | ||
this._cache.set(prefixedKey, value); | ||
return; | ||
} | ||
this._cache.add(prefixedKey, value); | ||
} | ||
async setWithSchema(key, value, schema) { | ||
const encodedValue = lisk_codec_1.codec.encode(schema, value); | ||
await this.set(key, encodedValue); | ||
} | ||
async del(key) { | ||
const prefixedKey = this._getKey(key); | ||
if (!this._cache.existAny(prefixedKey)) { | ||
await this._ensureCache(prefixedKey); | ||
} | ||
this._cache.del(prefixedKey); | ||
} | ||
async iterate(options) { | ||
const start = this._getKey(options.gte); | ||
const end = this._getKey(options.lte); | ||
const stream = this._db.createReadStream({ | ||
gte: start, | ||
lte: end, | ||
reverse: options.reverse, | ||
limit: options.limit, | ||
}); | ||
this.consensus = new consensus_state_store_1.ConsensusStateStore(dataAccess); | ||
this.chain = new chain_state_store_1.ChainStateStore(dataAccess, { | ||
lastBlockHeaders: additionalInformation.lastBlockHeaders, | ||
networkIdentifier: additionalInformation.networkIdentifier, | ||
lastBlockReward: additionalInformation.lastBlockReward, | ||
const storedData = await new Promise((resolve, reject) => { | ||
const values = []; | ||
stream | ||
.on('data', ({ key: prefixedKey, value }) => { | ||
const { value: cachedValue, deleted } = this._cache.get(prefixedKey); | ||
if (cachedValue) { | ||
values.push({ | ||
key: prefixedKey, | ||
value: (0, utils_1.copyBuffer)(cachedValue), | ||
}); | ||
return; | ||
} | ||
if (deleted) { | ||
return; | ||
} | ||
this._cache.cache(prefixedKey, value); | ||
values.push({ | ||
key: prefixedKey, | ||
value, | ||
}); | ||
}) | ||
.on('error', error => { | ||
reject(error); | ||
}) | ||
.on('end', () => { | ||
resolve(values); | ||
}); | ||
}); | ||
const cachedValues = this._cache.getRange(start, end); | ||
const existingKey = {}; | ||
const result = []; | ||
for (const data of cachedValues) { | ||
existingKey[data.key.toString('binary')] = true; | ||
result.push({ | ||
key: data.key.slice(this._prefix.length), | ||
value: data.value, | ||
}); | ||
} | ||
for (const data of storedData) { | ||
if (existingKey[data.key.toString('binary')] === undefined) { | ||
result.push({ | ||
key: data.key.slice(this._prefix.length), | ||
value: data.value, | ||
}); | ||
} | ||
} | ||
result.sort((a, b) => { | ||
if (options.reverse) { | ||
return b.key.compare(a.key); | ||
} | ||
return a.key.compare(b.key); | ||
}); | ||
if (options.limit) { | ||
result.splice(options.limit); | ||
} | ||
return result; | ||
} | ||
async iterateWithSchema(options, schema) { | ||
const result = await this.iterate(options); | ||
return result.map(kv => ({ | ||
key: kv.key, | ||
value: lisk_codec_1.codec.decode(schema, kv.value), | ||
})); | ||
} | ||
createSnapshot() { | ||
this.account.createSnapshot(); | ||
this.consensus.createSnapshot(); | ||
this.chain.createSnapshot(); | ||
this._snapshot = this._cache.copy(); | ||
return 0; | ||
} | ||
restoreSnapshot() { | ||
this.account.restoreSnapshot(); | ||
this.consensus.restoreSnapshot(); | ||
this.chain.restoreSnapshot(); | ||
restoreSnapshot(_id) { | ||
if (!this._snapshot) { | ||
throw new Error('Snapshot must be taken first before reverting'); | ||
} | ||
this._cache = this._snapshot; | ||
this._snapshot = undefined; | ||
} | ||
finalize(height, batch) { | ||
const accountStateDiff = this.account.finalize(batch); | ||
const chainStateDiff = this.chain.finalize(batch); | ||
const consensusStateDiff = this.consensus.finalize(batch); | ||
saveDiff(height, [accountStateDiff, chainStateDiff, consensusStateDiff], batch); | ||
finalize(batch) { | ||
return this._cache.finalize(batch); | ||
} | ||
async _ensureCache(prefixedKey) { | ||
try { | ||
const value = await this._db.get(prefixedKey); | ||
this._cache.cache(prefixedKey, value); | ||
return true; | ||
} | ||
catch (error) { | ||
if (error instanceof lisk_db_1.NotFoundError) { | ||
return false; | ||
} | ||
throw error; | ||
} | ||
} | ||
_getKey(key) { | ||
return Buffer.concat([this._prefix, key]); | ||
} | ||
} | ||
exports.StateStore = StateStore; | ||
//# sourceMappingURL=state_store.js.map |
/// <reference types="node" /> | ||
export interface TransactionInput { | ||
readonly moduleID: number; | ||
readonly assetID: number; | ||
import { JSONObject } from './types'; | ||
export interface TransactionAttrs { | ||
readonly module: string; | ||
readonly command: string; | ||
readonly senderPublicKey: Buffer; | ||
readonly nonce: bigint; | ||
readonly fee: bigint; | ||
readonly asset: Buffer; | ||
readonly params: Buffer; | ||
readonly signatures: ReadonlyArray<Buffer>; | ||
readonly id?: Buffer; | ||
} | ||
export type TransactionJSON = JSONObject<TransactionAttrs> & { | ||
id: string; | ||
}; | ||
export declare const transactionSchema: { | ||
@@ -16,10 +21,13 @@ $id: string; | ||
properties: { | ||
moduleID: { | ||
module: { | ||
dataType: string; | ||
fieldNumber: number; | ||
minimum: number; | ||
minLength: number; | ||
maxLength: number; | ||
}; | ||
assetID: { | ||
command: { | ||
dataType: string; | ||
fieldNumber: number; | ||
minLength: number; | ||
maxLength: number; | ||
}; | ||
@@ -40,3 +48,3 @@ nonce: { | ||
}; | ||
asset: { | ||
params: { | ||
dataType: string; | ||
@@ -54,19 +62,15 @@ fieldNumber: number; | ||
}; | ||
export declare const calculateMinFee: (tx: Transaction, minFeePerByte: number, baseFees: { | ||
moduleID: number; | ||
assetID: number; | ||
baseFee: string; | ||
}[]) => bigint; | ||
export declare class Transaction { | ||
readonly moduleID: number; | ||
readonly assetID: number; | ||
readonly asset: Buffer; | ||
readonly module: string; | ||
readonly command: string; | ||
readonly params: Buffer; | ||
readonly nonce: bigint; | ||
readonly fee: bigint; | ||
readonly senderPublicKey: Buffer; | ||
readonly signatures: ReadonlyArray<Buffer>; | ||
readonly signatures: Buffer[]; | ||
private _id?; | ||
private _senderAddress?; | ||
constructor(transaction: TransactionInput); | ||
static decode(bytes: Buffer): Transaction; | ||
constructor(transaction: TransactionAttrs); | ||
static fromBytes(bytes: Buffer): Transaction; | ||
static fromJSON(value: TransactionJSON): Transaction; | ||
get id(): Buffer; | ||
@@ -76,10 +80,7 @@ get senderAddress(): Buffer; | ||
getSigningBytes(): Buffer; | ||
validate(input: { | ||
minFeePerByte: number; | ||
baseFees: { | ||
moduleID: number; | ||
assetID: number; | ||
baseFee: string; | ||
}[]; | ||
}): void; | ||
sign(chainID: Buffer, privateKey: Buffer): void; | ||
validate(): void; | ||
toJSON(): TransactionJSON; | ||
toObject(): TransactionAttrs; | ||
private _getProps; | ||
} |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Transaction = exports.calculateMinFee = exports.transactionSchema = void 0; | ||
exports.Transaction = exports.transactionSchema = void 0; | ||
const lisk_codec_1 = require("@liskhq/lisk-codec"); | ||
const lisk_cryptography_1 = require("@liskhq/lisk-cryptography"); | ||
const lisk_validator_1 = require("@liskhq/lisk-validator"); | ||
const constants_1 = require("./constants"); | ||
exports.transactionSchema = { | ||
$id: 'lisk/transaction', | ||
$id: '/lisk/transaction', | ||
type: 'object', | ||
required: ['moduleID', 'assetID', 'nonce', 'fee', 'senderPublicKey', 'asset'], | ||
required: ['module', 'command', 'nonce', 'fee', 'senderPublicKey', 'params'], | ||
properties: { | ||
moduleID: { | ||
dataType: 'uint32', | ||
module: { | ||
dataType: 'string', | ||
fieldNumber: 1, | ||
minimum: 2, | ||
minLength: 1, | ||
maxLength: 32, | ||
}, | ||
assetID: { | ||
dataType: 'uint32', | ||
command: { | ||
dataType: 'string', | ||
fieldNumber: 2, | ||
minLength: 1, | ||
maxLength: 32, | ||
}, | ||
@@ -35,3 +39,3 @@ nonce: { | ||
}, | ||
asset: { | ||
params: { | ||
dataType: 'bytes', | ||
@@ -49,26 +53,23 @@ fieldNumber: 6, | ||
}; | ||
const calculateMinFee = (tx, minFeePerByte, baseFees) => { | ||
var _a, _b; | ||
const size = tx.getBytes().length; | ||
const baseFee = (_b = (_a = baseFees.find(bf => bf.moduleID === tx.moduleID && bf.assetID === tx.assetID)) === null || _a === void 0 ? void 0 : _a.baseFee) !== null && _b !== void 0 ? _b : '0'; | ||
return BigInt(minFeePerByte * size) + BigInt(baseFee); | ||
}; | ||
exports.calculateMinFee = calculateMinFee; | ||
class Transaction { | ||
constructor(transaction) { | ||
this.moduleID = transaction.moduleID; | ||
this.assetID = transaction.assetID; | ||
this.asset = transaction.asset; | ||
this.module = transaction.module; | ||
this.command = transaction.command; | ||
this.params = transaction.params; | ||
this.nonce = transaction.nonce; | ||
this.fee = transaction.fee; | ||
this.senderPublicKey = transaction.senderPublicKey; | ||
this.signatures = transaction.signatures; | ||
this.signatures = [...transaction.signatures]; | ||
} | ||
static decode(bytes) { | ||
static fromBytes(bytes) { | ||
const tx = lisk_codec_1.codec.decode(exports.transactionSchema, bytes); | ||
return new Transaction(tx); | ||
} | ||
static fromJSON(value) { | ||
const tx = lisk_codec_1.codec.fromJSON(exports.transactionSchema, value); | ||
return new Transaction(tx); | ||
} | ||
get id() { | ||
if (!this._id) { | ||
this._id = lisk_cryptography_1.hash(this.getBytes()); | ||
this._id = lisk_cryptography_1.utils.hash(this.getBytes()); | ||
} | ||
@@ -79,3 +80,3 @@ return this._id; | ||
if (!this._senderAddress) { | ||
this._senderAddress = lisk_cryptography_1.getAddressFromPublicKey(this.senderPublicKey); | ||
this._senderAddress = lisk_cryptography_1.address.getAddressFromPublicKey(this.senderPublicKey); | ||
} | ||
@@ -85,4 +86,3 @@ return this._senderAddress; | ||
getBytes() { | ||
const transactionBytes = lisk_codec_1.codec.encode(exports.transactionSchema, this); | ||
return transactionBytes; | ||
return lisk_codec_1.codec.encode(exports.transactionSchema, this); | ||
} | ||
@@ -96,7 +96,17 @@ getSigningBytes() { | ||
} | ||
validate(input) { | ||
const schemaErrors = lisk_validator_1.validator.validate(exports.transactionSchema, this); | ||
if (schemaErrors.length > 0) { | ||
throw new lisk_validator_1.LiskValidationError(schemaErrors); | ||
sign(chainID, privateKey) { | ||
const signature = lisk_cryptography_1.ed.signDataWithPrivateKey(constants_1.TAG_TRANSACTION, chainID, this.getSigningBytes(), privateKey); | ||
this.signatures.push(signature); | ||
} | ||
validate() { | ||
lisk_validator_1.validator.validate(exports.transactionSchema, this); | ||
if (!constants_1.NAME_REGEX.test(this.module)) { | ||
throw new Error(`Invalid module name ${this.module}`); | ||
} | ||
if (!constants_1.NAME_REGEX.test(this.command)) { | ||
throw new Error(`Invalid command name ${this.command}`); | ||
} | ||
if (this.params.length > constants_1.TRANSACTION_MAX_PARAMS_SIZE) { | ||
throw new Error(`Params exceeds max size allowed ${constants_1.TRANSACTION_MAX_PARAMS_SIZE}.`); | ||
} | ||
if (this.signatures.length === 0) { | ||
@@ -110,9 +120,23 @@ throw new Error('Signatures must not be empty'); | ||
} | ||
const minFee = exports.calculateMinFee(this, input.minFeePerByte, input.baseFees); | ||
if (this.fee < minFee) { | ||
throw new Error(`Insufficient transaction fee. Minimum required fee is: ${minFee.toString()}`); | ||
} | ||
} | ||
toJSON() { | ||
return { ...lisk_codec_1.codec.toJSON(exports.transactionSchema, this._getProps()), id: this.id.toString('hex') }; | ||
} | ||
toObject() { | ||
return this._getProps(); | ||
} | ||
_getProps() { | ||
return { | ||
module: this.module, | ||
command: this.command, | ||
params: this.params, | ||
nonce: this.nonce, | ||
fee: this.fee, | ||
senderPublicKey: this.senderPublicKey, | ||
signatures: this.signatures, | ||
id: this._id, | ||
}; | ||
} | ||
} | ||
exports.Transaction = Transaction; | ||
//# sourceMappingURL=transaction.js.map |
/// <reference types="node" /> | ||
import { Transaction } from './transaction'; | ||
export interface Context { | ||
readonly blockVersion: number; | ||
readonly blockHeight: number; | ||
readonly blockTimestamp: number; | ||
} | ||
export declare type Contexter = (() => Context) | Context; | ||
export interface BlockRewardOptions { | ||
@@ -14,44 +7,7 @@ readonly distance: number; | ||
} | ||
export interface BaseBlockHeader { | ||
readonly id: Buffer; | ||
readonly version: number; | ||
readonly timestamp: number; | ||
readonly height: number; | ||
readonly previousBlockID: Buffer; | ||
readonly transactionRoot: Buffer; | ||
readonly generatorPublicKey: Buffer; | ||
readonly reward: bigint; | ||
readonly signature: Buffer; | ||
} | ||
export declare type RawBlockHeader = BaseBlockHeader & { | ||
asset: Buffer; | ||
}; | ||
export interface RawBlock { | ||
header: Buffer; | ||
payload: ReadonlyArray<Buffer>; | ||
transactions: ReadonlyArray<Buffer>; | ||
assets: ReadonlyArray<Buffer>; | ||
} | ||
export interface GenesisBlockHeaderAsset<T = AccountDefaultProps> { | ||
readonly accounts: ReadonlyArray<Account<T>>; | ||
readonly initDelegates: ReadonlyArray<Buffer>; | ||
readonly initRounds: number; | ||
} | ||
export interface BlockHeaderAsset { | ||
readonly seedReveal: Buffer; | ||
readonly maxHeightPreviouslyForged: number; | ||
readonly maxHeightPrevoted: number; | ||
} | ||
export declare type BlockHeader<T = BlockHeaderAsset> = BaseBlockHeader & { | ||
asset: T; | ||
}; | ||
export declare type GenesisBlockHeader<T = AccountDefaultProps> = BaseBlockHeader & { | ||
asset: GenesisBlockHeaderAsset<T>; | ||
}; | ||
export interface Block<T = BlockHeaderAsset> { | ||
header: BlockHeader<T>; | ||
payload: ReadonlyArray<Transaction>; | ||
} | ||
export interface GenesisBlock<T = AccountDefaultProps> { | ||
header: GenesisBlockHeader<T>; | ||
payload: ReadonlyArray<Transaction>; | ||
} | ||
export interface DiffHistory { | ||
@@ -63,31 +19,14 @@ code: string; | ||
readonly updated: Array<Readonly<UpdatedDiff>>; | ||
readonly created: Array<Readonly<string>>; | ||
readonly created: Array<Buffer>; | ||
readonly deleted: Array<Readonly<UpdatedDiff>>; | ||
} | ||
export interface UpdatedDiff { | ||
readonly key: string; | ||
readonly key: Buffer; | ||
readonly value: Buffer; | ||
} | ||
export interface AccountSchema { | ||
type: string; | ||
fieldNumber: number; | ||
properties: Record<string, unknown>; | ||
default: Record<string, unknown>; | ||
} | ||
export declare type AccountDefaultProps = { | ||
[name: string]: { | ||
[key: string]: unknown; | ||
} | undefined | Buffer; | ||
type Primitive = string | number | bigint | boolean | null | undefined; | ||
type Replaced<T, TReplace, TWith, TKeep = Primitive> = T extends TReplace | TKeep ? T extends TReplace ? TWith | Exclude<T, TReplace> : T : { | ||
[P in keyof T]: Replaced<T[P], TReplace, TWith, TKeep>; | ||
}; | ||
export declare type Account<T = AccountDefaultProps> = T & { | ||
address: Buffer; | ||
}; | ||
export interface Validator { | ||
address: Buffer; | ||
minActiveHeight: number; | ||
isConsensusParticipant: boolean; | ||
} | ||
export interface GenesisInfo { | ||
height: number; | ||
initRounds: number; | ||
} | ||
export type JSONObject<T> = Replaced<T, bigint | Buffer, string>; | ||
export {}; |
@@ -1,4 +0,1 @@ | ||
export * from './buffer_string'; | ||
export * from './genesis_block'; | ||
export * from './validators'; | ||
export * from './account'; | ||
export * from './buffer_keys'; |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
@@ -13,6 +17,3 @@ if (k2 === undefined) k2 = k; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
__exportStar(require("./buffer_string"), exports); | ||
__exportStar(require("./genesis_block"), exports); | ||
__exportStar(require("./validators"), exports); | ||
__exportStar(require("./account"), exports); | ||
__exportStar(require("./buffer_keys"), exports); | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "@liskhq/lisk-chain", | ||
"version": "0.3.4", | ||
"version": "0.4.0-beta.0", | ||
"description": "Blocks and state management implementation that are used for block processing according to the Lisk protocol", | ||
"author": "Lisk Foundation <admin@lisk.io>, lightcurve GmbH <admin@lightcurve.io>", | ||
"author": "Lisk Foundation <admin@lisk.com>, lightcurve GmbH <admin@lightcurve.io>", | ||
"license": "Apache-2.0", | ||
@@ -27,50 +27,49 @@ "keywords": [ | ||
"format": "prettier --write '**/*'", | ||
"lint": "eslint --ext .js,.ts .", | ||
"lint": "eslint --ext .ts .", | ||
"lint:fix": "eslint --fix --ext .js,.ts .", | ||
"test": "jest", | ||
"test:coverage": "jest --coverage=true --coverage-reporters=text", | ||
"test:ci": "jest --coverage=true --coverage-reporters=json --verbose", | ||
"test:ci": "jest --coverage=true --coverage-reporters=json", | ||
"test:watch": "npm test -- --watch", | ||
"prebuild": "rm -r dist-node/* || mkdir dist-node || true", | ||
"build": "tsc", | ||
"build:check": "node -e \"require('./dist-node')\"", | ||
"prepublishOnly": "npm run lint && npm test && npm run build && npm run build:check" | ||
"build:check": "node -e \"require('./dist-node')\"" | ||
}, | ||
"dependencies": { | ||
"@liskhq/lisk-codec": "^0.2.2", | ||
"@liskhq/lisk-cryptography": "^3.2.1", | ||
"@liskhq/lisk-db": "^0.2.1", | ||
"@liskhq/lisk-tree": "^0.2.2", | ||
"@liskhq/lisk-utils": "^0.2.1", | ||
"@liskhq/lisk-validator": "^0.6.2", | ||
"@liskhq/lisk-codec": "^0.3.0-beta.0", | ||
"@liskhq/lisk-cryptography": "^4.0.0-beta.0", | ||
"@liskhq/lisk-db": "0.3.5", | ||
"@liskhq/lisk-tree": "^0.3.0-beta.0", | ||
"@liskhq/lisk-utils": "^0.3.0-beta.0", | ||
"@liskhq/lisk-validator": "^0.7.0-beta.0", | ||
"debug": "4.3.4" | ||
}, | ||
"devDependencies": { | ||
"@liskhq/lisk-passphrase": "^3.1.1", | ||
"@types/debug": "4.1.7", | ||
"@liskhq/lisk-passphrase": "^4.0.0-beta.0", | ||
"@types/debug": "4.1.5", | ||
"@types/faker": "4.1.10", | ||
"@types/jest": "26.0.21", | ||
"@types/jest-when": "2.7.2", | ||
"@types/node": "16.11.26", | ||
"@types/jest": "29.2.3", | ||
"@types/jest-when": "3.5.2", | ||
"@types/node": "16.18.3", | ||
"@types/randomstring": "1.1.6", | ||
"@typescript-eslint/eslint-plugin": "4.19.0", | ||
"@typescript-eslint/parser": "4.19.0", | ||
"eslint": "7.22.0", | ||
"@typescript-eslint/eslint-plugin": "5.44.0", | ||
"@typescript-eslint/parser": "5.44.0", | ||
"eslint": "8.28.0", | ||
"eslint-config-lisk-base": "2.0.1", | ||
"eslint-plugin-import": "2.22.1", | ||
"eslint-plugin-jest": "24.3.2", | ||
"eslint-plugin-import": "2.26.0", | ||
"eslint-plugin-jest": "27.1.6", | ||
"faker": "4.1.0", | ||
"fs-extra": "9.1.0", | ||
"jest": "26.6.3", | ||
"jest-extended": "0.11.5", | ||
"jest-when": "3.2.1", | ||
"prettier": "2.2.1", | ||
"fs-extra": "11.1.0", | ||
"jest": "29.3.1", | ||
"jest-extended": "3.2.0", | ||
"jest-when": "3.5.2", | ||
"prettier": "2.8.0", | ||
"randomstring": "1.1.5", | ||
"source-map-support": "0.5.19", | ||
"stampit": "4.3.2", | ||
"ts-jest": "26.5.4", | ||
"ts-node": "9.1.1", | ||
"tsconfig-paths": "3.9.0", | ||
"typescript": "4.2.3" | ||
"source-map-support": "0.5.21", | ||
"stampit": "4.3.1", | ||
"ts-jest": "29.0.3", | ||
"ts-node": "10.9.1", | ||
"tsconfig-paths": "4.1.0", | ||
"typescript": "5.0.2" | ||
} | ||
} |
@@ -28,2 +28,2 @@ # @liskhq/lisk-chain | ||
[lisk core github]: https://github.com/LiskHQ/lisk | ||
[lisk documentation site]: https://lisk.io/documentation/lisk-elements | ||
[lisk documentation site]: https://lisk.com/documentation/lisk-sdk/references/lisk-elements/chain.html |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
3290
198083
81
+ Added@liskhq/lisk-codec@0.3.0(transitive)
+ Added@liskhq/lisk-cryptography@4.1.0(transitive)
+ Added@liskhq/lisk-db@0.3.5(transitive)
+ Added@liskhq/lisk-passphrase@4.1.0(transitive)
+ Added@liskhq/lisk-tree@0.3.0(transitive)
+ Added@liskhq/lisk-utils@0.3.0(transitive)
+ Added@liskhq/lisk-validator@0.7.0(transitive)
+ Added@mapbox/node-pre-gyp@1.0.11(transitive)
+ Added@types/node@11.11.616.18.121(transitive)
+ Addedabbrev@1.1.1(transitive)
+ Addedagent-base@6.0.2(transitive)
+ Addedansi-regex@5.0.1(transitive)
+ Addedaproba@2.0.0(transitive)
+ Addedare-we-there-yet@2.0.0(transitive)
+ Addedbalanced-match@1.0.2(transitive)
+ Addedbip39@3.0.3(transitive)
+ Addedbrace-expansion@1.1.11(transitive)
+ Addedcargo-cp-artifact@0.1.9(transitive)
+ Addedchownr@2.0.0(transitive)
+ Addedcipher-base@1.0.6(transitive)
+ Addedcolor-support@1.1.3(transitive)
+ Addedconcat-map@0.0.1(transitive)
+ Addedconsole-control-strings@1.1.0(transitive)
+ Addedcreate-hash@1.2.0(transitive)
+ Addedcreate-hmac@1.1.7(transitive)
+ Addeddelegates@1.0.0(transitive)
+ Addeddetect-libc@2.0.3(transitive)
+ Addedemoji-regex@8.0.0(transitive)
+ Addedfs-minipass@2.1.0(transitive)
+ Addedfs.realpath@1.0.0(transitive)
+ Addedfunction-bind@1.1.2(transitive)
+ Addedgauge@3.0.2(transitive)
+ Addedglob@7.2.3(transitive)
+ Addedhas-unicode@2.0.1(transitive)
+ Addedhash-base@3.1.0(transitive)
+ Addedhash-wasm@4.9.0(transitive)
+ Addedhasown@2.0.2(transitive)
+ Addedhttps-proxy-agent@5.0.1(transitive)
+ Addedinflight@1.0.6(transitive)
+ Addedinterpret@1.4.0(transitive)
+ Addedis-core-module@2.15.1(transitive)
+ Addedis-fullwidth-code-point@3.0.0(transitive)
+ Addedmake-dir@3.1.0(transitive)
+ Addedmd5.js@1.3.5(transitive)
+ Addedminimatch@3.1.2(transitive)
+ Addedminipass@3.3.65.0.0(transitive)
+ Addedminizlib@2.1.2(transitive)
+ Addedmkdirp@1.0.4(transitive)
+ Addednode-fetch@2.7.0(transitive)
+ Addednopt@5.0.0(transitive)
+ Addednpmlog@5.0.1(transitive)
+ Addedobject-assign@4.1.1(transitive)
+ Addedonce@1.4.0(transitive)
+ Addedpath-is-absolute@1.0.1(transitive)
+ Addedpath-parse@1.0.7(transitive)
+ Addedpbkdf2@3.1.2(transitive)
+ Addedrandombytes@2.1.0(transitive)
+ Addedrechoir@0.6.2(transitive)
+ Addedresolve@1.22.8(transitive)
+ Addedrimraf@3.0.2(transitive)
+ Addedripemd160@2.0.2(transitive)
+ Addedsemver@6.3.1(transitive)
+ Addedset-blocking@2.0.0(transitive)
+ Addedsha.js@2.4.11(transitive)
+ Addedshelljs@0.8.5(transitive)
+ Addedsignal-exit@3.0.7(transitive)
+ Addedstring-width@4.2.3(transitive)
+ Addedstrip-ansi@6.0.1(transitive)
+ Addedsupports-preserve-symlinks-flag@1.0.0(transitive)
+ Addedtar@6.2.1(transitive)
+ Addedtr46@0.0.3(transitive)
+ Addedwebidl-conversions@3.0.1(transitive)
+ Addedwhatwg-url@5.0.0(transitive)
+ Addedwide-align@1.1.5(transitive)
+ Addedwrappy@1.0.2(transitive)
- Removed@liskhq/lisk-codec@0.2.2(transitive)
- Removed@liskhq/lisk-db@0.2.1(transitive)
- Removed@liskhq/lisk-tree@0.2.2(transitive)
- Removed@liskhq/lisk-utils@0.2.1(transitive)
- Removed@liskhq/lisk-validator@0.6.2(transitive)
- Removedabstract-leveldown@6.2.37.2.0(transitive)
- Removedbase64-js@1.5.1(transitive)
- Removedbuffer@5.7.16.0.3(transitive)
- Removedcatering@2.1.1(transitive)
- Removeddeferred-leveldown@5.3.0(transitive)
- Removederrno@0.1.8(transitive)
- Removedieee754@1.2.1(transitive)
- Removedimmediate@3.3.0(transitive)
- Removedis-buffer@2.0.5(transitive)
- Removedlevel-concat-iterator@2.0.13.1.0(transitive)
- Removedlevel-errors@2.0.1(transitive)
- Removedlevel-iterator-stream@4.0.2(transitive)
- Removedlevel-supports@1.0.12.1.0(transitive)
- Removedlevelup@4.4.0(transitive)
- Removednapi-macros@2.2.2(transitive)
- Removedprr@1.0.1(transitive)
- Removedqueue-microtask@1.2.3(transitive)
- Removedrocksdb@5.1.1(transitive)
- Removedxtend@4.0.2(transitive)
Updated@liskhq/lisk-db@0.3.5