Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@ethereumjs/block

Package Overview
Dependencies
Maintainers
4
Versions
34
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ethereumjs/block - npm Package Compare versions

Comparing version 4.3.0 to 5.0.0-rc.1

dist/cjs/block.d.ts

40

package.json
{
"name": "@ethereumjs/block",
"version": "4.3.0",
"version": "5.0.0-rc.1",
"description": "Provides Block serialization and help functions",

@@ -19,4 +19,11 @@ "keywords": [

"author": "mjbecze (mb@ethdev.com)",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"type": "commonjs",
"main": "dist/cjs/index.js",
"module": "dist/esm/index.js",
"exports": {
".": {
"import": "./dist/esm/index.js",
"require": "./dist/cjs/index.js"
}
},
"files": [

@@ -29,4 +36,5 @@ "dist",

"clean": "../../config/cli/clean-package.sh",
"coverage": "../../config/cli/coverage.sh",
"docs:build": "typedoc --options typedoc.js",
"coverage": "npx vitest run --coverage.enabled --coverage.reporter=lcov",
"docs:build": "typedoc --options typedoc.cjs",
"examples": "ts-node ../../scripts/examples-runner.ts -- block",
"lint": "../../config/cli/lint.sh",

@@ -36,23 +44,21 @@ "lint:diff": "../../config/cli/lint-diff.sh",

"prepublishOnly": "../../config/cli/prepublish.sh",
"tape": "tape -r ts-node/register",
"test": "npm run test:node && npm run test:browser",
"test:browser": "karma start karma.conf.js",
"test:node": "npm run tape -- test/*.spec.ts",
"test:browser": "npx vitest run --config=vitest.config.browser.ts --browser.name=webkit --browser.provider=playwright --browser.headless",
"test:node": "npx vitest run",
"tsc": "../../config/cli/ts-compile.sh"
},
"dependencies": {
"@ethereumjs/common": "^3.2.0",
"@ethereumjs/rlp": "^4.0.1",
"@ethereumjs/trie": "^5.1.0",
"@ethereumjs/tx": "^4.2.0",
"@ethereumjs/util": "^8.1.0",
"ethereum-cryptography": "^2.0.0"
"@ethereumjs/common": "4.0.0-rc.1",
"@ethereumjs/rlp": "5.0.0-rc.1",
"@ethereumjs/trie": "6.0.0-rc.1",
"@ethereumjs/tx": "5.0.0-rc.1",
"@ethereumjs/util": "9.0.0-rc.1",
"ethereum-cryptography": "^2.1.2"
},
"devDependencies": {
"@types/lru-cache": "^5.1.0",
"testdouble": "^3.17.2"
"c-kzg": "^2.1.0"
},
"engines": {
"node": ">=14"
"node": ">=18"
}
}

@@ -9,2 +9,4 @@ # @ethereumjs/block

Note: this README has been updated containing the changes from our next breaking release round [UNRELEASED] targeted for Summer 2023. See the README files from the [maintenance-v6](https://github.com/ethereumjs/ethereumjs-monorepo/tree/maintenance-v6/) branch for documentation matching our latest releases.
| Implements schema and functions related to Ethereum's block. |

@@ -32,6 +34,6 @@ | ------------------------------------------------------------ |

- `Block.fromBlockData(blockData: BlockData = {}, opts?: BlockOptions)`
- `Block.fromRLPSerializedBlock(serialized: Buffer, opts?: BlockOptions)`
- `Block.fromValuesArray(values: BlockBuffer, opts?: BlockOptions)`
- `Block.fromRLPSerializedBlock(serialized: Uint8Array, opts?: BlockOptions)`
- `Block.fromValuesArray(values: BlockBytes, opts?: BlockOptions)`
- `Block.fromRPC(blockData: JsonRpcBlock, uncles?: any[], opts?: BlockOptions)`
- `Block.fromEthersProvider(provider: ethers.providers.JsonRpcProvider | string, blockTag: string | bigint, opts: BlockOptions)`
- `Block.fromJsonRpcProvider(provider: string | EthersProvider, blockTag: string | bigint, opts: BlockOptions)`

@@ -107,7 +109,7 @@ For `BlockHeader` instantiation analog factory methods exists, see API docs linked below.

EIP-1559 blocks have an extra `baseFeePerGas` field (default: `BigInt(7)`) and can encompass `FeeMarketEIP1559Transaction` txs (type `2`) (supported by `@ethereumjs/tx` `v3.2.0` or higher) as well as `Transaction` legacy txs (internal type `0`) and `AccessListEIP2930Transaction` txs (type `1`).
EIP-1559 blocks have an extra `baseFeePerGas` field (default: `BigInt(7)`) and can encompass `FeeMarketEIP1559Transaction` txs (type `2`) (supported by `@ethereumjs/tx` `v3.2.0` or higher) as well as `LegacyTransaction` legacy txs (internal type `0`) and `AccessListEIP2930Transaction` txs (type `1`).
### EIP-4895 Beacon Chain Withdrawals Blocks (experimental)
### EIP-4895 Beacon Chain Withdrawals Blocks
Starting with the `v4.1.0` release there is (experimental) support for [EIP-4895](https://eips.ethereum.org/EIPS/eip-4895) beacon chain withdrawals. Withdrawals support can be activated by initializing a respective `Common` object and then use the `withdrawals` data option to pass in system-level withdrawal operations together with a matching `withdrawalsRoot` (mandatory when `EIP-4895` is activated) along Block creation, see the following example:
Starting with the `v4.1.0` release there is support for [EIP-4895](https://eips.ethereum.org/EIPS/eip-4895) beacon chain withdrawals. Withdrawals support can be activated by initializing a `Common` object with a hardfork set to `shanghai` (default) or higher and then use the `withdrawals` data option to pass in system-level withdrawal operations together with a matching `withdrawalsRoot` (mandatory when `EIP-4895` is activated) along Block creation, see the following example:

@@ -117,6 +119,6 @@ ```typescript

import { Common, Chain } from '@ethereumjs/common'
import { Address } from '@ethereumjs/util'
import { Address, hexToBytes } from '@ethereumjs/util'
import type { WithdrawalData } from '@ethereumjs/util'
const common = new Common({ chain: Chain.Mainnet, eips: [4895] })
const common = new Common({ chain: Chain.Mainnet })

@@ -126,3 +128,3 @@ const withdrawal = <WithdrawalData>{

validatorIndex: BigInt(0),
address: new Address(Buffer.from('20'.repeat(20), 'hex')),
address: new Address(hexToBytes(`0x${'20'.repeat(20)}`)),
amount: BigInt(1000),

@@ -134,5 +136,4 @@ }

header: {
withdrawalsRoot: Buffer.from(
'69f28913c562b0d38f8dc81e72eb0d99052444d301bf8158dc1f3f94a4526357',
'hex'
withdrawalsRoot: hexToBytes(
'0x69f28913c562b0d38f8dc81e72eb0d99052444d301bf8158dc1f3f94a4526357'
),

@@ -148,8 +149,10 @@ },

Validation of the withdrawals trie can be manually triggered with the newly introduced async `Block.validateWithdrawalsTrie()` method.
Validation of the withdrawals trie can be manually triggered with the newly introduced async `Block.withdrawalsTrieIsValid()` method.
### EIP-4844 Shard Blob Transaction Blocks (experimental)
### EIP-4844 Shard Blob Transaction Blocks
This library supports an experimental version of the blob transaction type introduced with [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) as being specified in the [01d3209](https://github.com/ethereum/EIPs/commit/01d320998d1d53d95f347b5f43feaf606f230703) EIP version from February 8, 2023 and deployed along `eip4844-devnet-4` (January 2023) starting with `v4.2.0`.
This library supports the blob transaction type introduced with [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844) as being specified in the [b9a5a11](https://github.com/ethereum/EIPs/commit/b9a5a117ab7e1dc18f937841d00598b527c306e7) EIP version from July 2023 deployed along [4844-devnet-7](https://github.com/ethpandaops/4844-testnet) (July 2023), see PR [#2349](https://github.com/ethereumjs/ethereumjs-monorepo/pull/2349) and following.
**Note:** 4844 support is not yet completely stable and there will still be (4844-)breaking changes along all types of library releases.
#### Initialization

@@ -214,4 +217,4 @@

- `BlockHeader.cliqueIsEpochTransition(): boolean`
- `BlockHeader.cliqueExtraVanity(): Buffer`
- `BlockHeader.cliqueExtraSeal(): Buffer`
- `BlockHeader.cliqueExtraVanity(): Uint8Array`
- `BlockHeader.cliqueExtraSeal(): Uint8Array`
- `BlockHeader.cliqueEpochTransitionSigners(): Address[]`

@@ -232,3 +235,3 @@ - `BlockHeader.cliqueVerifySignature(signerList: Address[]): boolean`

import { Chain, Common, Hardfork } from '@ethereumjs/common'
const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Merge })
const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.Paris })
const block = Block.fromBlockData(

@@ -242,2 +245,8 @@ {

## Browser
With the breaking release round in Summer 2023 we have added hybrid ESM/CJS builds for all our libraries (see section below) and have eliminated many of the caveats which had previously prevented a frictionless browser usage.
It is now easily possible to run a browser build of one of the EthereumJS libraries within a modern browser using the provided ESM build. For a setup example see [./examples/browser.html](./examples/browser.html).
## API

@@ -249,2 +258,26 @@

### Hybrid CJS/ESM Builds
With the breaking releases from Summer 2023 we have started to ship our libraries with both CommonJS (`cjs` folder) and ESM builds (`esm` folder), see `package.json` for the detailed setup.
If you use an ES6-style `import` in your code files from the ESM build will be used:
```typescript
import { EthereumJSClass } from '@ethereumjs/[PACKAGE_NAME]'
```
If you use Node.js specific `require` the CJS build will be used:
```typescript
const { EthereumJSClass } = require('@ethereumjs/[PACKAGE_NAME]')
```
Using ESM will give you additional advantages over CJS beyond browser usage like static code analysis / Tree Shaking which CJS can not provide.
### Buffer -> Uint8Array
With the breaking releases from Summer 2023 we have removed all Node.js specific `Buffer` usages from our libraries and replace these with [Uint8Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) representations, which are available both in Node.js and the browser (`Buffer` is a subclass of `Uint8Array`).
We have converted existing Buffer conversion methods to Uint8Array conversion methods in the [@ethereumjs/util](https://github.com/ethereumjs/ethereumjs-monorepo/tree/master/packages/util) `bytes` module, see the respective README section for guidance.
### BigInt Support

@@ -251,0 +284,0 @@

import { ConsensusType } from '@ethereumjs/common'
import { RLP } from '@ethereumjs/rlp'
import { Trie } from '@ethereumjs/trie'
import { Capability, TransactionFactory } from '@ethereumjs/tx'
import { BlobEIP4844Transaction, Capability, TransactionFactory } from '@ethereumjs/tx'
import {
KECCAK256_RLP,
Withdrawal,
arrToBufArr,
bigIntToHex,
bufArrToArr,
bufferToHex,
bytesToHex,
equalsBytes,
fetchFromProvider,
getProvider,
hexToBytes,
intToHex,
isHexPrefixed,
} from '@ethereumjs/util'
import { keccak256 } from 'ethereum-cryptography/keccak'
import { keccak256 } from 'ethereum-cryptography/keccak.js'
import { blockFromRpc } from './from-rpc'
import { BlockHeader } from './header'
import { executionPayloadFromBeaconPayload } from './from-beacon-payload.js'
import { blockFromRpc } from './from-rpc.js'
import { BlockHeader } from './header.js'
import type { BlockBuffer, BlockData, BlockOptions, JsonBlock, JsonRpcBlock } from './types'
import type { BeaconPayloadJson } from './from-beacon-payload.js'
import type {
BlockBytes,
BlockData,
BlockOptions,
ExecutionPayload,
HeaderData,
JsonBlock,
JsonRpcBlock,
} from './types.js'
import type { Common } from '@ethereumjs/common'
import type {
FeeMarketEIP1559Transaction,
Transaction,
LegacyTransaction,
TxOptions,
TypedTransaction,
} from '@ethereumjs/tx'
import type { WithdrawalBuffer } from '@ethereumjs/util'
import type { EthersProvider, WithdrawalBytes } from '@ethereumjs/util'

@@ -41,3 +51,3 @@ /**

public readonly txTrie = new Trie()
public readonly _common: Common
public readonly common: Common

@@ -52,3 +62,3 @@ /**

for (const [i, wt] of wts.entries()) {
await trie.put(Buffer.from(RLP.encode(i)), arrToBufArr(RLP.encode(wt.raw())))
await trie.put(RLP.encode(i), RLP.encode(wt.raw()))
}

@@ -66,3 +76,3 @@ return trie.root()

for (const [i, tx] of txs.entries()) {
await trie.put(Buffer.from(RLP.encode(i)), tx.serialize())
await trie.put(RLP.encode(i), tx.serialize())
}

@@ -92,4 +102,4 @@ return trie.root()

...opts,
// Use header common in case of hardforkByBlockNumber being activated
common: header._common,
// Use header common in case of setHardfork being activated
common: header.common,
} as TxOptions)

@@ -102,14 +112,11 @@ transactions.push(tx)

const uncleOpts: BlockOptions = {
hardforkByBlockNumber: true,
...opts,
// Use header common in case of hardforkByBlockNumber being activated
common: header._common,
// Use header common in case of setHardfork being activated
common: header.common,
// Disable this option here (all other options carried over), since this overwrites the provided Difficulty to an incorrect value
calcDifficultyFromHeader: undefined,
// This potentially overwrites hardforkBy options but we will set them cleanly just below
hardforkByTTD: undefined,
}
// Uncles are obsolete post-merge, any hardfork by option implies hardforkByBlockNumber
if (opts?.hardforkByTTD !== undefined) {
uncleOpts.hardforkByBlockNumber = true
// Uncles are obsolete post-merge, any hardfork by option implies setHardfork
if (opts?.setHardfork !== undefined) {
uncleOpts.setHardfork = true
}

@@ -123,3 +130,3 @@ for (const uhData of uhsData ?? []) {

return new Block(header, transactions, uncleHeaders, opts, withdrawals)
return new Block(header, transactions, uncleHeaders, withdrawals, opts)
}

@@ -133,4 +140,4 @@

*/
public static fromRLPSerializedBlock(serialized: Buffer, opts?: BlockOptions) {
const values = arrToBufArr(RLP.decode(Uint8Array.from(serialized))) as BlockBuffer
public static fromRLPSerializedBlock(serialized: Uint8Array, opts?: BlockOptions) {
const values = RLP.decode(Uint8Array.from(serialized)) as BlockBytes

@@ -145,3 +152,3 @@ if (!Array.isArray(values)) {

/**
* Static constructor to create a block from an array of Buffer values
* Static constructor to create a block from an array of Bytes values
*

@@ -151,9 +158,14 @@ * @param values

*/
public static fromValuesArray(values: BlockBuffer, opts?: BlockOptions) {
public static fromValuesArray(values: BlockBytes, opts?: BlockOptions) {
if (values.length > 4) {
throw new Error('invalid block. More values than expected were received')
}
// First try to load header so that we can use its common (in case of setHardfork being activated)
// to correctly make checks on the hardforks
const [headerData, txsData, uhsData, withdrawalBytes] = values
const header = BlockHeader.fromValuesArray(headerData, opts)
if (
opts?.common !== undefined &&
opts?.common?.isActivatedEIP(4895) &&
header.common.isActivatedEIP(4895) &&
(values[3] === undefined || !Array.isArray(values[3]))

@@ -166,6 +178,2 @@ ) {

const [headerData, txsData, uhsData, withdrawalsBuffer] = values
const header = BlockHeader.fromValuesArray(headerData, opts)
// parse transactions

@@ -177,4 +185,4 @@ const transactions = []

...opts,
// Use header common in case of hardforkByBlockNumber being activated
common: header._common,
// Use header common in case of setHardfork being activated
common: header.common,
})

@@ -187,14 +195,11 @@ )

const uncleOpts: BlockOptions = {
hardforkByBlockNumber: true,
...opts,
// Use header common in case of hardforkByBlockNumber being activated
common: header._common,
// Use header common in case of setHardfork being activated
common: header.common,
// Disable this option here (all other options carried over), since this overwrites the provided Difficulty to an incorrect value
calcDifficultyFromHeader: undefined,
// This potentially overwrites hardforkBy options but we will set them cleanly just below
hardforkByTTD: undefined,
}
// Uncles are obsolete post-merge, any hardfork by option implies hardforkByBlockNumber
if (opts?.hardforkByTTD !== undefined) {
uncleOpts.hardforkByBlockNumber = true
// Uncles are obsolete post-merge, any hardfork by option implies setHardfork
if (opts?.setHardfork !== undefined) {
uncleOpts.setHardfork = true
}

@@ -205,3 +210,3 @@ for (const uncleHeaderData of uhsData ?? []) {

const withdrawals = (withdrawalsBuffer as WithdrawalBuffer[])
const withdrawals = (withdrawalBytes as WithdrawalBytes[])
?.map(([index, validatorIndex, address, amount]) => ({

@@ -215,3 +220,3 @@ index,

return new Block(header, transactions, uncleHeaders, opts, withdrawals)
return new Block(header, transactions, uncleHeaders, withdrawals, opts)
}

@@ -231,4 +236,4 @@

/**
* Method to retrieve a block from the provider and format as a {@link Block}
* @param provider an Ethers JsonRPCProvider
* Method to retrieve a block from a JSON-RPC provider and format as a {@link Block}
* @param provider either a url for a remote provider or an Ethers JsonRpcProvider object
* @param blockTag block hash or block number to be run

@@ -238,4 +243,4 @@ * @param opts {@link BlockOptions}

*/
public static fromEthersProvider = async (
provider: any,
public static fromJsonRpcProvider = async (
provider: string | EthersProvider,
blockTag: string | bigint,

@@ -261,3 +266,5 @@ opts: BlockOptions

blockTag === 'earliest' ||
blockTag === 'pending'
blockTag === 'pending' ||
blockTag === 'finalized' ||
blockTag === 'safe'
) {

@@ -293,2 +300,76 @@ blockData = await fetchFromProvider(providerUrl, {

/**
* Method to retrieve a block from an execution payload
* @param execution payload constructed from beacon payload
* @param opts {@link BlockOptions}
* @returns the block constructed block
*/
public static async fromExecutionPayload(
payload: ExecutionPayload,
options?: BlockOptions
): Promise<Block> {
const {
blockNumber: number,
receiptsRoot: receiptTrie,
prevRandao: mixHash,
feeRecipient: coinbase,
transactions,
withdrawals: withdrawalsData,
} = payload
const txs = []
for (const [index, serializedTx] of transactions.entries()) {
try {
const tx = TransactionFactory.fromSerializedData(hexToBytes(serializedTx), {
common: options?.common,
})
txs.push(tx)
} catch (error) {
const validationError = `Invalid tx at index ${index}: ${error}`
throw validationError
}
}
const transactionsTrie = await Block.genTransactionsTrieRoot(txs)
const withdrawals = withdrawalsData?.map((wData) => Withdrawal.fromWithdrawalData(wData))
const withdrawalsRoot = withdrawals
? await Block.genWithdrawalsTrieRoot(withdrawals)
: undefined
const header: HeaderData = {
...payload,
number,
receiptTrie,
transactionsTrie,
withdrawalsRoot,
mixHash,
coinbase,
}
// we are not setting setHardfork as common is already set to the correct hf
const block = Block.fromBlockData({ header, transactions: txs, withdrawals }, options)
// Verify blockHash matches payload
if (!equalsBytes(block.hash(), hexToBytes(payload.blockHash))) {
const validationError = `Invalid blockHash, expected: ${
payload.blockHash
}, received: ${bytesToHex(block.hash())}`
throw Error(validationError)
}
return block
}
/**
* Method to retrieve a block from a beacon payload json
* @param payload json of a beacon beacon fetched from beacon apis
* @param opts {@link BlockOptions}
* @returns the block constructed block
*/
public static async fromBeaconPayloadJson(
payload: BeaconPayloadJson,
options?: BlockOptions
): Promise<Block> {
const executionPayload = executionPayloadFromBeaconPayload(payload)
return Block.fromExecutionPayload(executionPayload, options)
}
/**
* This constructor takes the values, validates them, assigns them and freezes the object.

@@ -301,14 +382,14 @@ * Use the static factory methods to assist in creating a Block object from varying data types and options.

uncleHeaders: BlockHeader[] = [],
opts: BlockOptions = {},
withdrawals?: Withdrawal[]
withdrawals?: Withdrawal[],
opts: BlockOptions = {}
) {
this.header = header ?? BlockHeader.fromHeaderData({}, opts)
this._common = this.header._common
this.common = this.header.common
this.transactions = transactions
this.withdrawals = withdrawals ?? (this._common.isActivatedEIP(4895) ? [] : undefined)
this.withdrawals = withdrawals ?? (this.common.isActivatedEIP(4895) ? [] : undefined)
this.uncleHeaders = uncleHeaders
if (uncleHeaders.length > 0) {
this.validateUncles()
if (this._common.consensusType() === ConsensusType.ProofOfAuthority) {
if (this.common.consensusType() === ConsensusType.ProofOfAuthority) {
const msg = this._errorMsg(

@@ -319,3 +400,3 @@ 'Block initialization with uncleHeaders on a PoA network is not allowed'

}
if (this._common.consensusType() === ConsensusType.ProofOfStake) {
if (this.common.consensusType() === ConsensusType.ProofOfStake) {
const msg = this._errorMsg(

@@ -328,3 +409,3 @@ 'Block initialization with uncleHeaders on a PoS network is not allowed'

if (!this._common.isActivatedEIP(4895) && withdrawals !== undefined) {
if (!this.common.isActivatedEIP(4895) && withdrawals !== undefined) {
throw new Error('Cannot have a withdrawals field if EIP 4895 is not active')

@@ -340,10 +421,10 @@ }

/**
* Returns a Buffer Array of the raw Buffers of this block, in order.
* Returns a Array of the raw Bytes Arays of this block, in order.
*/
raw(): BlockBuffer {
const bufferArray = <BlockBuffer>[
raw(): BlockBytes {
const bytesArray = <BlockBytes>[
this.header.raw(),
this.transactions.map((tx) =>
tx.supports(Capability.EIP2718TypedTransaction) ? tx.serialize() : tx.raw()
) as Buffer[],
) as Uint8Array[],
this.uncleHeaders.map((uh) => uh.raw()),

@@ -353,5 +434,5 @@ ]

if (withdrawalsRaw) {
bufferArray.push(withdrawalsRaw)
bytesArray.push(withdrawalsRaw)
}
return bufferArray
return bytesArray
}

@@ -362,3 +443,3 @@

*/
hash(): Buffer {
hash(): Uint8Array {
return this.header.hash()

@@ -377,4 +458,4 @@ }

*/
serialize(): Buffer {
return Buffer.from(RLP.encode(bufArrToArr(this.raw())))
serialize(): Uint8Array {
return RLP.encode(this.raw())
}

@@ -393,14 +474,15 @@

* and do a check on the root hash.
* @returns True if the transaction trie is valid, false otherwise
*/
async validateTransactionsTrie(): Promise<boolean> {
async transactionsTrieIsValid(): Promise<boolean> {
let result
if (this.transactions.length === 0) {
result = this.header.transactionsTrie.equals(KECCAK256_RLP)
result = equalsBytes(this.header.transactionsTrie, KECCAK256_RLP)
return result
}
if (this.txTrie.root().equals(KECCAK256_RLP)) {
if (equalsBytes(this.txTrie.root(), KECCAK256_RLP)) {
await this.genTxTrie()
}
result = this.txTrie.root().equals(this.header.transactionsTrie)
result = equalsBytes(this.txTrie.root(), this.header.transactionsTrie)
return result

@@ -411,15 +493,14 @@ }

* Validates transaction signatures and minimum gas requirements.
*
* @param stringError - If `true`, a string with the indices of the invalid txs is returned.
* @returns {string[]} an array of error strings
*/
validateTransactions(): boolean
validateTransactions(stringError: false): boolean
validateTransactions(stringError: true): string[]
validateTransactions(stringError = false) {
getTransactionsValidationErrors(): string[] {
const errors: string[] = []
let dataGasUsed = BigInt(0)
const dataGasLimit = this.common.param('gasConfig', 'maxDataGasPerBlock')
const dataGasPerBlob = this.common.param('gasConfig', 'dataGasPerBlob')
// eslint-disable-next-line prefer-const
for (let [i, tx] of this.transactions.entries()) {
const errs = <string[]>tx.validate(true)
if (this._common.isActivatedEIP(1559) === true) {
const errs = tx.getValidationErrors()
if (this.common.isActivatedEIP(1559) === true) {
if (tx.supports(Capability.EIP1559FeeMarket)) {

@@ -431,3 +512,3 @@ tx = tx as FeeMarketEIP1559Transaction

} else {
tx = tx as Transaction
tx = tx as LegacyTransaction
if (tx.gasPrice < this.header.baseFeePerGas!) {

@@ -438,2 +519,12 @@ errs.push('tx unable to pay base fee (non EIP-1559 tx)')

}
if (this.common.isActivatedEIP(4844) === true) {
if (tx instanceof BlobEIP4844Transaction) {
dataGasUsed += BigInt(tx.numBlobs()) * dataGasPerBlob
if (dataGasUsed > dataGasLimit) {
errs.push(
`tx causes total data gas of ${dataGasUsed} to exceed maximum data gas per block of ${dataGasLimit}`
)
}
}
}
if (errs.length > 0) {

@@ -444,6 +535,22 @@ errors.push(`errors at tx ${i}: ${errs.join(', ')}`)

return stringError ? errors : errors.length === 0
if (this.common.isActivatedEIP(4844) === true) {
if (dataGasUsed !== this.header.dataGasUsed) {
errors.push(`invalid dataGasUsed expected=${this.header.dataGasUsed} actual=${dataGasUsed}`)
}
}
return errors
}
/**
* Validates transaction signatures and minimum gas requirements.
* @returns True if all transactions are valid, false otherwise
*/
transactionsAreValid(): boolean {
const errors = this.getTransactionsValidationErrors()
return errors.length === 0
}
/**
* Validates the block data, throwing if invalid.

@@ -458,3 +565,3 @@ * This can be checked on the Block itself without needing access to any parent block

async validateData(onlyHeader: boolean = false): Promise<void> {
const txErrors = this.validateTransactions(true)
const txErrors = this.getTransactionsValidationErrors()
if (txErrors.length > 0) {

@@ -469,4 +576,3 @@ const msg = this._errorMsg(`invalid transactions: ${txErrors.join(' ')}`)

const validateTxTrie = await this.validateTransactionsTrie()
if (!validateTxTrie) {
if (!(await this.transactionsTrieIsValid())) {
const msg = this._errorMsg('invalid transaction trie')

@@ -476,3 +582,3 @@ throw new Error(msg)

if (!this.validateUnclesHash()) {
if (!this.uncleHashIsValid()) {
const msg = this._errorMsg('invalid uncle hash')

@@ -482,3 +588,3 @@ throw new Error(msg)

if (this._common.isActivatedEIP(4895) && !(await this.validateWithdrawalsTrie())) {
if (this.common.isActivatedEIP(4895) && !(await this.withdrawalsTrieIsValid())) {
const msg = this._errorMsg('invalid withdrawals trie')

@@ -490,8 +596,57 @@ throw new Error(msg)

/**
* Validates that data gas fee for each transaction is greater than or equal to the
* dataGasPrice for the block and that total data gas in block is less than maximum
* data gas per block
* @param parentHeader header of parent block
*/
validateBlobTransactions(parentHeader: BlockHeader) {
if (this.common.isActivatedEIP(4844)) {
const dataGasLimit = this.common.param('gasConfig', 'maxDataGasPerBlock')
const dataGasPerBlob = this.common.param('gasConfig', 'dataGasPerBlob')
let dataGasUsed = BigInt(0)
for (const tx of this.transactions) {
if (tx instanceof BlobEIP4844Transaction) {
const dataGasPrice = this.header.getDataGasPrice()
if (tx.maxFeePerDataGas < dataGasPrice) {
throw new Error(
`blob transaction maxFeePerDataGas ${
tx.maxFeePerDataGas
} < than block data gas price ${dataGasPrice} - ${this.errorStr()}`
)
}
dataGasUsed += BigInt(tx.versionedHashes.length) * dataGasPerBlob
if (dataGasUsed > dataGasLimit) {
throw new Error(
`tx causes total data gas of ${dataGasUsed} to exceed maximum data gas per block of ${dataGasLimit}`
)
}
}
}
if (this.header.dataGasUsed !== dataGasUsed) {
throw new Error(
`block dataGasUsed mismatch: have ${this.header.dataGasUsed}, want ${dataGasUsed}`
)
}
const expectedExcessDataGas = parentHeader.calcNextExcessDataGas()
if (this.header.excessDataGas !== expectedExcessDataGas) {
throw new Error(
`block excessDataGas mismatch: have ${this.header.excessDataGas}, want ${expectedExcessDataGas}`
)
}
}
}
/**
* Validates the uncle's hash.
* @returns true if the uncle's hash is valid, false otherwise.
*/
validateUnclesHash(): boolean {
uncleHashIsValid(): boolean {
const uncles = this.uncleHeaders.map((uh) => uh.raw())
const raw = RLP.encode(bufArrToArr(uncles))
return Buffer.from(keccak256(raw)).equals(this.header.uncleHash)
const raw = RLP.encode(uncles)
return equalsBytes(keccak256(raw), this.header.uncleHash)
}

@@ -501,9 +656,10 @@

* Validates the withdrawal root
* @returns true if the withdrawals trie root is valid, false otherwise
*/
async validateWithdrawalsTrie(): Promise<boolean> {
if (!this._common.isActivatedEIP(4895)) {
async withdrawalsTrieIsValid(): Promise<boolean> {
if (!this.common.isActivatedEIP(4895)) {
throw new Error('EIP 4895 is not activated')
}
const withdrawalsRoot = await Block.genWithdrawalsTrieRoot(this.withdrawals!)
return withdrawalsRoot.equals(this.header.withdrawalsRoot!)
return equalsBytes(withdrawalsRoot, this.header.withdrawalsRoot!)
}

@@ -532,3 +688,3 @@

// Header does not count an uncle twice.
const uncleHashes = this.uncleHeaders.map((header) => header.hash().toString('hex'))
const uncleHashes = this.uncleHeaders.map((header) => bytesToHex(header.hash()))
if (!(new Set(uncleHashes).size === uncleHashes.length)) {

@@ -582,3 +738,3 @@ const msg = this._errorMsg('duplicate uncles')

try {
hash = bufferToHex(this.hash())
hash = bytesToHex(this.hash())
} catch (e: any) {

@@ -589,3 +745,3 @@ hash = 'error'

try {
hf = this._common.hardfork()
hf = this.common.hardfork()
} catch (e: any) {

@@ -592,0 +748,0 @@ hf = 'error'

import { TransactionFactory } from '@ethereumjs/tx'
import { TypeOutput, setLengthLeft, toBuffer, toType } from '@ethereumjs/util'
import { TypeOutput, setLengthLeft, toBytes, toType } from '@ethereumjs/util'
import { blockHeaderFromRpc } from './header-from-rpc'
import { blockHeaderFromRpc } from './header-from-rpc.js'
import { Block } from './index'
import { Block } from './index.js'
import type { BlockOptions, JsonRpcBlock } from './index'
import type { TxData, TypedTransaction } from '@ethereumjs/tx'
import type { BlockOptions, JsonRpcBlock } from './index.js'
import type { TypedTransaction } from '@ethereumjs/tx'

@@ -24,3 +24,3 @@ function normalizeTxParams(_txParams: any) {

txParams.to !== null && txParams.to !== undefined
? setLengthLeft(toBuffer(txParams.to), 20)
? setLengthLeft(toBytes(txParams.to), 20)
: null

@@ -49,6 +49,6 @@

const transactions: TypedTransaction[] = []
const opts = { common: header._common }
const opts = { common: header.common }
for (const _txParams of blockParams.transactions ?? []) {
const txParams = normalizeTxParams(_txParams)
const tx = TransactionFactory.fromTxData(txParams as TxData, opts)
const tx = TransactionFactory.fromTxData(txParams, opts)
transactions.push(tx)

@@ -55,0 +55,0 @@ }

@@ -1,5 +0,5 @@

import { BlockHeader } from './header'
import { numberToHex } from './helpers'
import { BlockHeader } from './header.js'
import { numberToHex } from './helpers.js'
import type { BlockOptions, JsonRpcBlock } from './types'
import type { BlockOptions, JsonRpcBlock } from './types.js'

@@ -31,2 +31,4 @@ /**

withdrawalsRoot,
dataGasUsed,
excessDataGas,
} = blockParams

@@ -53,2 +55,4 @@

withdrawalsRoot,
dataGasUsed,
excessDataGas,
},

@@ -55,0 +59,0 @@ options

@@ -8,24 +8,26 @@ import { Chain, Common, ConsensusAlgorithm, ConsensusType, Hardfork } from '@ethereumjs/common'

TypeOutput,
arrToBufArr,
bigIntToBuffer,
bigIntToBytes,
bigIntToHex,
bigIntToUnpaddedBuffer,
bufArrToArr,
bufferToBigInt,
bufferToHex,
bigIntToUnpaddedBytes,
bytesToBigInt,
bytesToHex,
concatBytes,
ecrecover,
ecsign,
equalsBytes,
hexToBytes,
toType,
zeros,
} from '@ethereumjs/util'
import { keccak256 } from 'ethereum-cryptography/keccak'
import { keccak256 } from 'ethereum-cryptography/keccak.js'
import { CLIQUE_EXTRA_SEAL, CLIQUE_EXTRA_VANITY } from './clique'
import { valuesArrayToHeaderData } from './helpers'
import { CLIQUE_EXTRA_SEAL, CLIQUE_EXTRA_VANITY } from './clique.js'
import { fakeExponential, valuesArrayToHeaderData } from './helpers.js'
import type { BlockHeaderBuffer, BlockOptions, HeaderData, JsonHeader } from './types'
import type { BlockHeaderBytes, BlockOptions, HeaderData, JsonHeader } from './types.js'
import type { CliqueConfig } from '@ethereumjs/common'
import type { BigIntLike } from '@ethereumjs/util'
interface HeaderCache {
hash: Buffer | undefined
hash: Uint8Array | undefined
}

@@ -39,9 +41,9 @@

export class BlockHeader {
public readonly parentHash: Buffer
public readonly uncleHash: Buffer
public readonly parentHash: Uint8Array
public readonly uncleHash: Uint8Array
public readonly coinbase: Address
public readonly stateRoot: Buffer
public readonly transactionsTrie: Buffer
public readonly receiptTrie: Buffer
public readonly logsBloom: Buffer
public readonly stateRoot: Uint8Array
public readonly transactionsTrie: Uint8Array
public readonly receiptTrie: Uint8Array
public readonly logsBloom: Uint8Array
public readonly difficulty: bigint

@@ -52,10 +54,12 @@ public readonly number: bigint

public readonly timestamp: bigint
public readonly extraData: Buffer
public readonly mixHash: Buffer
public readonly nonce: Buffer
public readonly extraData: Uint8Array
public readonly mixHash: Uint8Array
public readonly nonce: Uint8Array
public readonly baseFeePerGas?: bigint
public readonly withdrawalsRoot?: Buffer
public readonly withdrawalsRoot?: Uint8Array
public readonly dataGasUsed?: bigint
public readonly excessDataGas?: bigint
public readonly parentBeaconBlockRoot?: Uint8Array
public readonly _common: Common
public readonly common: Common

@@ -70,3 +74,3 @@ private cache: HeaderCache = {

get prevRandao() {
if (this._common.isActivatedEIP(4399) === false) {
if (this.common.isActivatedEIP(4399) === false) {
const msg = this._errorMsg(

@@ -96,12 +100,12 @@ 'The prevRandao parameter can only be accessed when EIP-4399 is activated'

*/
public static fromRLPSerializedHeader(serializedHeaderData: Buffer, opts: BlockOptions = {}) {
const values = arrToBufArr(RLP.decode(Uint8Array.from(serializedHeaderData)))
public static fromRLPSerializedHeader(serializedHeaderData: Uint8Array, opts: BlockOptions = {}) {
const values = RLP.decode(serializedHeaderData)
if (!Array.isArray(values)) {
throw new Error('Invalid serialized header input. Must be array')
}
return BlockHeader.fromValuesArray(values as Buffer[], opts)
return BlockHeader.fromValuesArray(values as Uint8Array[], opts)
}
/**
* Static constructor to create a block header from an array of Buffer values
* Static constructor to create a block header from an array of Bytes values
*

@@ -111,14 +115,26 @@ * @param values

*/
public static fromValuesArray(values: BlockHeaderBuffer, opts: BlockOptions = {}) {
public static fromValuesArray(values: BlockHeaderBytes, opts: BlockOptions = {}) {
const headerData = valuesArrayToHeaderData(values)
const { number, baseFeePerGas } = headerData
const { number, baseFeePerGas, excessDataGas, dataGasUsed, parentBeaconBlockRoot } = headerData
const header = BlockHeader.fromHeaderData(headerData, opts)
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
if (opts.common?.isActivatedEIP(1559) && baseFeePerGas === undefined) {
const eip1559ActivationBlock = bigIntToBuffer(opts.common?.eipBlock(1559)!)
if (header.common.isActivatedEIP(1559) && baseFeePerGas === undefined) {
const eip1559ActivationBlock = bigIntToBytes(header.common.eipBlock(1559)!)
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
if (eip1559ActivationBlock && eip1559ActivationBlock.equals(number! as Buffer)) {
if (eip1559ActivationBlock && equalsBytes(eip1559ActivationBlock, number as Uint8Array)) {
throw new Error('invalid header. baseFeePerGas should be provided')
}
}
return BlockHeader.fromHeaderData(headerData, opts)
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
if (header.common.isActivatedEIP(4844)) {
if (excessDataGas === undefined) {
throw new Error('invalid header. excessDataGas should be provided')
} else if (dataGasUsed === undefined) {
throw new Error('invalid header. dataGasUsed should be provided')
}
}
if (header.common.isActivatedEIP(4788) && parentBeaconBlockRoot === undefined) {
throw new Error('invalid header. parentBeaconBlockRoot should be provided')
}
return header
}

@@ -134,5 +150,5 @@ /**

if (options.common) {
this._common = options.common.copy()
this.common = options.common.copy()
} else {
this._common = new Common({
this.common = new Common({
chain: Chain.Mainnet, // default

@@ -142,8 +158,2 @@ })

if (options.hardforkByBlockNumber !== undefined && options.hardforkByTTD !== undefined) {
throw new Error(
`The hardforkByBlockNumber and hardforkByTTD options can't be used in conjunction`
)
}
const skipValidateConsensusFormat = options.skipConsensusFormatValidation ?? false

@@ -164,3 +174,3 @@

timestamp: BigInt(0),
extraData: Buffer.from([]),
extraData: new Uint8Array(0),
mixHash: zeros(32),

@@ -170,12 +180,13 @@ nonce: zeros(8),

const parentHash = toType(headerData.parentHash, TypeOutput.Buffer) ?? defaults.parentHash
const uncleHash = toType(headerData.uncleHash, TypeOutput.Buffer) ?? defaults.uncleHash
const parentHash = toType(headerData.parentHash, TypeOutput.Uint8Array) ?? defaults.parentHash
const uncleHash = toType(headerData.uncleHash, TypeOutput.Uint8Array) ?? defaults.uncleHash
const coinbase = new Address(
toType(headerData.coinbase ?? defaults.coinbase, TypeOutput.Buffer)
toType(headerData.coinbase ?? defaults.coinbase, TypeOutput.Uint8Array)
)
const stateRoot = toType(headerData.stateRoot, TypeOutput.Buffer) ?? defaults.stateRoot
const stateRoot = toType(headerData.stateRoot, TypeOutput.Uint8Array) ?? defaults.stateRoot
const transactionsTrie =
toType(headerData.transactionsTrie, TypeOutput.Buffer) ?? defaults.transactionsTrie
const receiptTrie = toType(headerData.receiptTrie, TypeOutput.Buffer) ?? defaults.receiptTrie
const logsBloom = toType(headerData.logsBloom, TypeOutput.Buffer) ?? defaults.logsBloom
toType(headerData.transactionsTrie, TypeOutput.Uint8Array) ?? defaults.transactionsTrie
const receiptTrie =
toType(headerData.receiptTrie, TypeOutput.Uint8Array) ?? defaults.receiptTrie
const logsBloom = toType(headerData.logsBloom, TypeOutput.Uint8Array) ?? defaults.logsBloom
const difficulty = toType(headerData.difficulty, TypeOutput.BigInt) ?? defaults.difficulty

@@ -186,9 +197,18 @@ const number = toType(headerData.number, TypeOutput.BigInt) ?? defaults.number

const timestamp = toType(headerData.timestamp, TypeOutput.BigInt) ?? defaults.timestamp
const extraData = toType(headerData.extraData, TypeOutput.Buffer) ?? defaults.extraData
const mixHash = toType(headerData.mixHash, TypeOutput.Buffer) ?? defaults.mixHash
const nonce = toType(headerData.nonce, TypeOutput.Buffer) ?? defaults.nonce
const extraData = toType(headerData.extraData, TypeOutput.Uint8Array) ?? defaults.extraData
const mixHash = toType(headerData.mixHash, TypeOutput.Uint8Array) ?? defaults.mixHash
const nonce = toType(headerData.nonce, TypeOutput.Uint8Array) ?? defaults.nonce
const hardforkByBlockNumber = options.hardforkByBlockNumber ?? false
if (hardforkByBlockNumber || options.hardforkByTTD !== undefined) {
this._common.setHardforkByBlockNumber(number, options.hardforkByTTD, timestamp)
const setHardfork = options.setHardfork ?? false
if (setHardfork === true) {
this.common.setHardforkBy({
blockNumber: number,
timestamp,
})
} else if (typeof setHardfork !== 'boolean') {
this.common.setHardforkBy({
blockNumber: number,
td: setHardfork as BigIntLike,
timestamp,
})
}

@@ -198,9 +218,11 @@

const hardforkDefaults = {
baseFeePerGas: this._common.isActivatedEIP(1559)
? number === this._common.hardforkBlock(Hardfork.London)
? this._common.param('gasConfig', 'initialBaseFee')
baseFeePerGas: this.common.isActivatedEIP(1559)
? number === this.common.hardforkBlock(Hardfork.London)
? this.common.param('gasConfig', 'initialBaseFee')
: BigInt(7)
: undefined,
withdrawalsRoot: this._common.isActivatedEIP(4895) ? KECCAK256_RLP : undefined,
excessDataGas: this._common.isActivatedEIP(4844) ? BigInt(0) : undefined,
withdrawalsRoot: this.common.isActivatedEIP(4895) ? KECCAK256_RLP : undefined,
dataGasUsed: this.common.isActivatedEIP(4844) ? BigInt(0) : undefined,
excessDataGas: this.common.isActivatedEIP(4844) ? BigInt(0) : undefined,
parentBeaconBlockRoot: this.common.isActivatedEIP(4788) ? zeros(32) : undefined,
}

@@ -211,11 +233,16 @@

const withdrawalsRoot =
toType(headerData.withdrawalsRoot, TypeOutput.Buffer) ?? hardforkDefaults.withdrawalsRoot
toType(headerData.withdrawalsRoot, TypeOutput.Uint8Array) ?? hardforkDefaults.withdrawalsRoot
const dataGasUsed =
toType(headerData.dataGasUsed, TypeOutput.BigInt) ?? hardforkDefaults.dataGasUsed
const excessDataGas =
toType(headerData.excessDataGas, TypeOutput.BigInt) ?? hardforkDefaults.excessDataGas
const parentBeaconBlockRoot =
toType(headerData.parentBeaconBlockRoot, TypeOutput.Uint8Array) ??
hardforkDefaults.parentBeaconBlockRoot
if (!this._common.isActivatedEIP(1559) && baseFeePerGas !== undefined) {
if (!this.common.isActivatedEIP(1559) && baseFeePerGas !== undefined) {
throw new Error('A base fee for a block can only be set with EIP1559 being activated')
}
if (!this._common.isActivatedEIP(4895) && withdrawalsRoot !== undefined) {
if (!this.common.isActivatedEIP(4895) && withdrawalsRoot !== undefined) {
throw new Error(

@@ -226,2 +253,18 @@ 'A withdrawalsRoot for a header can only be provided with EIP4895 being activated'

if (!this.common.isActivatedEIP(4844)) {
if (headerData.dataGasUsed !== undefined) {
throw new Error('data gas used can only be provided with EIP4844 activated')
}
if (headerData.excessDataGas !== undefined) {
throw new Error('excess data gas can only be provided with EIP4844 activated')
}
}
if (!this.common.isActivatedEIP(4788) && parentBeaconBlockRoot !== undefined) {
throw new Error(
'A parentBeaconBlockRoot for a header can only be provided with EIP4788 being activated'
)
}
this.parentHash = parentHash

@@ -244,3 +287,5 @@ this.uncleHash = uncleHash

this.withdrawalsRoot = withdrawalsRoot
this.dataGasUsed = dataGasUsed
this.excessDataGas = excessDataGas
this.parentBeaconBlockRoot = parentBeaconBlockRoot
this._genericFormatValidation()

@@ -254,3 +299,3 @@ this._validateDAOExtraData()

options.calcDifficultyFromHeader &&
this._common.consensusAlgorithm() === ConsensusAlgorithm.Ethash
this.common.consensusAlgorithm() === ConsensusAlgorithm.Ethash
) {

@@ -266,3 +311,3 @@ this.difficulty = this.ethashCanonicalDifficulty(options.calcDifficultyFromHeader)

const remainingLength = minExtraDataLength - this.extraData.length
this.extraData = Buffer.concat([this.extraData, Buffer.alloc(remainingLength)])
this.extraData = concatBytes(this.extraData, new Uint8Array(remainingLength))
}

@@ -285,3 +330,3 @@

*/
_genericFormatValidation() {
protected _genericFormatValidation() {
const { parentHash, stateRoot, transactionsTrie, receiptTrie, mixHash, nonce } = this

@@ -326,3 +371,3 @@

// Validation for EIP-1559 blocks
if (this._common.isActivatedEIP(1559) === true) {
if (this.common.isActivatedEIP(1559) === true) {
if (typeof this.baseFeePerGas !== 'bigint') {

@@ -332,3 +377,3 @@ const msg = this._errorMsg('EIP1559 block has no base fee field')

}
const londonHfBlock = this._common.hardforkBlock(Hardfork.London)
const londonHfBlock = this.common.hardforkBlock(Hardfork.London)
if (

@@ -339,3 +384,3 @@ typeof londonHfBlock === 'bigint' &&

) {
const initialBaseFee = this._common.param('gasConfig', 'initialBaseFee')
const initialBaseFee = this.common.param('gasConfig', 'initialBaseFee')
if (this.baseFeePerGas !== initialBaseFee) {

@@ -348,3 +393,3 @@ const msg = this._errorMsg('Initial EIP1559 block does not have initial base fee')

if (this._common.isActivatedEIP(4895) === true) {
if (this.common.isActivatedEIP(4895) === true) {
if (this.withdrawalsRoot === undefined) {

@@ -361,2 +406,17 @@ const msg = this._errorMsg('EIP4895 block has no withdrawalsRoot field')

}
if (this.common.isActivatedEIP(4788) === true) {
if (this.parentBeaconBlockRoot === undefined) {
const msg = this._errorMsg('EIP4788 block has no parentBeaconBlockRoot field')
throw new Error(msg)
}
if (this.parentBeaconBlockRoot?.length !== 32) {
const msg = this._errorMsg(
`parentBeaconBlockRoot must be 32 bytes, received ${
this.parentBeaconBlockRoot!.length
} bytes`
)
throw new Error(msg)
}
}
}

@@ -368,12 +428,12 @@

*/
_consensusFormatValidation() {
protected _consensusFormatValidation() {
const { nonce, uncleHash, difficulty, extraData, number } = this
const hardfork = this._common.hardfork()
const hardfork = this.common.hardfork()
// Consensus type dependent checks
if (this._common.consensusAlgorithm() === ConsensusAlgorithm.Ethash) {
if (this.common.consensusAlgorithm() === ConsensusAlgorithm.Ethash) {
// PoW/Ethash
if (
number > BigInt(0) &&
this.extraData.length > this._common.paramByHardfork('vm', 'maxExtraDataSize', hardfork)
this.extraData.length > this.common.paramByHardfork('vm', 'maxExtraDataSize', hardfork)
) {

@@ -385,3 +445,3 @@ // Check length of data on all post-genesis blocks

}
if (this._common.consensusAlgorithm() === ConsensusAlgorithm.Clique) {
if (this.common.consensusAlgorithm() === ConsensusAlgorithm.Clique) {
// PoA/Clique

@@ -414,3 +474,3 @@ const minLength = CLIQUE_EXTRA_VANITY + CLIQUE_EXTRA_SEAL

// MixHash format
if (!this.mixHash.equals(Buffer.alloc(32))) {
if (!equalsBytes(this.mixHash, new Uint8Array(32))) {
const msg = this._errorMsg(`mixHash must be filled with zeros, received ${this.mixHash}`)

@@ -421,10 +481,10 @@ throw new Error(msg)

// Validation for PoS blocks (EIP-3675)
if (this._common.consensusType() === ConsensusType.ProofOfStake) {
if (this.common.consensusType() === ConsensusType.ProofOfStake) {
let error = false
let errorMsg = ''
if (!uncleHash.equals(KECCAK256_RLP_ARRAY)) {
errorMsg += `, uncleHash: ${uncleHash.toString(
'hex'
)} (expected: ${KECCAK256_RLP_ARRAY.toString('hex')})`
if (!equalsBytes(uncleHash, KECCAK256_RLP_ARRAY)) {
errorMsg += `, uncleHash: ${bytesToHex(uncleHash)} (expected: ${bytesToHex(
KECCAK256_RLP_ARRAY
)})`
error = true

@@ -439,9 +499,9 @@ }

if (extraData.length > 32) {
errorMsg += `, extraData: ${extraData.toString(
'hex'
errorMsg += `, extraData: ${bytesToHex(
extraData
)} (cannot exceed 32 bytes length, received ${extraData.length} bytes)`
error = true
}
if (!nonce.equals(zeros(8))) {
errorMsg += `, nonce: ${nonce.toString('hex')} (expected: ${zeros(8).toString('hex')})`
if (!equalsBytes(nonce, zeros(8))) {
errorMsg += `, nonce: ${bytesToHex(nonce)} (expected: ${bytesToHex(zeros(8))})`
error = true

@@ -451,3 +511,3 @@ }

if (error) {
const msg = this._errorMsg(`Invalid PoS block${errorMsg}`)
const msg = this._errorMsg(`Invalid PoS block: ${errorMsg}`)
throw new Error(msg)

@@ -468,3 +528,3 @@ }

// to adopt to the new gas target centered logic
const londonHardforkBlock = this._common.hardforkBlock(Hardfork.London)
const londonHardforkBlock = this.common.hardforkBlock(Hardfork.London)
if (

@@ -475,10 +535,10 @@ typeof londonHardforkBlock === 'bigint' &&

) {
const elasticity = this._common.param('gasConfig', 'elasticityMultiplier')
const elasticity = this.common.param('gasConfig', 'elasticityMultiplier')
parentGasLimit = parentGasLimit * elasticity
}
const gasLimit = this.gasLimit
const hardfork = this._common.hardfork()
const hardfork = this.common.hardfork()
const a =
parentGasLimit / this._common.paramByHardfork('gasConfig', 'gasLimitBoundDivisor', hardfork)
parentGasLimit / this.common.paramByHardfork('gasConfig', 'gasLimitBoundDivisor', hardfork)
const maxGasLimit = parentGasLimit + a

@@ -497,3 +557,3 @@ const minGasLimit = parentGasLimit - a

if (gasLimit < this._common.paramByHardfork('gasConfig', 'minGasLimit', hardfork)) {
if (gasLimit < this.common.paramByHardfork('gasConfig', 'minGasLimit', hardfork)) {
const msg = this._errorMsg(

@@ -510,3 +570,3 @@ `gas limit decreased below minimum gas limit for hardfork=${hardfork}`

public calcNextBaseFee(): bigint {
if (this._common.isActivatedEIP(1559) === false) {
if (this.common.isActivatedEIP(1559) === false) {
const msg = this._errorMsg(

@@ -518,3 +578,3 @@ 'calcNextBaseFee() can only be called with EIP1559 being activated'

let nextBaseFee: bigint
const elasticity = this._common.param('gasConfig', 'elasticityMultiplier')
const elasticity = this.common.param('gasConfig', 'elasticityMultiplier')
const parentGasTarget = this.gasLimit / elasticity

@@ -526,3 +586,3 @@

const gasUsedDelta = this.gasUsed - parentGasTarget
const baseFeeMaxChangeDenominator = this._common.param(
const baseFeeMaxChangeDenominator = this.common.param(
'gasConfig',

@@ -538,3 +598,3 @@ 'baseFeeMaxChangeDenominator'

const gasUsedDelta = parentGasTarget - this.gasUsed
const baseFeeMaxChangeDenominator = this._common.param(
const baseFeeMaxChangeDenominator = this.common.param(
'gasConfig',

@@ -555,9 +615,53 @@ 'baseFeeMaxChangeDenominator'

/**
* Returns a Buffer Array of the raw Buffers in this header, in order.
* Returns the price per unit of data gas for a blob transaction in the current/pending block
* @returns the price in gwei per unit of data gas spent
*/
raw(): BlockHeaderBuffer {
getDataGasPrice(): bigint {
if (this.excessDataGas === undefined) {
throw new Error('header must have excessDataGas field populated')
}
return fakeExponential(
this.common.param('gasPrices', 'minDataGasPrice'),
this.excessDataGas,
this.common.param('gasConfig', 'dataGasPriceUpdateFraction')
)
}
/**
* Returns the total fee for data gas spent for including blobs in block.
*
* @param numBlobs number of blobs in the transaction/block
* @returns the total data gas fee for numBlobs blobs
*/
calcDataFee(numBlobs: number): bigint {
const dataGasPerBlob = this.common.param('gasConfig', 'dataGasPerBlob')
const dataGasUsed = dataGasPerBlob * BigInt(numBlobs)
const dataGasPrice = this.getDataGasPrice()
return dataGasUsed * dataGasPrice
}
/**
* Calculates the excess data gas for next (hopefully) post EIP 4844 block.
*/
public calcNextExcessDataGas(): bigint {
// The validation of the fields and 4844 activation is already taken care in BlockHeader constructor
const targetGasConsumed = (this.excessDataGas ?? BigInt(0)) + (this.dataGasUsed ?? BigInt(0))
const targetDataGasPerBlock = this.common.param('gasConfig', 'targetDataGasPerBlock')
if (targetGasConsumed <= targetDataGasPerBlock) {
return BigInt(0)
} else {
return targetGasConsumed - targetDataGasPerBlock
}
}
/**
* Returns a Uint8Array Array of the raw Bytes in this header, in order.
*/
raw(): BlockHeaderBytes {
const rawItems = [
this.parentHash,
this.uncleHash,
this.coinbase.buf,
this.coinbase.bytes,
this.stateRoot,

@@ -567,7 +671,7 @@ this.transactionsTrie,

this.logsBloom,
bigIntToUnpaddedBuffer(this.difficulty),
bigIntToUnpaddedBuffer(this.number),
bigIntToUnpaddedBuffer(this.gasLimit),
bigIntToUnpaddedBuffer(this.gasUsed),
bigIntToUnpaddedBuffer(this.timestamp ?? BigInt(0)),
bigIntToUnpaddedBytes(this.difficulty),
bigIntToUnpaddedBytes(this.number),
bigIntToUnpaddedBytes(this.gasLimit),
bigIntToUnpaddedBytes(this.gasUsed),
bigIntToUnpaddedBytes(this.timestamp ?? BigInt(0)),
this.extraData,

@@ -578,12 +682,16 @@ this.mixHash,

if (this._common.isActivatedEIP(1559) === true) {
rawItems.push(bigIntToUnpaddedBuffer(this.baseFeePerGas!))
if (this.common.isActivatedEIP(1559) === true) {
rawItems.push(bigIntToUnpaddedBytes(this.baseFeePerGas!))
}
if (this._common.isActivatedEIP(4895) === true) {
if (this.common.isActivatedEIP(4895) === true) {
rawItems.push(this.withdrawalsRoot!)
}
if (this._common.isActivatedEIP(4844) === true) {
rawItems.push(bigIntToUnpaddedBuffer(this.excessDataGas!))
if (this.common.isActivatedEIP(4844) === true) {
rawItems.push(bigIntToUnpaddedBytes(this.dataGasUsed!))
rawItems.push(bigIntToUnpaddedBytes(this.excessDataGas!))
}
if (this.common.isActivatedEIP(4788) === true) {
rawItems.push(this.parentBeaconBlockRoot!)
}

@@ -596,6 +704,6 @@ return rawItems

*/
hash(): Buffer {
hash(): Uint8Array {
if (Object.isFrozen(this)) {
if (!this.cache.hash) {
this.cache.hash = Buffer.from(keccak256(RLP.encode(bufArrToArr(this.raw()))))
this.cache.hash = keccak256(RLP.encode(this.raw()))
}

@@ -605,3 +713,3 @@ return this.cache.hash

return Buffer.from(keccak256(RLP.encode(bufArrToArr(this.raw()))))
return keccak256(RLP.encode(this.raw()))
}

@@ -616,4 +724,4 @@

private _requireClique(name: string) {
if (this._common.consensusAlgorithm() !== ConsensusAlgorithm.Clique) {
protected _requireClique(name: string) {
if (this.common.consensusAlgorithm() !== ConsensusAlgorithm.Clique) {
const msg = this._errorMsg(

@@ -632,7 +740,7 @@ `BlockHeader.${name}() call only supported for clique PoA networks`

ethashCanonicalDifficulty(parentBlockHeader: BlockHeader): bigint {
if (this._common.consensusType() !== ConsensusType.ProofOfWork) {
if (this.common.consensusType() !== ConsensusType.ProofOfWork) {
const msg = this._errorMsg('difficulty calculation is only supported on PoW chains')
throw new Error(msg)
}
if (this._common.consensusAlgorithm() !== ConsensusAlgorithm.Ethash) {
if (this.common.consensusAlgorithm() !== ConsensusAlgorithm.Ethash) {
const msg = this._errorMsg(

@@ -643,8 +751,8 @@ 'difficulty calculation currently only supports the ethash algorithm'

}
const hardfork = this._common.hardfork()
const hardfork = this.common.hardfork()
const blockTs = this.timestamp
const { timestamp: parentTs, difficulty: parentDif } = parentBlockHeader
const minimumDifficulty = this._common.paramByHardfork('pow', 'minimumDifficulty', hardfork)
const minimumDifficulty = this.common.paramByHardfork('pow', 'minimumDifficulty', hardfork)
const offset =
parentDif / this._common.paramByHardfork('pow', 'difficultyBoundDivisor', hardfork)
parentDif / this.common.paramByHardfork('pow', 'difficultyBoundDivisor', hardfork)
let num = this.number

@@ -655,5 +763,5 @@

if (this._common.hardforkGteHardfork(hardfork, Hardfork.Byzantium) === true) {
if (this.common.hardforkGteHardfork(hardfork, Hardfork.Byzantium) === true) {
// max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp) // 9), -99) (EIP100)
const uncleAddend = parentBlockHeader.uncleHash.equals(KECCAK256_RLP_ARRAY) ? 1 : 2
const uncleAddend = equalsBytes(parentBlockHeader.uncleHash, KECCAK256_RLP_ARRAY) ? 1 : 2
let a = BigInt(uncleAddend) - (blockTs - parentTs) / BigInt(9)

@@ -668,9 +776,9 @@ const cutoff = BigInt(-99)

if (this._common.hardforkGteHardfork(hardfork, Hardfork.Byzantium) === true) {
if (this.common.hardforkGteHardfork(hardfork, Hardfork.Byzantium) === true) {
// Get delay as parameter from common
num = num - this._common.param('pow', 'difficultyBombDelay')
num = num - this.common.param('pow', 'difficultyBombDelay')
if (num < BigInt(0)) {
num = BigInt(0)
}
} else if (this._common.hardforkGteHardfork(hardfork, Hardfork.Homestead) === true) {
} else if (this.common.hardforkGteHardfork(hardfork, Hardfork.Homestead) === true) {
// 1 - (block_timestamp - parent_timestamp) // 10

@@ -686,3 +794,3 @@ let a = BigInt(1) - (blockTs - parentTs) / BigInt(10)

// pre-homestead
if (parentTs + this._common.paramByHardfork('pow', 'durationLimit', hardfork) > blockTs) {
if (parentTs + this.common.paramByHardfork('pow', 'durationLimit', hardfork) > blockTs) {
dif = offset + parentDif

@@ -712,4 +820,4 @@ } else {

const raw = this.raw()
raw[12] = this.extraData.slice(0, this.extraData.length - CLIQUE_EXTRA_SEAL)
return Buffer.from(keccak256(RLP.encode(bufArrToArr(raw))))
raw[12] = this.extraData.subarray(0, this.extraData.length - CLIQUE_EXTRA_SEAL)
return keccak256(RLP.encode(raw))
}

@@ -723,3 +831,3 @@

this._requireClique('cliqueIsEpochTransition')
const epoch = BigInt((this._common.consensusConfig() as CliqueConfig).epoch)
const epoch = BigInt((this.common.consensusConfig() as CliqueConfig).epoch)
// Epoch transition block if the block number has no

@@ -734,5 +842,5 @@ // remainder on the division by the epoch length

*/
cliqueExtraVanity(): Buffer {
cliqueExtraVanity(): Uint8Array {
this._requireClique('cliqueExtraVanity')
return this.extraData.slice(0, CLIQUE_EXTRA_VANITY)
return this.extraData.subarray(0, CLIQUE_EXTRA_VANITY)
}

@@ -744,5 +852,5 @@

*/
cliqueExtraSeal(): Buffer {
cliqueExtraSeal(): Uint8Array {
this._requireClique('cliqueExtraSeal')
return this.extraData.slice(-CLIQUE_EXTRA_SEAL)
return this.extraData.subarray(-CLIQUE_EXTRA_SEAL)
}

@@ -755,14 +863,17 @@

*/
private cliqueSealBlock(privateKey: Buffer) {
private cliqueSealBlock(privateKey: Uint8Array) {
this._requireClique('cliqueSealBlock')
const signature = ecsign(this.cliqueSigHash(), privateKey)
const signatureB = Buffer.concat([
const signatureB = concatBytes(
signature.r,
signature.s,
bigIntToBuffer(signature.v - BigInt(27)),
])
bigIntToBytes(signature.v - BigInt(27))
)
const extraDataWithoutSeal = this.extraData.slice(0, this.extraData.length - CLIQUE_EXTRA_SEAL)
const extraData = Buffer.concat([extraDataWithoutSeal, signatureB])
const extraDataWithoutSeal = this.extraData.subarray(
0,
this.extraData.length - CLIQUE_EXTRA_SEAL
)
const extraData = concatBytes(extraDataWithoutSeal, signatureB)
return extraData

@@ -788,8 +899,8 @@ }

const end = this.extraData.length - CLIQUE_EXTRA_SEAL
const signerBuffer = this.extraData.slice(start, end)
const signerBytes = this.extraData.subarray(start, end)
const signerList: Buffer[] = []
const signerList: Uint8Array[] = []
const signerLength = 20
for (let start = 0; start <= signerBuffer.length - signerLength; start += signerLength) {
signerList.push(signerBuffer.slice(start, start + signerLength))
for (let start = 0; start <= signerBytes.length - signerLength; start += signerLength) {
signerList.push(signerBytes.subarray(start, start + signerLength))
}

@@ -821,8 +932,8 @@ return signerList.map((buf) => new Address(buf))

// Reasonable default for default blocks
if (extraSeal.length === 0 || extraSeal.equals(Buffer.alloc(65).fill(0))) {
if (extraSeal.length === 0 || equalsBytes(extraSeal, new Uint8Array(65))) {
return Address.zero()
}
const r = extraSeal.slice(0, 32)
const s = extraSeal.slice(32, 64)
const v = bufferToBigInt(extraSeal.slice(64, 65)) + BigInt(27)
const r = extraSeal.subarray(0, 32)
const s = extraSeal.subarray(32, 64)
const v = bytesToBigInt(extraSeal.subarray(64, 65)) + BigInt(27)
const pubKey = ecrecover(this.cliqueSigHash(), v, r, s)

@@ -835,4 +946,4 @@ return Address.fromPublicKey(pubKey)

*/
serialize(): Buffer {
return Buffer.from(RLP.encode(bufArrToArr(this.raw())))
serialize(): Uint8Array {
return RLP.encode(this.raw())
}

@@ -845,13 +956,13 @@

const withdrawalAttr = this.withdrawalsRoot
? { withdrawalsRoot: '0x' + this.withdrawalsRoot.toString('hex') }
? { withdrawalsRoot: bytesToHex(this.withdrawalsRoot) }
: {}
const jsonDict: JsonHeader = {
parentHash: '0x' + this.parentHash.toString('hex'),
uncleHash: '0x' + this.uncleHash.toString('hex'),
parentHash: bytesToHex(this.parentHash),
uncleHash: bytesToHex(this.uncleHash),
coinbase: this.coinbase.toString(),
stateRoot: '0x' + this.stateRoot.toString('hex'),
transactionsTrie: '0x' + this.transactionsTrie.toString('hex'),
stateRoot: bytesToHex(this.stateRoot),
transactionsTrie: bytesToHex(this.transactionsTrie),
...withdrawalAttr,
receiptTrie: '0x' + this.receiptTrie.toString('hex'),
logsBloom: '0x' + this.logsBloom.toString('hex'),
receiptTrie: bytesToHex(this.receiptTrie),
logsBloom: bytesToHex(this.logsBloom),
difficulty: bigIntToHex(this.difficulty),

@@ -862,12 +973,16 @@ number: bigIntToHex(this.number),

timestamp: bigIntToHex(this.timestamp),
extraData: '0x' + this.extraData.toString('hex'),
mixHash: '0x' + this.mixHash.toString('hex'),
nonce: '0x' + this.nonce.toString('hex'),
extraData: bytesToHex(this.extraData),
mixHash: bytesToHex(this.mixHash),
nonce: bytesToHex(this.nonce),
}
if (this._common.isActivatedEIP(1559) === true) {
if (this.common.isActivatedEIP(1559) === true) {
jsonDict.baseFeePerGas = bigIntToHex(this.baseFeePerGas!)
}
if (this._common.isActivatedEIP(4844) === true) {
if (this.common.isActivatedEIP(4844) === true) {
jsonDict.dataGasUsed = bigIntToHex(this.dataGasUsed!)
jsonDict.excessDataGas = bigIntToHex(this.excessDataGas!)
}
if (this.common.isActivatedEIP(4788) === true) {
jsonDict.parentBeaconBlockRoot = bytesToHex(this.parentBeaconBlockRoot!)
}
return jsonDict

@@ -880,14 +995,14 @@ }

*/
private _validateDAOExtraData() {
if (this._common.hardforkIsActiveOnBlock(Hardfork.Dao, this.number) === false) {
protected _validateDAOExtraData() {
if (this.common.hardforkIsActiveOnBlock(Hardfork.Dao, this.number) === false) {
return
}
const DAOActivationBlock = this._common.hardforkBlock(Hardfork.Dao)
const DAOActivationBlock = this.common.hardforkBlock(Hardfork.Dao)
if (DAOActivationBlock === null || this.number < DAOActivationBlock) {
return
}
const DAO_ExtraData = Buffer.from('64616f2d686172642d666f726b', 'hex')
const DAO_ExtraData = hexToBytes('0x64616f2d686172642d666f726b')
const DAO_ForceExtraDataRange = BigInt(9)
const drift = this.number - DAOActivationBlock
if (drift <= DAO_ForceExtraDataRange && !this.extraData.equals(DAO_ExtraData)) {
if (drift <= DAO_ForceExtraDataRange && !equalsBytes(this.extraData, DAO_ExtraData)) {
const msg = this._errorMsg("extraData should be 'dao-hard-fork'")

@@ -904,3 +1019,3 @@ throw new Error(msg)

try {
hash = bufferToHex(this.hash())
hash = bytesToHex(this.hash())
} catch (e: any) {

@@ -911,3 +1026,3 @@ hash = 'error'

try {
hf = this._common.hardfork()
hf = this.common.hardfork()
} catch (e: any) {

@@ -914,0 +1029,0 @@ hf = 'error'

@@ -0,5 +1,6 @@

import { BlobEIP4844Transaction } from '@ethereumjs/tx'
import { TypeOutput, isHexString, toType } from '@ethereumjs/util'
import type { BlockHeader } from './header'
import type { BlockHeaderBuffer, HeaderData } from './types'
import type { BlockHeaderBytes, HeaderData } from './types.js'
import type { TypedTransaction } from '@ethereumjs/tx'

@@ -23,3 +24,3 @@ /**

export function valuesArrayToHeaderData(values: BlockHeaderBuffer): HeaderData {
export function valuesArrayToHeaderData(values: BlockHeaderBytes): HeaderData {
const [

@@ -43,6 +44,8 @@ parentHash,

withdrawalsRoot,
dataGasUsed,
excessDataGas,
parentBeaconBlockRoot,
] = values
if (values.length > 18) {
if (values.length > 20) {
throw new Error('invalid header. More values than expected were received')

@@ -72,3 +75,5 @@ }

withdrawalsRoot,
dataGasUsed,
excessDataGas,
parentBeaconBlockRoot,
}

@@ -85,28 +90,10 @@ }

/**
* Calculates the excess data gas for a post EIP 4844 block given the parent block header.
* @param parent header for the parent block
* @param newBlobs number of blobs contained in block
* @returns the excess data gas for the prospective next block
*
* Note: This function expects that it is only being called on a valid block as it does not have
* access to the "current" block's common instance to verify if 4844 is active or not.
*/
export const calcExcessDataGas = (parent: BlockHeader, newBlobs: number) => {
if (!parent._common.isActivatedEIP(4844)) {
// If 4844 isn't active on header, assume this is the first post-fork block so excess data gas is 0
return BigInt(0)
export const getNumBlobs = (transactions: TypedTransaction[]) => {
let numBlobs = 0
for (const tx of transactions) {
if (tx instanceof BlobEIP4844Transaction) {
numBlobs += tx.versionedHashes.length
}
}
if (parent.excessDataGas === undefined) {
// Given 4844 is active on parent block, we expect it to have an excessDataGas field
throw new Error('parent header does not contain excessDataGas field')
}
const consumedDataGas = BigInt(newBlobs) * parent._common.param('gasConfig', 'dataGasPerBlob')
const targetDataGasPerBlock = parent._common.param('gasConfig', 'targetDataGasPerBlock')
if (parent.excessDataGas + consumedDataGas < targetDataGasPerBlock) return BigInt(0)
else {
return parent.excessDataGas + consumedDataGas - targetDataGasPerBlock
}
return numBlobs
}

@@ -123,37 +110,7 @@

output += numerator_accum
numerator_accum = BigInt(Math.floor(Number((numerator_accum * numerator) / (denominator * i))))
numerator_accum = (numerator_accum * numerator) / (denominator * i)
i++
}
return BigInt(Math.floor(Number(output / denominator)))
}
/**
* Returns the price per unit of data gas for a blob transaction in the current/pending block
* @param header the parent header for the current block (or current head of the chain)
* @returns the price in gwei per unit of data gas spent
*/
export const getDataGasPrice = (header: BlockHeader) => {
if (header.excessDataGas === undefined) {
throw new Error('parent header must have excessDataGas field populated')
}
return fakeExponential(
header._common.param('gasPrices', 'minDataGasPrice'),
header.excessDataGas,
header._common.param('gasConfig', 'dataGasPriceUpdateFraction')
)
return output / denominator
}
/**
* Returns the total fee for data gas spent on `numBlobs` in the current/pending block
* @param numBlobs
* @param parent parent header of the current/pending block
* @returns the total data gas fee for a transaction assuming it contains `numBlobs`
*/
export const calcDataFee = (numBlobs: number, parent: BlockHeader) => {
if (parent.excessDataGas === undefined) {
throw new Error('parent header must have excessDataGas field populated')
}
const totalDataGas = parent._common.param('gasConfig', 'dataGasPerBlob') * BigInt(numBlobs)
const dataGasPrice = getDataGasPrice(parent)
return totalDataGas * dataGasPrice
}

@@ -1,10 +0,4 @@

export { Block } from './block'
export { BlockHeader } from './header'
export {
calcDataFee,
calcExcessDataGas,
getDataGasPrice,
getDifficulty,
valuesArrayToHeaderData,
} from './helpers'
export * from './types'
export { Block } from './block.js'
export { BlockHeader } from './header.js'
export { getDifficulty, valuesArrayToHeaderData } from './helpers.js'
export * from './types.js'

@@ -1,16 +0,11 @@

import type { BlockHeader } from './header'
import type { BlockHeader } from './header.js'
import type { Common } from '@ethereumjs/common'
import type { JsonRpcTx, JsonTx, TransactionType, TxData } from '@ethereumjs/tx'
import type {
AccessListEIP2930TxData,
FeeMarketEIP1559TxData,
JsonRpcTx,
JsonTx,
TxData,
} from '@ethereumjs/tx'
import type {
AddressLike,
BigIntLike,
BufferLike,
BytesLike,
JsonRpcWithdrawal,
WithdrawalBuffer,
PrefixedHexString,
WithdrawalBytes,
WithdrawalData,

@@ -38,19 +33,12 @@ } from '@ethereumjs/util'

/**
* Determine the HF by the block number
* Set the hardfork either by timestamp (for HFs from Shanghai onwards) or by block number
* for older Hfs.
*
* Additionally it is possible to pass in a specific TD value to support live-Merge-HF
* transitions. Note that this should only be needed in very rare and specific scenarios.
*
* Default: `false` (HF is set to whatever default HF is set by the {@link Common} instance)
*/
hardforkByBlockNumber?: boolean
setHardfork?: boolean | BigIntLike
/**
* Determine the HF by total difficulty (Merge HF)
*
* This option is a superset of `hardforkByBlockNumber` (so only use one of both options)
* and determines the HF by both the block number and the TD.
*
* Since the TTD is only a threshold the block number will in doubt take precedence (imagine
* e.g. both Merge and Shanghai HF blocks set and the block number from the block provided
* pointing to a Shanghai block: this will lead to set the HF as Shanghai and not the Merge).
*/
hardforkByTTD?: BigIntLike
/**
* If a preceding {@link BlockHeader} (usually the parent header) is given the preceding

@@ -80,3 +68,3 @@ * header will be used to calculate the difficulty for this block and the calculated

*/
cliqueSigner?: Buffer
cliqueSigner?: Uint8Array
/**

@@ -92,9 +80,9 @@ * Skip consensus format validation checks on header if set. Defaults to false.

export interface HeaderData {
parentHash?: BufferLike
uncleHash?: BufferLike
parentHash?: BytesLike
uncleHash?: BytesLike
coinbase?: AddressLike
stateRoot?: BufferLike
transactionsTrie?: BufferLike
receiptTrie?: BufferLike
logsBloom?: BufferLike
stateRoot?: BytesLike
transactionsTrie?: BytesLike
receiptTrie?: BytesLike
logsBloom?: BytesLike
difficulty?: BigIntLike

@@ -105,8 +93,10 @@ number?: BigIntLike

timestamp?: BigIntLike
extraData?: BufferLike
mixHash?: BufferLike
nonce?: BufferLike
extraData?: BytesLike
mixHash?: BytesLike
nonce?: BytesLike
baseFeePerGas?: BigIntLike
withdrawalsRoot?: BufferLike
withdrawalsRoot?: BytesLike
dataGasUsed?: BigIntLike
excessDataGas?: BigIntLike
parentBeaconBlockRoot?: BytesLike
}

@@ -122,3 +112,3 @@

header?: HeaderData
transactions?: Array<TxData | AccessListEIP2930TxData | FeeMarketEIP1559TxData>
transactions?: Array<TxData[TransactionType]>
uncleHeaders?: Array<HeaderData>

@@ -128,14 +118,14 @@ withdrawals?: Array<WithdrawalData>

export type WithdrawalsBuffer = WithdrawalBuffer[]
export type WithdrawalsBytes = WithdrawalBytes[]
export type BlockBuffer =
| [BlockHeaderBuffer, TransactionsBuffer, UncleHeadersBuffer]
| [BlockHeaderBuffer, TransactionsBuffer, UncleHeadersBuffer, WithdrawalsBuffer]
export type BlockHeaderBuffer = Buffer[]
export type BlockBodyBuffer = [TransactionsBuffer, UncleHeadersBuffer, WithdrawalsBuffer?]
export type BlockBytes =
| [BlockHeaderBytes, TransactionsBytes, UncleHeadersBytes]
| [BlockHeaderBytes, TransactionsBytes, UncleHeadersBytes, WithdrawalsBytes]
export type BlockHeaderBytes = Uint8Array[]
export type BlockBodyBytes = [TransactionsBytes, UncleHeadersBytes, WithdrawalsBytes?]
/**
* TransactionsBuffer can be an array of serialized txs for Typed Transactions or an array of Buffer Arrays for legacy transactions.
* TransactionsBytes can be an array of serialized txs for Typed Transactions or an array of Uint8Array Arrays for legacy transactions.
*/
export type TransactionsBuffer = Buffer[][] | Buffer[]
export type UncleHeadersBuffer = Buffer[][]
export type TransactionsBytes = Uint8Array[][] | Uint8Array[]
export type UncleHeadersBytes = Uint8Array[][]

@@ -176,3 +166,5 @@ /**

withdrawalsRoot?: string
dataGasUsed?: string
excessDataGas?: string
parentBeaconBlockRoot?: string
}

@@ -207,3 +199,35 @@

withdrawalsRoot?: string // If EIP-4895 is enabled for this block, the root of the withdrawal trie of the block.
dataGasUsed?: string // If EIP-4844 is enabled for this block, returns the data gas used for the block
excessDataGas?: string // If EIP-4844 is enabled for this block, returns the excess data gas for the block
parentBeaconBlockRoot?: string // If EIP-4788 is enabled for this block, returns parent beacon block root
}
// Note: all these strings are 0x-prefixed
export type WithdrawalV1 = {
index: PrefixedHexString // Quantity, 8 Bytes
validatorIndex: PrefixedHexString // Quantity, 8 bytes
address: PrefixedHexString // DATA, 20 bytes
amount: PrefixedHexString // Quantity, 32 bytes
}
// Note: all these strings are 0x-prefixed
export type ExecutionPayload = {
parentHash: PrefixedHexString // DATA, 32 Bytes
feeRecipient: PrefixedHexString // DATA, 20 Bytes
stateRoot: PrefixedHexString // DATA, 32 Bytes
receiptsRoot: PrefixedHexString // DATA, 32 bytes
logsBloom: PrefixedHexString // DATA, 256 Bytes
prevRandao: PrefixedHexString // DATA, 32 Bytes
blockNumber: PrefixedHexString // QUANTITY, 64 Bits
gasLimit: PrefixedHexString // QUANTITY, 64 Bits
gasUsed: PrefixedHexString // QUANTITY, 64 Bits
timestamp: PrefixedHexString // QUANTITY, 64 Bits
extraData: PrefixedHexString // DATA, 0 to 32 Bytes
baseFeePerGas: PrefixedHexString // QUANTITY, 256 Bits
blockHash: PrefixedHexString // DATA, 32 Bytes
transactions: PrefixedHexString[] // Array of DATA - Array of transaction rlp strings,
withdrawals?: WithdrawalV1[] // Array of withdrawal objects
dataGasUsed?: PrefixedHexString // QUANTITY, 64 Bits
excessDataGas?: PrefixedHexString // QUANTITY, 64 Bits
parentBeaconBlockRoot?: PrefixedHexString // QUANTITY, 64 Bits
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc