From 95b6b8bea636139ecf418c611fec490707626c1a Mon Sep 17 00:00:00 2001 From: Holger Drewes Date: Wed, 25 May 2022 16:44:02 +0200 Subject: [PATCH 1/8] Util, Block: added Util error module, first exemplary BlockHeader error implementation --- packages/block/src/errors.ts | 12 ++++++++++++ packages/block/src/header/header.ts | 12 +++++++++--- packages/util/src/errors.ts | 30 +++++++++++++++++++++++++++++ packages/util/src/index.ts | 5 +++++ 4 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 packages/block/src/errors.ts create mode 100644 packages/util/src/errors.ts diff --git a/packages/block/src/errors.ts b/packages/block/src/errors.ts new file mode 100644 index 0000000000..379808a280 --- /dev/null +++ b/packages/block/src/errors.ts @@ -0,0 +1,12 @@ +import { EthereumJSError } from '@ethereumjs/util' + +export enum HeaderValidationErrorCode { + WRONG_TX_TRIE_LENGTH = 'WRONG_TX_TRIE_LENGTH', +} + +export type HeaderValidationErrorType = { + block: string + received: string +} + +export class HeaderValidationError extends EthereumJSError {} diff --git a/packages/block/src/header/header.ts b/packages/block/src/header/header.ts index 9f24919f56..b23366f6a4 100644 --- a/packages/block/src/header/header.ts +++ b/packages/block/src/header/header.ts @@ -26,6 +26,7 @@ import { CLIQUE_EXTRA_VANITY, cliqueIsEpochTransition, } from '../consensus/clique.js' +import { HeaderValidationError, HeaderValidationErrorCode } from '../errors.js' import { fakeExponential } from '../helpers.js' import { paramsBlock } from '../params.js' @@ -267,10 +268,15 @@ export class BlockHeader { throw new Error(msg) } if (transactionsTrie.length !== 32) { - const msg = this._errorMsg( - `transactionsTrie must be 32 bytes, received ${transactionsTrie.length} bytes`, + const e = new HeaderValidationError( + 'transactionsTrie must be 32 bytes', + HeaderValidationErrorCode.WRONG_TX_TRIE_LENGTH, + { + block: this.errorStr(), + received: `${bytesToHex(transactionsTrie)} (${transactionsTrie.length} bytes)`, + }, ) - throw new Error(msg) + throw e } if (receiptTrie.length !== 32) { const msg = this._errorMsg( diff --git a/packages/util/src/errors.ts b/packages/util/src/errors.ts new file mode 100644 index 0000000000..0430621648 --- /dev/null +++ b/packages/util/src/errors.ts @@ -0,0 +1,30 @@ +/** + * Generic EthereumJS error with metadata attached + * + * Kudos to https://github.com/ChainSafe/lodestar monorepo + * for the inspiration :-) + */ +export class EthereumJSError extends Error { + code: string + errorContext: T + + constructor(msg: string, code: string, errorContext: T) { + super(msg) + this.code = code + this.errorContext = errorContext + } + + getErrorContext(): Record { + return { code: this.code, ...this.errorContext } + } + + /** + * Get the metadata and the stacktrace for the error. + */ + toObject(): Record { + return { + ...this.getErrorContext(), + stack: this.stack ?? '', + } + } +} diff --git a/packages/util/src/index.ts b/packages/util/src/index.ts index d1f6dd95e7..2776c03d03 100644 --- a/packages/util/src/index.ts +++ b/packages/util/src/index.ts @@ -28,6 +28,11 @@ export * from './db.js' */ export * from './withdrawal.js' +/** + * EthereumJS Extended Errors + */ +export * from './errors.js' + /** * ECDSA signature */ From 88e6a31c27dc4c07f20fd46ce0993f4e4cdccb7e Mon Sep 17 00:00:00 2001 From: Holger Drewes Date: Thu, 26 May 2022 09:55:15 +0200 Subject: [PATCH 2/8] Util, Block: added generic error types like ValidationError, UsageError --- packages/block/src/errors.ts | 23 ++++++++++++++++++++--- packages/block/src/header/header.ts | 4 ++-- packages/util/src/errors.ts | 20 +++++++++++++++++++- 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/packages/block/src/errors.ts b/packages/block/src/errors.ts index 379808a280..df98cda3f6 100644 --- a/packages/block/src/errors.ts +++ b/packages/block/src/errors.ts @@ -1,12 +1,29 @@ -import { EthereumJSError } from '@ethereumjs/util' +import { UsageError, ValidationError } from '@ethereumjs/util' -export enum HeaderValidationErrorCode { +/** + * Always define error codes on the generic Util + * error class level (e.g. associated to `ValidationError`) + */ +export enum ValidationErrorCode { WRONG_TX_TRIE_LENGTH = 'WRONG_TX_TRIE_LENGTH', } +/** + * Additional types extending the generic Util + * error types (e.g. `ValidationErrorType`) + */ export type HeaderValidationErrorType = { block: string received: string } +export type HeaderUsageErrorType = { + block: string +} -export class HeaderValidationError extends EthereumJSError {} +/** + * Dedicated error classes for the specific package, + * always to be subclassed from the generic Util error type + * classes (e.g. `ValidationError`, not: `EthereumJSError`) + */ +export class HeaderValidationError extends ValidationError {} +export class HeaderUsageError extends UsageError {} diff --git a/packages/block/src/header/header.ts b/packages/block/src/header/header.ts index b23366f6a4..1ec9669f55 100644 --- a/packages/block/src/header/header.ts +++ b/packages/block/src/header/header.ts @@ -26,7 +26,7 @@ import { CLIQUE_EXTRA_VANITY, cliqueIsEpochTransition, } from '../consensus/clique.js' -import { HeaderValidationError, HeaderValidationErrorCode } from '../errors.js' +import { HeaderValidationError, ValidationErrorCode } from '../errors.js' import { fakeExponential } from '../helpers.js' import { paramsBlock } from '../params.js' @@ -270,7 +270,7 @@ export class BlockHeader { if (transactionsTrie.length !== 32) { const e = new HeaderValidationError( 'transactionsTrie must be 32 bytes', - HeaderValidationErrorCode.WRONG_TX_TRIE_LENGTH, + ValidationErrorCode.WRONG_TX_TRIE_LENGTH, { block: this.errorStr(), received: `${bytesToHex(transactionsTrie)} (${transactionsTrie.length} bytes)`, diff --git a/packages/util/src/errors.ts b/packages/util/src/errors.ts index 0430621648..a781f2cbf1 100644 --- a/packages/util/src/errors.ts +++ b/packages/util/src/errors.ts @@ -1,5 +1,5 @@ /** - * Generic EthereumJS error with metadata attached + * Generic EthereumJS error class with metadata attached * * Kudos to https://github.com/ChainSafe/lodestar monorepo * for the inspiration :-) @@ -28,3 +28,21 @@ export class EthereumJSError extends Error { } } } + +export type ValidationErrorType = { + received: string +} + +/** + * Error along Object Validation + * + * Use directly or in a subclassed context for error comparison (`e instanceof ValidationError`) + */ +export class ValidationError extends EthereumJSError {} + +/** + * Error along API Usage + * + * Use directly or in a subclassed context for error comparison (`e instanceof UsageError`) + */ +export class UsageError extends EthereumJSError {} From 0c9ba5ecb44fb55c69399b53ea893cba9541768a Mon Sep 17 00:00:00 2001 From: Holger Drewes Date: Fri, 27 May 2022 09:18:48 +0200 Subject: [PATCH 3/8] Block: allow sub class error to take on the type shapes of the generic error by unionizing the types --- packages/block/src/errors.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/block/src/errors.ts b/packages/block/src/errors.ts index df98cda3f6..c12814bd59 100644 --- a/packages/block/src/errors.ts +++ b/packages/block/src/errors.ts @@ -1,5 +1,7 @@ import { UsageError, ValidationError } from '@ethereumjs/util' +import type { ValidationErrorType } from '@ethereumjs/util' + /** * Always define error codes on the generic Util * error class level (e.g. associated to `ValidationError`) @@ -12,10 +14,12 @@ export enum ValidationErrorCode { * Additional types extending the generic Util * error types (e.g. `ValidationErrorType`) */ -export type HeaderValidationErrorType = { - block: string - received: string -} +export type HeaderValidationErrorType = + | { + block: string + received: string + } + | ValidationErrorType export type HeaderUsageErrorType = { block: string } From 2f904ab61f230c11e6dcad02a87f0c74d6cb3c5f Mon Sep 17 00:00:00 2001 From: Holger Drewes Date: Fri, 27 May 2022 11:49:46 +0200 Subject: [PATCH 4/8] Util, Block: Removed 2-layer error structure, removed local package errors file, moved error codes to Util --- packages/block/src/errors.ts | 33 --------- packages/block/src/header/constructors.ts | 4 +- packages/block/src/header/header.ts | 82 ++++++++++++++--------- packages/util/src/errors.ts | 70 +++++++++++++++---- 4 files changed, 110 insertions(+), 79 deletions(-) delete mode 100644 packages/block/src/errors.ts diff --git a/packages/block/src/errors.ts b/packages/block/src/errors.ts deleted file mode 100644 index c12814bd59..0000000000 --- a/packages/block/src/errors.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { UsageError, ValidationError } from '@ethereumjs/util' - -import type { ValidationErrorType } from '@ethereumjs/util' - -/** - * Always define error codes on the generic Util - * error class level (e.g. associated to `ValidationError`) - */ -export enum ValidationErrorCode { - WRONG_TX_TRIE_LENGTH = 'WRONG_TX_TRIE_LENGTH', -} - -/** - * Additional types extending the generic Util - * error types (e.g. `ValidationErrorType`) - */ -export type HeaderValidationErrorType = - | { - block: string - received: string - } - | ValidationErrorType -export type HeaderUsageErrorType = { - block: string -} - -/** - * Dedicated error classes for the specific package, - * always to be subclassed from the generic Util error type - * classes (e.g. `ValidationError`, not: `EthereumJSError`) - */ -export class HeaderValidationError extends ValidationError {} -export class HeaderUsageError extends UsageError {} diff --git a/packages/block/src/header/constructors.ts b/packages/block/src/header/constructors.ts index 97222b970d..72ca874628 100644 --- a/packages/block/src/header/constructors.ts +++ b/packages/block/src/header/constructors.ts @@ -1,5 +1,5 @@ import { RLP } from '@ethereumjs/rlp' -import { bigIntToBytes, equalsBytes } from '@ethereumjs/util' +import { ErrorCode, ValueError, bigIntToBytes, equalsBytes } from '@ethereumjs/util' import { generateCliqueBlockExtraData } from '../consensus/clique.js' import { numberToHex, valuesArrayToHeaderData } from '../helpers.js' @@ -66,7 +66,7 @@ export function createBlockHeaderFromRLP( ) { const values = RLP.decode(serializedHeaderData) if (!Array.isArray(values)) { - throw new Error('Invalid serialized header input. Must be array') + throw new ValueError('Invalid serialized header input. Must be array', ErrorCode.INVALID_VALUE) } return createBlockHeaderFromBytesArray(values as Uint8Array[], opts) } diff --git a/packages/block/src/header/header.ts b/packages/block/src/header/header.ts index 1ec9669f55..a7f9f1a874 100644 --- a/packages/block/src/header/header.ts +++ b/packages/block/src/header/header.ts @@ -6,9 +6,12 @@ import { BIGINT_1, BIGINT_2, BIGINT_7, + ErrorCode, KECCAK256_RLP, KECCAK256_RLP_ARRAY, TypeOutput, + UsageError, + ValueError, bigIntToHex, bigIntToUnpaddedBytes, bytesToHex, @@ -26,7 +29,6 @@ import { CLIQUE_EXTRA_VANITY, cliqueIsEpochTransition, } from '../consensus/clique.js' -import { HeaderValidationError, ValidationErrorCode } from '../errors.js' import { fakeExponential } from '../helpers.js' import { paramsBlock } from '../params.js' @@ -77,10 +79,13 @@ export class BlockHeader { */ get prevRandao() { if (!this.common.isActivatedEIP(4399)) { - const msg = this._errorMsg( + throw new UsageError( 'The prevRandao parameter can only be accessed when EIP-4399 is activated', + ErrorCode.EIP_NOT_ACTIVATED, + { + objectContext: this.errorStr(), + }, ) - throw new Error(msg) } return this.mixHash } @@ -181,7 +186,10 @@ export class BlockHeader { toType(headerData.requestsRoot, TypeOutput.Uint8Array) ?? hardforkDefaults.requestsRoot if (!this.common.isActivatedEIP(1559) && baseFeePerGas !== undefined) { - throw new Error('A base fee for a block can only be set with EIP1559 being activated') + throw new UsageError( + 'A base fee for a block can only be set with EIP1559 being activated', + ErrorCode.EIP_NOT_ACTIVATED, + ) } if (!this.common.isActivatedEIP(4895) && withdrawalsRoot !== undefined) { @@ -260,38 +268,41 @@ export class BlockHeader { const { parentHash, stateRoot, transactionsTrie, receiptTrie, mixHash, nonce } = this if (parentHash.length !== 32) { - const msg = this._errorMsg(`parentHash must be 32 bytes, received ${parentHash.length} bytes`) - throw new Error(msg) + throw new ValueError(`parentHash must be 32 bytes`, ErrorCode.INVALID_VALUE_LENGTH, { + objectContext: this.errorStr(), + received: `${parentHash.length} bytes`, + }) } if (stateRoot.length !== 32) { - const msg = this._errorMsg(`stateRoot must be 32 bytes, received ${stateRoot.length} bytes`) - throw new Error(msg) + throw new ValueError(`stateRoot must be 32 bytes`, ErrorCode.INVALID_VALUE_LENGTH, { + objectContext: this.errorStr(), + received: `${stateRoot.length} bytes`, + }) } if (transactionsTrie.length !== 32) { - const e = new HeaderValidationError( - 'transactionsTrie must be 32 bytes', - ValidationErrorCode.WRONG_TX_TRIE_LENGTH, - { - block: this.errorStr(), - received: `${bytesToHex(transactionsTrie)} (${transactionsTrie.length} bytes)`, - }, - ) - throw e + throw new ValueError('transactionsTrie must be 32 bytes', ErrorCode.INVALID_VALUE_LENGTH, { + objectContext: this.errorStr(), + received: `${bytesToHex(transactionsTrie)} (${transactionsTrie.length} bytes)`, + }) } if (receiptTrie.length !== 32) { - const msg = this._errorMsg( - `receiptTrie must be 32 bytes, received ${receiptTrie.length} bytes`, - ) - throw new Error(msg) + throw new ValueError('receiptTrie must be 32 bytes', ErrorCode.INVALID_VALUE_LENGTH, { + objectContext: this.errorStr(), + received: `${bytesToHex(receiptTrie)} (${receiptTrie.length} bytes)`, + }) } if (mixHash.length !== 32) { - const msg = this._errorMsg(`mixHash must be 32 bytes, received ${mixHash.length} bytes`) - throw new Error(msg) + throw new ValueError('mixHash must be 32 bytes', ErrorCode.INVALID_VALUE_LENGTH, { + objectContext: this.errorStr(), + received: `${bytesToHex(mixHash)} (${mixHash.length} bytes)`, + }) } if (nonce.length !== 8) { - const msg = this._errorMsg(`nonce must be 8 bytes, received ${nonce.length} bytes`) - throw new Error(msg) + throw new ValueError('nonce must be 8 bytes', ErrorCode.INVALID_VALUE_LENGTH, { + objectContext: this.errorStr(), + received: `${bytesToHex(nonce)} (${nonce.length} bytes)`, + }) } // check if the block used too much gas @@ -436,8 +447,9 @@ export class BlockHeader { } } if (error) { - const msg = this._errorMsg(`Invalid PoS block: ${errorMsg}`) - throw new Error(msg) + throw new ValueError(`Invalid PoS block${errorMsg}`, ErrorCode.INVALID_OBJECT, { + objectContext: this.errorStr(), + }) } } } @@ -666,14 +678,22 @@ export class BlockHeader { */ ethashCanonicalDifficulty(parentBlockHeader: BlockHeader): bigint { if (this.common.consensusType() !== ConsensusType.ProofOfWork) { - const msg = this._errorMsg('difficulty calculation is only supported on PoW chains') - throw new Error(msg) + throw new UsageError( + 'difficulty calculation is only supported on PoW chains', + ErrorCode.INVALID_METHOD_CALL, + { + objectContext: this.errorStr(), + }, + ) } if (this.common.consensusAlgorithm() !== ConsensusAlgorithm.Ethash) { - const msg = this._errorMsg( + throw new UsageError( 'difficulty calculation currently only supports the ethash algorithm', + ErrorCode.INVALID_METHOD_CALL, + { + objectContext: this.errorStr(), + }, ) - throw new Error(msg) } const blockTs = this.timestamp const { timestamp: parentTs, difficulty: parentDif } = parentBlockHeader diff --git a/packages/util/src/errors.ts b/packages/util/src/errors.ts index a781f2cbf1..1eba2d31dc 100644 --- a/packages/util/src/errors.ts +++ b/packages/util/src/errors.ts @@ -4,18 +4,22 @@ * Kudos to https://github.com/ChainSafe/lodestar monorepo * for the inspiration :-) */ -export class EthereumJSError extends Error { +type EthereumJSErrorType = { + objectContext: string +} + +export class EthereumJSError extends Error { code: string - errorContext: T + context: T | {} - constructor(msg: string, code: string, errorContext: T) { + constructor(msg: string, code: string, context?: T) { super(msg) this.code = code - this.errorContext = errorContext + this.context = context ?? {} } - getErrorContext(): Record { - return { code: this.code, ...this.errorContext } + getContext(): Record { + return { code: this.code, ...this.context } } /** @@ -23,26 +27,66 @@ export class EthereumJSError extends Error { */ toObject(): Record { return { - ...this.getErrorContext(), + ...this.getContext(), stack: this.stack ?? '', } } } -export type ValidationErrorType = { - received: string +/** + * Error Codes + */ +export enum ErrorCode { + // Value Errors + INVALID_OBJECT = 'INVALID_OBJECT', + INVALID_VALUE = 'INVALID_VALUE', + INVALID_VALUE_LENGTH = 'INVALID_VALUE_LENGTH', + TOO_FEW_VALUES = 'TOO_FEW_VALUES', + TOO_MANY_VALUES = 'TOO_MANY_VALUES', + + // Usage Errors + EIP_NOT_ACTIVATED = 'EIP_NOT_ACTIVATED', + INCOMPATIBLE_LIBRARY_VERSION = 'INCOMPATIBLE_LIBRARY_VERSION', + INVALID_OPTION_USAGE = 'INVALID_OPTION_USAGE', + INVALID_METHOD_CALL = 'INVALID_METHOD_CALL', } /** - * Error along Object Validation + * Generic error types + */ + +/** + * Type flavors for ValueError + */ +export type ValueErrorType = + | { + received: string + } + | { + objectContext: string + received: string + } + | EthereumJSErrorType + +/** + * Type flavors for UsageError + */ +export type UsageErrorType = EthereumJSErrorType + +/** + * Generic Errors * - * Use directly or in a subclassed context for error comparison (`e instanceof ValidationError`) + * Use directly or in a subclassed context for error comparison (`e instanceof ValueError`) + */ + +/** + * Error along Object Value */ -export class ValidationError extends EthereumJSError {} +export class ValueError extends EthereumJSError {} /** * Error along API Usage * * Use directly or in a subclassed context for error comparison (`e instanceof UsageError`) */ -export class UsageError extends EthereumJSError {} +export class UsageError extends EthereumJSError {} From f456b81cf10149a2ae7316c6ea068e24f2ffa9d2 Mon Sep 17 00:00:00 2001 From: Amir Date: Mon, 30 Sep 2024 21:24:22 -0700 Subject: [PATCH 5/8] Refactor constructor errors to use more descriptive error type --- packages/block/src/header/constructors.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/block/src/header/constructors.ts b/packages/block/src/header/constructors.ts index 72ca874628..bda0b01e5f 100644 --- a/packages/block/src/header/constructors.ts +++ b/packages/block/src/header/constructors.ts @@ -34,22 +34,22 @@ export function createBlockHeaderFromBytesArray(values: BlockHeaderBytes, opts: eip1559ActivationBlock !== undefined && equalsBytes(eip1559ActivationBlock, number as Uint8Array) ) { - throw new Error('invalid header. baseFeePerGas should be provided') + throw new ValueError('invalid header. baseFeePerGas should be provided', ValueError.INVALID_VALUE) } } if (header.common.isActivatedEIP(4844)) { if (excessBlobGas === undefined) { - throw new Error('invalid header. excessBlobGas should be provided') + throw new ValueError('invalid header. excessBlobGas should be provided', ValueError.INVALID_VALUE) } else if (blobGasUsed === undefined) { - throw new Error('invalid header. blobGasUsed should be provided') + throw new ValueError('invalid header. blobGasUsed should be provided', ValueError.INVALID_VALUE) } } if (header.common.isActivatedEIP(4788) && parentBeaconBlockRoot === undefined) { - throw new Error('invalid header. parentBeaconBlockRoot should be provided') + throw new ValueError('invalid header. parentBeaconBlockRoot should be provided', ValueError.INVALID_VALUE) } if (header.common.isActivatedEIP(7685) && requestsRoot === undefined) { - throw new Error('invalid header. requestsRoot should be provided') + throw new ValueError('invalid header. requestsRoot should be provided', ValueError.INVALID_VALUE) } return header } From 856b582b38ccf4a66d6e2faa5cdb787b6ddad23c Mon Sep 17 00:00:00 2001 From: Amir Date: Mon, 30 Sep 2024 21:24:55 -0700 Subject: [PATCH 6/8] Refactor clique verification errors to use more descriptive error type --- packages/block/src/consensus/clique.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/block/src/consensus/clique.ts b/packages/block/src/consensus/clique.ts index 3a89a46319..fbc7b59c1e 100644 --- a/packages/block/src/consensus/clique.ts +++ b/packages/block/src/consensus/clique.ts @@ -12,6 +12,7 @@ import { ecrecover, ecsign, equalsBytes, + ErrorCode, UsageErrorType } from '@ethereumjs/util' import type { BlockHeader } from '../index.js' @@ -28,7 +29,7 @@ export function requireClique(header: BlockHeader, name: string) { const msg = header['_errorMsg']( `BlockHeader.${name}() call only supported for clique PoA networks`, ) - throw new Error(msg) + throw new UsageErrorType(msg, ErrorCode.INVALID_METHOD_CALL) } } @@ -84,7 +85,7 @@ export function cliqueEpochTransitionSigners(header: BlockHeader): Address[] { requireClique(header, 'cliqueEpochTransitionSigners') if (!cliqueIsEpochTransition(header)) { const msg = header['_errorMsg']('Signers are only included in epoch transition blocks (clique)') - throw new Error(msg) + throw new UsageErrorType(msg, ErrorCode.INVALID_METHOD_CALL) } const start = CLIQUE_EXTRA_VANITY From bb478ea469e27d6c4b7c35f473d9288c9abb7a70 Mon Sep 17 00:00:00 2001 From: Amir Date: Mon, 30 Sep 2024 21:25:40 -0700 Subject: [PATCH 7/8] Refactor block errors to use more descriptive error type --- packages/block/src/block/block.ts | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/packages/block/src/block/block.ts b/packages/block/src/block/block.ts index b6613a2791..2f909d1177 100644 --- a/packages/block/src/block/block.ts +++ b/packages/block/src/block/block.ts @@ -35,13 +35,16 @@ import { import type { BlockBytes, BlockOptions, ExecutionPayload, JSONBlock } from '../types.js' import type { Common } from '@ethereumjs/common' import type { FeeMarket1559Tx, LegacyTx, TypedTransaction } from '@ethereumjs/tx' -import type { +import { CLRequest, ConsolidationRequest, DepositRequest, VerkleExecutionWitness, Withdrawal, WithdrawalRequest, + UsageErrorType, + ErrorCode, + ValueError } from '@ethereumjs/util' /** @@ -133,18 +136,18 @@ export class Block { const msg = this._errorMsg( 'Block initialization with uncleHeaders on a PoA network is not allowed', ) - throw new Error(msg) + throw new UsageErrorType(msg, ErrorCode.INVALID_OPTION_USAGE) } if (this.common.consensusType() === ConsensusType.ProofOfStake) { const msg = this._errorMsg( 'Block initialization with uncleHeaders on a PoS network is not allowed', ) - throw new Error(msg) + throw new UsageErrorType(msg, ErrorCode.INVALID_OPTION_USAGE) } } if (!this.common.isActivatedEIP(4895) && withdrawals !== undefined) { - throw new Error('Cannot have a withdrawals field if EIP 4895 is not active') + throw new UsageErrorType('Cannot have a withdrawals field if EIP 4895 is not active', ErrorCode.EIP_NOT_ACTIVATED) } if ( @@ -152,11 +155,11 @@ export class Block { executionWitness !== undefined && executionWitness !== null ) { - throw new Error(`Cannot have executionWitness field if EIP 6800 is not active `) + throw new UsageErrorType(`Cannot have executionWitness field if EIP 6800 is not active `, ErrorCode.EIP_NOT_ACTIVATED) } if (!this.common.isActivatedEIP(7685) && requests !== undefined) { - throw new Error(`Cannot have requests field if EIP 7685 is not active`) + throw new UsageErrorType(`Cannot have requests field if EIP 7685 is not active`, ErrorCode.EIP_NOT_ACTIVATED) } // Requests should be sorted in monotonically ascending order based on type @@ -164,7 +167,7 @@ export class Block { if (requests !== undefined && requests.length > 1) { for (let x = 1; x < requests.length; x++) { if (requests[x].type < requests[x - 1].type) - throw new Error('requests are not sorted in ascending order') + throw new ValueError('requests are not sorted in ascending order', ErrorCode.INVALID_VALUE) } } const freeze = opts?.freeze ?? true @@ -250,7 +253,7 @@ export class Block { async requestsTrieIsValid(requestsInput?: CLRequest[]): Promise { if (!this.common.isActivatedEIP(7685)) { - throw new Error('EIP 7685 is not activated') + throw new UsageErrorType('EIP 7685 is not activated', ErrorCode.EIP_NOT_ACTIVATED) } const requests = requestsInput ?? this.requests! @@ -459,7 +462,7 @@ export class Block { */ async withdrawalsTrieIsValid(): Promise { if (!this.common.isActivatedEIP(4895)) { - throw new Error('EIP 4895 is not activated') + throw new UsageErrorType('EIP 4895 is not activated', ErrorCode.EIP_NOT_ACTIVATED) } let result From 17598ce0f5704193e4f7acded7e1c439fc580bb8 Mon Sep 17 00:00:00 2001 From: Amir Date: Mon, 30 Sep 2024 21:31:54 -0700 Subject: [PATCH 8/8] Fix ErrorCode usage --- packages/block/src/block/block.ts | 36 +++++++++++++++-------- packages/block/src/consensus/clique.ts | 7 +++-- packages/block/src/header/constructors.ts | 22 ++++++++++---- 3 files changed, 45 insertions(+), 20 deletions(-) diff --git a/packages/block/src/block/block.ts b/packages/block/src/block/block.ts index 2f909d1177..29f75296c4 100644 --- a/packages/block/src/block/block.ts +++ b/packages/block/src/block/block.ts @@ -5,8 +5,11 @@ import { Blob4844Tx, Capability } from '@ethereumjs/tx' import { BIGINT_0, CLRequestType, + ErrorCode, KECCAK256_RLP, KECCAK256_RLP_ARRAY, + UsageError, + ValueError, bytesToHex, equalsBytes, } from '@ethereumjs/util' @@ -35,16 +38,13 @@ import { import type { BlockBytes, BlockOptions, ExecutionPayload, JSONBlock } from '../types.js' import type { Common } from '@ethereumjs/common' import type { FeeMarket1559Tx, LegacyTx, TypedTransaction } from '@ethereumjs/tx' -import { +import type { CLRequest, ConsolidationRequest, DepositRequest, VerkleExecutionWitness, Withdrawal, WithdrawalRequest, - UsageErrorType, - ErrorCode, - ValueError } from '@ethereumjs/util' /** @@ -136,18 +136,21 @@ export class Block { const msg = this._errorMsg( 'Block initialization with uncleHeaders on a PoA network is not allowed', ) - throw new UsageErrorType(msg, ErrorCode.INVALID_OPTION_USAGE) + throw new UsageError(msg, ErrorCode.INVALID_OPTION_USAGE) } if (this.common.consensusType() === ConsensusType.ProofOfStake) { const msg = this._errorMsg( 'Block initialization with uncleHeaders on a PoS network is not allowed', ) - throw new UsageErrorType(msg, ErrorCode.INVALID_OPTION_USAGE) + throw new UsageError(msg, ErrorCode.INVALID_OPTION_USAGE) } } if (!this.common.isActivatedEIP(4895) && withdrawals !== undefined) { - throw new UsageErrorType('Cannot have a withdrawals field if EIP 4895 is not active', ErrorCode.EIP_NOT_ACTIVATED) + throw new UsageError( + 'Cannot have a withdrawals field if EIP 4895 is not active', + ErrorCode.EIP_NOT_ACTIVATED, + ) } if ( @@ -155,11 +158,17 @@ export class Block { executionWitness !== undefined && executionWitness !== null ) { - throw new UsageErrorType(`Cannot have executionWitness field if EIP 6800 is not active `, ErrorCode.EIP_NOT_ACTIVATED) + throw new UsageError( + `Cannot have executionWitness field if EIP 6800 is not active `, + ErrorCode.EIP_NOT_ACTIVATED, + ) } if (!this.common.isActivatedEIP(7685) && requests !== undefined) { - throw new UsageErrorType(`Cannot have requests field if EIP 7685 is not active`, ErrorCode.EIP_NOT_ACTIVATED) + throw new UsageError( + `Cannot have requests field if EIP 7685 is not active`, + ErrorCode.EIP_NOT_ACTIVATED, + ) } // Requests should be sorted in monotonically ascending order based on type @@ -167,7 +176,10 @@ export class Block { if (requests !== undefined && requests.length > 1) { for (let x = 1; x < requests.length; x++) { if (requests[x].type < requests[x - 1].type) - throw new ValueError('requests are not sorted in ascending order', ErrorCode.INVALID_VALUE) + throw new ValueError( + 'requests are not sorted in ascending order', + ErrorCode.INVALID_VALUE, + ) } } const freeze = opts?.freeze ?? true @@ -253,7 +265,7 @@ export class Block { async requestsTrieIsValid(requestsInput?: CLRequest[]): Promise { if (!this.common.isActivatedEIP(7685)) { - throw new UsageErrorType('EIP 7685 is not activated', ErrorCode.EIP_NOT_ACTIVATED) + throw new UsageError('EIP 7685 is not activated', ErrorCode.EIP_NOT_ACTIVATED) } const requests = requestsInput ?? this.requests! @@ -462,7 +474,7 @@ export class Block { */ async withdrawalsTrieIsValid(): Promise { if (!this.common.isActivatedEIP(4895)) { - throw new UsageErrorType('EIP 4895 is not activated', ErrorCode.EIP_NOT_ACTIVATED) + throw new UsageError('EIP 4895 is not activated', ErrorCode.EIP_NOT_ACTIVATED) } let result diff --git a/packages/block/src/consensus/clique.ts b/packages/block/src/consensus/clique.ts index fbc7b59c1e..7b670ae1cb 100644 --- a/packages/block/src/consensus/clique.ts +++ b/packages/block/src/consensus/clique.ts @@ -4,6 +4,8 @@ import { Address, BIGINT_0, BIGINT_27, + ErrorCode, + UsageError, bigIntToBytes, bytesToBigInt, concatBytes, @@ -12,7 +14,6 @@ import { ecrecover, ecsign, equalsBytes, - ErrorCode, UsageErrorType } from '@ethereumjs/util' import type { BlockHeader } from '../index.js' @@ -29,7 +30,7 @@ export function requireClique(header: BlockHeader, name: string) { const msg = header['_errorMsg']( `BlockHeader.${name}() call only supported for clique PoA networks`, ) - throw new UsageErrorType(msg, ErrorCode.INVALID_METHOD_CALL) + throw new UsageError(msg, ErrorCode.INVALID_METHOD_CALL) } } @@ -85,7 +86,7 @@ export function cliqueEpochTransitionSigners(header: BlockHeader): Address[] { requireClique(header, 'cliqueEpochTransitionSigners') if (!cliqueIsEpochTransition(header)) { const msg = header['_errorMsg']('Signers are only included in epoch transition blocks (clique)') - throw new UsageErrorType(msg, ErrorCode.INVALID_METHOD_CALL) + throw new UsageError(msg, ErrorCode.INVALID_METHOD_CALL) } const start = CLIQUE_EXTRA_VANITY diff --git a/packages/block/src/header/constructors.ts b/packages/block/src/header/constructors.ts index bda0b01e5f..826e5d1a87 100644 --- a/packages/block/src/header/constructors.ts +++ b/packages/block/src/header/constructors.ts @@ -34,22 +34,34 @@ export function createBlockHeaderFromBytesArray(values: BlockHeaderBytes, opts: eip1559ActivationBlock !== undefined && equalsBytes(eip1559ActivationBlock, number as Uint8Array) ) { - throw new ValueError('invalid header. baseFeePerGas should be provided', ValueError.INVALID_VALUE) + throw new ValueError( + 'invalid header. baseFeePerGas should be provided', + ErrorCode.INVALID_VALUE, + ) } } if (header.common.isActivatedEIP(4844)) { if (excessBlobGas === undefined) { - throw new ValueError('invalid header. excessBlobGas should be provided', ValueError.INVALID_VALUE) + throw new ValueError( + 'invalid header. excessBlobGas should be provided', + ErrorCode.INVALID_VALUE, + ) } else if (blobGasUsed === undefined) { - throw new ValueError('invalid header. blobGasUsed should be provided', ValueError.INVALID_VALUE) + throw new ValueError( + 'invalid header. blobGasUsed should be provided', + ErrorCode.INVALID_VALUE, + ) } } if (header.common.isActivatedEIP(4788) && parentBeaconBlockRoot === undefined) { - throw new ValueError('invalid header. parentBeaconBlockRoot should be provided', ValueError.INVALID_VALUE) + throw new ValueError( + 'invalid header. parentBeaconBlockRoot should be provided', + ErrorCode.INVALID_VALUE, + ) } if (header.common.isActivatedEIP(7685) && requestsRoot === undefined) { - throw new ValueError('invalid header. requestsRoot should be provided', ValueError.INVALID_VALUE) + throw new ValueError('invalid header. requestsRoot should be provided', ErrorCode.INVALID_VALUE) } return header }