Skip to content

Commit 2f904ab

Browse files
holgerd77jochem-brouwer
authored andcommitted
Util, Block: Removed 2-layer error structure, removed local package errors file, moved error codes to Util
1 parent 0c9ba5e commit 2f904ab

File tree

4 files changed

+110
-79
lines changed

4 files changed

+110
-79
lines changed

packages/block/src/errors.ts

Lines changed: 0 additions & 33 deletions
This file was deleted.

packages/block/src/header/constructors.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { RLP } from '@ethereumjs/rlp'
2-
import { bigIntToBytes, equalsBytes } from '@ethereumjs/util'
2+
import { ErrorCode, ValueError, bigIntToBytes, equalsBytes } from '@ethereumjs/util'
33

44
import { generateCliqueBlockExtraData } from '../consensus/clique.js'
55
import { numberToHex, valuesArrayToHeaderData } from '../helpers.js'
@@ -66,7 +66,7 @@ export function createBlockHeaderFromRLP(
6666
) {
6767
const values = RLP.decode(serializedHeaderData)
6868
if (!Array.isArray(values)) {
69-
throw new Error('Invalid serialized header input. Must be array')
69+
throw new ValueError('Invalid serialized header input. Must be array', ErrorCode.INVALID_VALUE)
7070
}
7171
return createBlockHeaderFromBytesArray(values as Uint8Array[], opts)
7272
}

packages/block/src/header/header.ts

