Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix invalid rpc response err handling #60

Merged
merged 2 commits into from
Oct 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 65 additions & 33 deletions internal/block_getters/block_getter.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { Block, BlockTransactionObject, Eth, TransactionReceipt } from "web3-eth";
import {
Block,
BlockTransactionObject,
Eth,
TransactionReceipt,
} from "web3-eth";
import { ITransactionReceipt } from "../interfaces/transaction_receipt.js";
import { BlockProducerError } from "../errors/block_producer_error.js";
import { IWeb3Transaction } from "../interfaces/web3_transaction.js";
Expand All @@ -10,14 +15,14 @@ import { Logger } from "../logger/logger.js";

/**
* A wrapper class on web3 block related functions
*
*
* @author - Vibhu Rajeev, Nitin Mittal
*/
export class BlockGetter extends BlockFormatter implements IBlockGetter {
/**
* @param {Eth} eth - Eth module from web3.js
* @param {number} maxRetries - The number of times to retry on errors.
*
*
* @constructor
*/
constructor(protected eth: Eth, protected maxRetries: number = 0) {
Expand All @@ -27,9 +32,9 @@ export class BlockGetter extends BlockFormatter implements IBlockGetter {
/**
* @async
* Public method to query block data of a single block
*
*
* @param {number | string} blockNumber - Block number to query the block details for.
*
*
* @returns {Promise<Block>} - Block object
*/
public async getBlock(blockNumber: number | string): Promise<Block> {
Expand All @@ -39,16 +44,22 @@ export class BlockGetter extends BlockFormatter implements IBlockGetter {
/**
* @async
* Public method to query block data including transaction receipts of a single block.
*
* @param {number | string} blockNumber - The block number for which block data needs to be retrieved.
*
*
* @param {number | string} blockNumber - The block number for which block data needs to be retrieved.
*
* @returns {Promise<IBlock>} - Block object containing all details including transaction receipts.
*
*
* @throws {Error} - Throws error object on failure.
*/
public async getBlockWithTransactionReceipts(blockNumber: number | string, errorCount: number = 0): Promise<IBlock> {
public async getBlockWithTransactionReceipts(
blockNumber: number | string,
errorCount: number = 0
): Promise<IBlock> {
try {
const block: BlockTransactionObject = await this.eth.getBlock(blockNumber, true);
const block: BlockTransactionObject = await this.eth.getBlock(
blockNumber,
true
);

if (!block) {
throw new BlockProducerError(
Expand All @@ -60,7 +71,9 @@ export class BlockGetter extends BlockFormatter implements IBlockGetter {
);
}

Logger.debug(`Fetching transaction receipts for the following block ${block.number}`);
Logger.debug(
`Fetching transaction receipts for the following block ${block.number}`
);

const transactions: ITransaction[] = [];

Expand All @@ -73,31 +86,40 @@ export class BlockGetter extends BlockFormatter implements IBlockGetter {
);
}

return this.formatBlockWithTransactions(
block,
transactions
);
return this.formatBlockWithTransactions(block, transactions);
} catch (error) {
if (!(error instanceof BlockProducerError)) {
throw new BlockProducerError(
"Block producer error",
BlockProducerError.codes.RPC_ERR,
true,
JSON.stringify(error),
"remote"
);
}
if (errorCount > this.maxRetries) {
Logger.info({
location: "block_getter",
function: "getBlockWithTransactionReceipts",
errorCount,
error: JSON.stringify(error)
error: JSON.stringify(error),
});
throw error;
}

return await this.getBlockWithTransactionReceipts(blockNumber, errorCount + 1);
return await this.getBlockWithTransactionReceipts(
blockNumber,
errorCount + 1
);
}
}

/**
* @async
* Public method to query the current block number.
*
*
* @returns {Promise<number>} - the current block.
*
*
* @throws {Error} - Throws error object on failure.
*/
public getLatestBlockNumber(): Promise<number> {
Expand All @@ -106,43 +128,53 @@ export class BlockGetter extends BlockFormatter implements IBlockGetter {

/**
* @async
* This internal method retrieves the transaction receipt of the given transaction hash and retries upto retryLimit on failure.
*
* @param {string} transactionHash - The transaction hash for which transaction receipt is to be retrieved.
* @param {number} errorCount - Parameter for the function to know the number of times query has been retried.
* This parameter must ideally not be set by an external call.
*
* @returns {Promise<ITransactionReceipt>} - The transaction receipt of the given transaction hash. On failure throws error object.
*
* This internal method retrieves the transaction receipt of the given transaction hash and retries upto retryLimit on failure.
*
* @param {string} transactionHash - The transaction hash for which transaction receipt is to be retrieved.
* @param {number} errorCount - Parameter for the function to know the number of times query has been retried.
* This parameter must ideally not be set by an external call.
*
* @returns {Promise<ITransactionReceipt>} - The transaction receipt of the given transaction hash. On failure throws error object.
*
* @throws {Error} - Throws error object on failure.
*/
protected async getTransactionReceipt(transactionHash: string, errorCount: number = 0): Promise<ITransactionReceipt> {
protected async getTransactionReceipt(
transactionHash: string,
errorCount: number = 0
): Promise<ITransactionReceipt> {
try {
const transactionReceipt: TransactionReceipt = await this.eth.getTransactionReceipt(transactionHash);
const transactionReceipt: TransactionReceipt =
await this.eth.getTransactionReceipt(transactionHash);

if (transactionReceipt === null) {
throw new BlockProducerError(
"Block producer error",
BlockProducerError.codes.RECEIPT_NOT_FOUND,
false,
true,
`Transaction receipt not found for ${transactionHash}.`,
"remote"
);
}

return this.formatTransactionReceipt(transactionReceipt);
} catch (error) {
if (!(error instanceof BlockProducerError)) {
throw error;
}
if (errorCount > this.maxRetries) {
Logger.info({
location: "block_getter",
function: "getTransactionReceipt",
errorCount,
error: JSON.stringify(error)
error: JSON.stringify(error),
});
throw error;
}

return await this.getTransactionReceipt(transactionHash, errorCount + 1);
return await this.getTransactionReceipt(
transactionHash,
errorCount + 1
);
}
}
}
10 changes: 9 additions & 1 deletion internal/block_subscription/abstract_block_subscription.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,12 @@ export abstract class AbstractBlockSubscription extends Queue<IBlockGetterWorker
if (
this.isReOrgedMissed(promiseResult.block)
) {
throw new Error("Chain re org not handled.");
throw new BlockProducerError(
"Chain reorg encountered",
BlockProducerError.codes.REORG_ENCOUNTERED,
true,
"Chain re org not handled",
"block_subscription");
}

this.observer.next(
Expand All @@ -211,6 +216,9 @@ export abstract class AbstractBlockSubscription extends Queue<IBlockGetterWorker
hash: promiseResult.block.hash
};
} catch (error) {
if (error instanceof BlockProducerError) {
this.observer.error(error);
}
this.fatalError = true;
this.observer.error(
BlockProducerError.createUnknown(error)
Expand Down
4 changes: 3 additions & 1 deletion internal/errors/error_codes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ export const codes = {
blockProducer: {
UNKNOWN_ERR: 4000,
RECEIPT_NOT_FOUND: 4001,
OBSERVER_NOT_SET: 4002
OBSERVER_NOT_SET: 4002,
REORG_ENCOUNTERED: 4003,
RPC_ERR: 4004
},

// Event consumer error codes
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@maticnetwork/chain-indexer-framework",
"version": "1.3.14",
"version": "1.3.15",
"description": "blockchain data indexer",
"type": "module",
"exports": {
Expand Down
Loading