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

Commit

Permalink
Legacy endpoints issue (#9058)
Browse files Browse the repository at this point in the history
* ♻️ Fix legacy DB keys and encode/decode

* ♻️  Improve syncing process
- Add snapshotBlockID in requestSchema
- Use bracketInfo to respond with legacyBlocks
- Add legacyChainBracketInfoExist storage api
- Fix tests and add test for getLegacyBrackets endpoint

* 🐛 Fix schema prop name blockId->blockID

* ♻️ Fix legacy request schema

* ♻️ Fix legacy sync issue

* ♻️ Improve FailAndAttemptSyncError handling

* ♻️ Update legacy sync handler flow
- Fix storage bug related to getTransactionsByBlockID
- Handle timeouts
- Handler errors

* ♻️ Update improve sync timeouts

* 💅Improve naming and format

* ✅ Fix and improve tests
  • Loading branch information
ishantiw authored Oct 6, 2023
1 parent da598fb commit c589442
Show file tree
Hide file tree
Showing 16 changed files with 613 additions and 241 deletions.
2 changes: 2 additions & 0 deletions framework/src/engine/engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ export class Engine {
await this._network.stop();
await this._generator.stop();
await this._consensus.stop();
this._legacyChainHandler.stop();
this._rpcServer.stop();
this._closeDB();
this._logger.info('Engine cleanup completed');
Expand Down Expand Up @@ -228,6 +229,7 @@ export class Engine {

const legacyEndpoint = new LegacyEndpoint({
db: this._legacyDB,
legacyConfig: this._config.legacy,
});

const chainEndpoint = new ChainEndpoint({
Expand Down
38 changes: 30 additions & 8 deletions framework/src/engine/legacy/codec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
LegacyBlockHeaderWithID,
LegacyTransaction,
LegacyTransactionJSON,
LegacyBlockHeader,
} from './types';

interface LegacyBlockSchema {
Expand All @@ -43,17 +44,22 @@ export const blockSchemaMap: Record<number, LegacyBlockSchema> = {
},
};

export const getBlockSchema = (version: number) => {
const blockSchema = blockSchemaMap[version];
if (!blockSchema) {
throw new Error(`Legacy block version ${version} is not registered.`);
}
return blockSchema;
};

// Implement read version logic when adding more versions
const readVersion = (): number => 2;

export const decodeBlock = (
data: Buffer,
): { block: LegacyBlockWithID; schema: LegacyBlockSchema } => {
const version = readVersion();
const blockSchema = blockSchemaMap[version];
if (!blockSchema) {
throw new Error(`Legacy block version ${version} is not registered.`);
}
const blockSchema = getBlockSchema(version);
const rawBlock = codec.decode<RawLegacyBlock>(blockSchema.block, data);
const id = utils.hash(rawBlock.header);
return {
Expand All @@ -68,6 +74,17 @@ export const decodeBlock = (
};
};

export const decodeBlockHeader = (blockHeader: Buffer): LegacyBlockHeaderWithID => {
const version = readVersion();
const blockSchema = getBlockSchema(version);
const id = utils.hash(blockHeader);

return {
...codec.decode<LegacyBlockHeaderWithID>(blockSchema.header, blockHeader),
id,
};
};

export const decodeBlockJSON = (
data: Buffer,
): { block: LegacyBlockJSON; schema: LegacyBlockSchema } => {
Expand Down Expand Up @@ -100,10 +117,7 @@ export const getLegacyTransactionJSONWithSchema = (
};

export const encodeBlock = (data: LegacyBlock): Buffer => {
const blockSchema = blockSchemaMap[data.header.version];
if (!blockSchema) {
throw new Error(`Legacy block version ${data.header.version} is not registered.`);
}
const blockSchema = getBlockSchema(data.header.version);
const headerBytes = codec.encode(blockSchema.header, data.header);

return codec.encode(blockSchema.block, {
Expand All @@ -112,5 +126,13 @@ export const encodeBlock = (data: LegacyBlock): Buffer => {
});
};

export const encodeBlockHeader = (blockHeader: LegacyBlockHeader): Buffer => {
const blockSchema = getBlockSchema(blockHeader.version);
return codec.encode(blockSchema.header, blockHeader);
};

export const encodeLegacyChainBracketInfo = (data: LegacyChainBracketInfo): Buffer =>
codec.encode(legacyChainBracketInfoSchema, data);

export const decodeLegacyChainBracketInfo = (data: Buffer): LegacyChainBracketInfo =>
codec.decode<LegacyChainBracketInfo>(legacyChainBracketInfoSchema, data);
16 changes: 12 additions & 4 deletions framework/src/engine/legacy/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,16 @@
* Removal or modification of this copyright notice is prohibited.
*/

export const DB_KEY_BLOCKS_ID = Buffer.from('blocks:id');
export const DB_KEY_BLOCKS_HEIGHT = Buffer.from('blocks:height');
export const DB_KEY_TRANSACTIONS_BLOCK_ID = Buffer.from('transactions:blockID');
export const DB_KEY_TRANSACTIONS_ID = Buffer.from('transactions:id');
export const DB_KEY_BLOCKS_ID = 'blocks:id';
export const DB_KEY_BLOCKS_HEIGHT = 'blocks:height';
export const DB_KEY_TRANSACTIONS_BLOCK_ID = 'transactions:blockID';
export const DB_KEY_TRANSACTIONS_ID = 'transactions:id';
export const DB_KEY_LEGACY_BRACKET = Buffer.from([2]);

// When no peer was found then resyncing after 12 seconds, 1000 * 12 ms
export const FAILED_SYNC_RETRY_TIMEOUT = 12000;
// To avoid syncing with the same peer frequently and get banned due to RPC limit, resync after 5 seconds, 5 * 1000 ms
export const SUCCESS_SYNC_RETRY_TIMEOUT = 5000;
export const MAX_FAILED_ATTEMPTS = 10;
export const ENGINE_LEGACY_MODULE_NAME = 'legacy';
export const LOG_OBJECT_ENGINE_LEGACY_MODULE = { engineModule: ENGINE_LEGACY_MODULE_NAME };
27 changes: 26 additions & 1 deletion framework/src/engine/legacy/endpoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,29 @@
import { Database } from '@liskhq/lisk-db';
import { isHexString } from '@liskhq/lisk-validator';
import { RequestContext } from '../rpc/rpc_server';
import { LegacyBlockJSON, LegacyTransactionJSON } from './types';
import {
LegacyBlockJSON,
LegacyChainBracketInfoWithSnapshotBlockID,
LegacyTransactionJSON,
} from './types';
import { Storage } from './storage';
import { decodeBlockJSON, getLegacyTransactionJSONWithSchema } from './codec';
import { LegacyConfig } from '../../types';

interface EndpointArgs {
db: Database;
legacyConfig: LegacyConfig;
}

export class LegacyEndpoint {
[key: string]: unknown;

public readonly storage: Storage;
private readonly _legacyConfig: LegacyConfig;

public constructor(args: EndpointArgs) {
this.storage = new Storage(args.db);
this._legacyConfig = args.legacyConfig;
}

public async getTransactionByID(context: RequestContext): Promise<LegacyTransactionJSON> {
Expand Down Expand Up @@ -77,4 +85,21 @@ export class LegacyEndpoint {

return decodeBlockJSON(await this.storage.getBlockByHeight(height)).block;
}

public async getLegacyBrackets(
_context: RequestContext,
): Promise<LegacyChainBracketInfoWithSnapshotBlockID[]> {
return Promise.all(
this._legacyConfig.brackets.map(async bracket => {
const bracketInfo = await this.storage.getBracketInfo(
Buffer.from(bracket.snapshotBlockID, 'hex'),
);

return {
...bracketInfo,
snapshotBlockID: bracket.snapshotBlockID,
};
}),
);
}
}
6 changes: 4 additions & 2 deletions framework/src/engine/legacy/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@
* Removal or modification of this copyright notice is prohibited.
*/

export class PeerNotFoundWithLegacyInfo extends Error {
import { FAILED_SYNC_RETRY_TIMEOUT } from './constants';

export class FailSyncError extends Error {
public constructor(message: string) {
super(message);
super(`${message}: Attempting to sync again after ${FAILED_SYNC_RETRY_TIMEOUT} ms`);
this.name = this.constructor.name;
}
}
Loading

0 comments on commit c589442

Please sign in to comment.