Lines changed: 51 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,12 @@ import {
66
BIGINT_1,
77
BIGINT_2,
88
BIGINT_7,
9+
ErrorCode,
910
KECCAK256_RLP,
1011
KECCAK256_RLP_ARRAY,
1112
TypeOutput,
13+
UsageError,
14+
ValueError,
1215
bigIntToHex,
1316
bigIntToUnpaddedBytes,
1417
bytesToHex,
@@ -26,7 +29,6 @@ import {
2629
CLIQUE_EXTRA_VANITY,
2730
cliqueIsEpochTransition,
2831
} from '../consensus/clique.js'
29-
import { HeaderValidationError, ValidationErrorCode } from '../errors.js'
3032
import { fakeExponential } from '../helpers.js'
3133
import { paramsBlock } from '../params.js'
3234

@@ -77,10 +79,13 @@ export class BlockHeader {
7779
*/
7880
get prevRandao() {
7981
if (!this.common.isActivatedEIP(4399)) {
80-
const msg = this._errorMsg(
82+
throw new UsageError(
8183
'The prevRandao parameter can only be accessed when EIP-4399 is activated',
84+
ErrorCode.EIP_NOT_ACTIVATED,
85+
{
86+
objectContext: this.errorStr(),
87+
},
8288
)
83-
throw new Error(msg)
8489
}
8590
return this.mixHash
8691
}
@@ -181,7 +186,10 @@ export class BlockHeader {
181186
toType(headerData.requestsRoot, TypeOutput.Uint8Array) ?? hardforkDefaults.requestsRoot
182187

183188
if (!this.common.isActivatedEIP(1559) && baseFeePerGas !== undefined) {
184-
throw new Error('A base fee for a block can only be set with EIP1559 being activated')
189+
throw new UsageError(
190+
'A base fee for a block can only be set with EIP1559 being activated',
191+
ErrorCode.EIP_NOT_ACTIVATED,
192+
)
185193
}
186194

187195
if (!this.common.isActivatedEIP(4895) && withdrawalsRoot !== undefined) {
@@ -260,38 +268,41 @@ export class BlockHeader {
260268
const { parentHash, stateRoot, transactionsTrie, receiptTrie, mixHash, nonce } = this
261269

262270
if (parentHash.length !== 32) {
263-
const msg = this._errorMsg(`parentHash must be 32 bytes, received ${parentHash.length} bytes`)
264-
throw new Error(msg)
271+
throw new ValueError(`parentHash must be 32 bytes`, ErrorCode.INVALID_VALUE_LENGTH, {
272+
objectContext: this.errorStr(),
273+
received: `${parentHash.length} bytes`,
274+
})
265275
}
266276
if (stateRoot.length !== 32) {
267-
const msg = this._errorMsg(`stateRoot must be 32 bytes, received ${stateRoot.length} bytes`)
268-
throw new Error(msg)
277+
throw new ValueError(`stateRoot must be 32 bytes`, ErrorCode.INVALID_VALUE_LENGTH, {
278+
objectContext: this.errorStr(),
279+
received: `${stateRoot.length} bytes`,
280+
})
269281
}
270282
if (transactionsTrie.length !== 32) {
271-
const e = new HeaderValidationError(
272-
'transactionsTrie must be 32 bytes',
273-
ValidationErrorCode.WRONG_TX_TRIE_LENGTH,
274-
{
275-
block: this.errorStr(),
276-
received: `${bytesToHex(transactionsTrie)} (${transactionsTrie.length} bytes)`,
277-
},
278-
)
279-
throw e
283+
throw new ValueError('transactionsTrie must be 32 bytes', ErrorCode.INVALID_VALUE_LENGTH, {
284+
objectContext: this.errorStr(),
285+
received: `${bytesToHex(transactionsTrie)} (${transactionsTrie.length} bytes)`,
286+
})
280287
}
281288
if (receiptTrie.length !== 32) {
282-
const msg = this._errorMsg(
283-
`receiptTrie must be 32 bytes, received ${receiptTrie.length} bytes`,
284-
)
285-
throw new Error(msg)
289+
throw new ValueError('receiptTrie must be 32 bytes', ErrorCode.INVALID_VALUE_LENGTH, {
290+
objectContext: this.errorStr(),
291+
received: `${bytesToHex(receiptTrie)} (${receiptTrie.length} bytes)`,
292+
})
286293
}
287294
if (mixHash.length !== 32) {
288-
const msg = this._errorMsg(`mixHash must be 32 bytes, received ${mixHash.length} bytes`)
289-
throw new Error(msg)
295+
throw new ValueError('mixHash must be 32 bytes', ErrorCode.INVALID_VALUE_LENGTH, {
296+
objectContext: this.errorStr(),
297+
received: `${bytesToHex(mixHash)} (${mixHash.length} bytes)`,
298+
})
290299
}
291300

292301
if (nonce.length !== 8) {
293-
const msg = this._errorMsg(`nonce must be 8 bytes, received ${nonce.length} bytes`)
294-
throw new Error(msg)
302+
throw new ValueError('nonce must be 8 bytes', ErrorCode.INVALID_VALUE_LENGTH, {
303+
objectContext: this.errorStr(),
304+
received: `${bytesToHex(nonce)} (${nonce.length} bytes)`,
305+
})
295306
}
296307

297308
// check if the block used too much gas
@@ -436,8 +447,9 @@ export class BlockHeader {
436447
}
437448
}
438449
if (error) {
439-
const msg = this._errorMsg(`Invalid PoS block: ${errorMsg}`)
440-
throw new Error(msg)
450+
throw new ValueError(`Invalid PoS block${errorMsg}`, ErrorCode.INVALID_OBJECT, {
451+
objectContext: this.errorStr(),
452+
})
441453
}
442454
}
443455
}
@@ -666,14 +678,22 @@ export class BlockHeader {
666678
*/
667679
ethashCanonicalDifficulty(parentBlockHeader: BlockHeader): bigint {
668680
if (this.common.consensusType() !== ConsensusType.ProofOfWork) {
669-
const msg = this._errorMsg('difficulty calculation is only supported on PoW chains')
670-
throw new Error(msg)
681+
throw new UsageError(
682+
'difficulty calculation is only supported on PoW chains',
683+
ErrorCode.INVALID_METHOD_CALL,
684+
{
685+
objectContext: this.errorStr(),
686+
},
687+
)
671688
}
672689
if (this.common.consensusAlgorithm() !== ConsensusAlgorithm.Ethash) {
673-
const msg = this._errorMsg(
690+
throw new UsageError(
674691
'difficulty calculation currently only supports the ethash algorithm',
692+
ErrorCode.INVALID_METHOD_CALL,
693+
{
694+
objectContext: this.errorStr(),
695+
},
675696
)
676-
throw new Error(msg)
677697
}
678698
const blockTs = this.timestamp
679699
const { timestamp: parentTs, difficulty: parentDif } = parentBlockHeader

packages/util/src/errors.ts

Lines changed: 57 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,45 +4,89 @@
44
* Kudos to https://github.com/ChainSafe/lodestar monorepo
55
* for the inspiration :-)
66
*/
7-
export class EthereumJSError<T extends {}> extends Error {
7+
type EthereumJSErrorType = {
8+
objectContext: string
9+
}
10+
11+
export class EthereumJSError<T> extends Error {
812
code: string
9-
errorContext: T
13+
context: T | {}
1014

11-
constructor(msg: string, code: string, errorContext: T) {
15+
constructor(msg: string, code: string, context?: T) {
1216
super(msg)
1317
this.code = code
14-
this.errorContext = errorContext
18+
this.context = context ?? {}
1519
}
1620

17-
getErrorContext(): Record<string, string | number | null> {
18-
return { code: this.code, ...this.errorContext }
21+
getContext(): Record<string, string | number | null> {
22+
return { code: this.code, ...this.context }
1923
}
2024

2125
/**
2226
* Get the metadata and the stacktrace for the error.
2327
*/
2428
toObject(): Record<string, string | number | null> {
2529
return {
26-
...this.getErrorContext(),
30+
...this.getContext(),
2731
stack: this.stack ?? '',
2832
}
2933
}
3034
}
3135

32-
export type ValidationErrorType = {
33-
received: string
36+
/**
37+
* Error Codes
38+
*/
39+
export enum ErrorCode {
40+
// Value Errors
41+
INVALID_OBJECT = 'INVALID_OBJECT',
42+
INVALID_VALUE = 'INVALID_VALUE',
43+
INVALID_VALUE_LENGTH = 'INVALID_VALUE_LENGTH',
44+
TOO_FEW_VALUES = 'TOO_FEW_VALUES',
45+
TOO_MANY_VALUES = 'TOO_MANY_VALUES',
46+
47+
// Usage Errors
48+
EIP_NOT_ACTIVATED = 'EIP_NOT_ACTIVATED',
49+
INCOMPATIBLE_LIBRARY_VERSION = 'INCOMPATIBLE_LIBRARY_VERSION',
50+
INVALID_OPTION_USAGE = 'INVALID_OPTION_USAGE',
51+
INVALID_METHOD_CALL = 'INVALID_METHOD_CALL',
3452
}
3553

3654
/**
37-
* Error along Object Validation
55+
* Generic error types
56+
*/
57+
58+
/**
59+
* Type flavors for ValueError
60+
*/
61+
export type ValueErrorType =
62+
| {
63+
received: string
64+
}
65+
| {
66+
objectContext: string
67+
received: string
68+
}
69+
| EthereumJSErrorType
70+
71+
/**
72+
* Type flavors for UsageError
73+
*/
74+
export type UsageErrorType = EthereumJSErrorType
75+
76+
/**
77+
* Generic Errors
3878
*
39-
* Use directly or in a subclassed context for error comparison (`e instanceof ValidationError`)
79+
* Use directly or in a subclassed context for error comparison (`e instanceof ValueError`)
80+
*/
81+
82+
/**
83+
* Error along Object Value
4084
*/
41-
export class ValidationError<T extends ValidationErrorType> extends EthereumJSError<T> {}
85+
export class ValueError extends EthereumJSError<ValueErrorType> {}
4286

4387
/**
4488
* Error along API Usage
4589
*
4690
* Use directly or in a subclassed context for error comparison (`e instanceof UsageError`)
4791
*/
48-
export class UsageError<T extends {}> extends EthereumJSError<T> {}
92+
export class UsageError extends EthereumJSError<UsageErrorType> {}

0 commit comments

Comments
 (0)