Skip to content

Commit

Permalink
Merge branch 'master' into proof-function-util-helpers-refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
scorbajio committed Jul 30, 2024
2 parents ab24833 + def477a commit 81577fc
Show file tree
Hide file tree
Showing 41 changed files with 303 additions and 308 deletions.
8 changes: 5 additions & 3 deletions packages/block/examples/simple.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { BlockHeader } from '@ethereumjs/block'
import { createHeader } from '@ethereumjs/block'
import { bytesToHex } from '@ethereumjs/util'

const headerData = {
import type { HeaderData } from '@ethereumjs/block'

const headerData: HeaderData = {
number: 15,
parentHash: '0x6bfee7294bf44572b7266358e627f3c35105e1c3851f3de09e6d646f955725a7',
gasLimit: 8000000,
timestamp: 1562422144,
}
const header = BlockHeader.fromHeaderData(headerData)
const header = createHeader(headerData)
console.log(`Created block header with hash=${bytesToHex(header.hash())}`)
20 changes: 10 additions & 10 deletions packages/block/src/block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {
} from '@ethereumjs/util'
import { keccak256 } from 'ethereum-cryptography/keccak.js'

import { BlockHeader } from './header.js'
import { genRequestsTrieRoot, genTransactionsTrieRoot, genWithdrawalsTrieRoot } from './helpers.js'

/* eslint-disable */
Expand All @@ -21,14 +20,15 @@ import { genRequestsTrieRoot, genTransactionsTrieRoot, genWithdrawalsTrieRoot }
// TODO: See if there is an easier way to achieve the same result.
// See: https://github.com/microsoft/TypeScript/issues/47558
// (situation will eventually improve on Typescript and/or Eslint update)
import type {
createBlockFromBeaconPayloadJson,
createBlockFromBlockData,
createBlockFromExecutionPayload,
createBlockFromJsonRpcProvider,
createBlockFromRLPSerializedBlock,
createBlockFromRPC,
createBlockFromValuesArray,
import {
BlockHeader,
type createBlockFromBeaconPayloadJson,
type createBlockFromBlockData,
type createBlockFromExecutionPayload,
type createBlockFromJsonRpcProvider,
type createBlockFromRLPSerializedBlock,
type createBlockFromRPC,
type createBlockFromValuesArray,
} from './index.js'
/* eslint-enable */
import type { BlockBytes, BlockOptions, ExecutionPayload, JsonBlock } from './types.js'
Expand Down Expand Up @@ -100,7 +100,7 @@ export class Block {
requests?: CLRequest<CLRequestType>[],
executionWitness?: VerkleExecutionWitness | null,
) {
this.header = header ?? BlockHeader.fromHeaderData({}, opts)
this.header = header ?? new BlockHeader({}, opts)
this.common = this.header.common
this.keccakFunction = this.common.customCrypto.keccak256 ?? keccak256

Expand Down
78 changes: 73 additions & 5 deletions packages/block/src/constructors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
DepositRequest,
Withdrawal,
WithdrawalRequest,
bigIntToBytes,
bigIntToHex,
bytesToHex,
bytesToUtf8,
Expand All @@ -24,14 +25,20 @@ import {
} from '@ethereumjs/util'

import { createBlockFromRpc } from './from-rpc.js'
import { genRequestsTrieRoot, genTransactionsTrieRoot, genWithdrawalsTrieRoot } from './helpers.js'
import {
genRequestsTrieRoot,
genTransactionsTrieRoot,
genWithdrawalsTrieRoot,
valuesArrayToHeaderData,
} from './helpers.js'

import { Block, BlockHeader, executionPayloadFromBeaconPayload } from './index.js'

import type { BeaconPayloadJson } from './from-beacon-payload.js'
import type {
BlockBytes,
BlockData,
BlockHeaderBytes,
BlockOptions,
ExecutionPayload,
ExecutionWitnessBytes,
Expand All @@ -49,6 +56,67 @@ import type {
WithdrawalBytes,
} from '@ethereumjs/util'

/**
* Static constructor to create a block header from a header data dictionary
*
* @param headerData
* @param opts
*/
export function createHeader(headerData: HeaderData = {}, opts: BlockOptions = {}) {
return new BlockHeader(headerData, opts)
}

/**
* Static constructor to create a block header from an array of Bytes values
*
* @param values
* @param opts
*/
export function createHeaderFromValuesArray(values: BlockHeaderBytes, opts: BlockOptions = {}) {
const headerData = valuesArrayToHeaderData(values)
const { number, baseFeePerGas, excessBlobGas, blobGasUsed, parentBeaconBlockRoot, requestsRoot } =
headerData
const header = createHeader(headerData, opts)
if (header.common.isActivatedEIP(1559) && baseFeePerGas === undefined) {
const eip1559ActivationBlock = bigIntToBytes(header.common.eipBlock(1559)!)
if (
eip1559ActivationBlock !== undefined &&
equalsBytes(eip1559ActivationBlock, number as Uint8Array)
) {
throw new Error('invalid header. baseFeePerGas should be provided')
}
}
if (header.common.isActivatedEIP(4844)) {
if (excessBlobGas === undefined) {
throw new Error('invalid header. excessBlobGas should be provided')
} else if (blobGasUsed === undefined) {
throw new Error('invalid header. blobGasUsed should be provided')
}
}
if (header.common.isActivatedEIP(4788) && parentBeaconBlockRoot === undefined) {
throw new Error('invalid header. parentBeaconBlockRoot should be provided')
}

if (header.common.isActivatedEIP(7685) && requestsRoot === undefined) {
throw new Error('invalid header. requestsRoot should be provided')
}
return header
}

/**
* Static constructor to create a block header from a RLP-serialized header
*
* @param serializedHeaderData
* @param opts
*/
export function createHeaderFromRLP(serializedHeaderData: Uint8Array, opts: BlockOptions = {}) {
const values = RLP.decode(serializedHeaderData)
if (!Array.isArray(values)) {
throw new Error('Invalid serialized header input. Must be array')
}
return createHeaderFromValuesArray(values as Uint8Array[], opts)
}

/**
* Static constructor to create a block from a block data dictionary
*
Expand All @@ -65,7 +133,7 @@ export function createBlockFromBlockData(blockData: BlockData = {}, opts?: Block
requests: clRequests,
} = blockData

const header = BlockHeader.fromHeaderData(headerData, opts)
const header = createHeader(headerData, opts)

// parse transactions
const transactions = []
Expand All @@ -92,7 +160,7 @@ export function createBlockFromBlockData(blockData: BlockData = {}, opts?: Block
uncleOpts.setHardfork = true
}
for (const uhData of uhsData ?? []) {
const uh = BlockHeader.fromHeaderData(uhData, uncleOpts)
const uh = createHeader(uhData, uncleOpts)
uncleHeaders.push(uh)
}

Expand Down Expand Up @@ -126,7 +194,7 @@ export function createBlockFromValuesArray(values: BlockBytes, opts?: BlockOptio
// 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, ...valuesTail] = values
const header = BlockHeader.fromValuesArray(headerData, opts)
const header = createHeaderFromValuesArray(headerData, opts)

// conditional assignment of rest of values and splicing them out from the valuesTail
const withdrawalBytes = header.common.isActivatedEIP(4895)
Expand Down Expand Up @@ -191,7 +259,7 @@ export function createBlockFromValuesArray(values: BlockBytes, opts?: BlockOptio
uncleOpts.setHardfork = true
}
for (const uncleHeaderData of uhsData ?? []) {
uncleHeaders.push(BlockHeader.fromValuesArray(uncleHeaderData, uncleOpts))
uncleHeaders.push(createHeaderFromValuesArray(uncleHeaderData, uncleOpts))
}

const withdrawals = (withdrawalBytes as WithdrawalBytes[])
Expand Down
5 changes: 3 additions & 2 deletions packages/block/src/header-from-rpc.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { BlockHeader } from './header.js'
import { numberToHex } from './helpers.js'

import { BlockHeader } from './index.js'

import type { BlockOptions, JsonRpcBlock } from './types.js'

/**
Expand Down Expand Up @@ -34,7 +35,7 @@ export function blockHeaderFromRpc(blockParams: JsonRpcBlock, options?: BlockOpt
requestsRoot,
} = blockParams

const blockHeader = BlockHeader.fromHeaderData(
const blockHeader = new BlockHeader(
{
parentHash,
uncleHash: sha3Uncles,
Expand Down
70 changes: 2 additions & 68 deletions packages/block/src/header.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import {
import { keccak256 } from 'ethereum-cryptography/keccak.js'

import { CLIQUE_EXTRA_SEAL, CLIQUE_EXTRA_VANITY } from './clique.js'
import { fakeExponential, valuesArrayToHeaderData } from './helpers.js'
import { fakeExponential } from './helpers.js'
import { paramsBlock } from './params.js'

import type { BlockHeaderBytes, BlockOptions, HeaderData, JsonHeader } from './types.js'
Expand Down Expand Up @@ -89,77 +89,11 @@ export class BlockHeader {
return this.mixHash
}

/**
* Static constructor to create a block header from a header data dictionary
*
* @param headerData
* @param opts
*/
public static fromHeaderData(headerData: HeaderData = {}, opts: BlockOptions = {}) {
return new BlockHeader(headerData, opts)
}

/**
* Static constructor to create a block header from a RLP-serialized header
*
* @param serializedHeaderData
* @param opts
*/
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 Uint8Array[], opts)
}

/**
* Static constructor to create a block header from an array of Bytes values
*
* @param values
* @param opts
*/
public static fromValuesArray(values: BlockHeaderBytes, opts: BlockOptions = {}) {
const headerData = valuesArrayToHeaderData(values)
const {
number,
baseFeePerGas,
excessBlobGas,
blobGasUsed,
parentBeaconBlockRoot,
requestsRoot,
} = headerData
const header = BlockHeader.fromHeaderData(headerData, opts)
if (header.common.isActivatedEIP(1559) && baseFeePerGas === undefined) {
const eip1559ActivationBlock = bigIntToBytes(header.common.eipBlock(1559)!)
if (
eip1559ActivationBlock !== undefined &&
equalsBytes(eip1559ActivationBlock, number as Uint8Array)
) {
throw new Error('invalid header. baseFeePerGas should be provided')
}
}
if (header.common.isActivatedEIP(4844)) {
if (excessBlobGas === undefined) {
throw new Error('invalid header. excessBlobGas should be provided')
} else if (blobGasUsed === undefined) {
throw new Error('invalid header. blobGasUsed should be provided')
}
}
if (header.common.isActivatedEIP(4788) && parentBeaconBlockRoot === undefined) {
throw new Error('invalid header. parentBeaconBlockRoot should be provided')
}

if (header.common.isActivatedEIP(7685) && requestsRoot === undefined) {
throw new Error('invalid header. requestsRoot should be provided')
}
return header
}
/**
* This constructor takes the values, validates them, assigns them and freezes the object.
*
* @deprecated Use the public static factory methods to assist in creating a Header object from
* varying data types. For a default empty header, use {@link BlockHeader.fromHeaderData}.
* varying data types. For a default empty header, use {@link createHeader}.
*
*/
constructor(headerData: HeaderData, opts: BlockOptions = {}) {
Expand Down
17 changes: 7 additions & 10 deletions packages/block/test/clique.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common'
import { Address, createZeroAddress, hexToBytes } from '@ethereumjs/util'
import { assert, describe, it } from 'vitest'

import { BlockHeader } from '../src/header.js'
import { createHeader } from '../src/constructors.js'

describe('[Header]: Clique PoA Functionality', () => {
const common = new Common({ chain: Chain.Goerli, hardfork: Hardfork.Chainstart })

it('Header Data', () => {
let header = BlockHeader.fromHeaderData({ number: 1 })
let header = createHeader({ number: 1 })
assert.throws(
() => {
header.cliqueIsEpochTransition()
Expand All @@ -18,13 +18,13 @@ describe('[Header]: Clique PoA Functionality', () => {
'cliqueIsEpochTransition() -> should throw on PoW networks',
)

header = BlockHeader.fromHeaderData({ extraData: new Uint8Array(97) }, { common })
header = createHeader({ extraData: new Uint8Array(97) }, { common })
assert.ok(
header.cliqueIsEpochTransition(),
'cliqueIsEpochTransition() -> should indicate an epoch transition for the genesis block',
)

header = BlockHeader.fromHeaderData({ number: 1, extraData: new Uint8Array(97) }, { common })
header = createHeader({ number: 1, extraData: new Uint8Array(97) }, { common })
assert.notOk(
header.cliqueIsEpochTransition(),
'cliqueIsEpochTransition() -> should correctly identify a non-epoch block',
Expand All @@ -48,10 +48,7 @@ describe('[Header]: Clique PoA Functionality', () => {
'cliqueEpochTransitionSigners() -> should throw on non-epch block',
)

header = BlockHeader.fromHeaderData(
{ number: 60000, extraData: new Uint8Array(137) },
{ common },
)
header = createHeader({ number: 60000, extraData: new Uint8Array(137) }, { common })
assert.ok(
header.cliqueIsEpochTransition(),
'cliqueIsEpochTransition() -> should correctly identify an epoch block',
Expand Down Expand Up @@ -92,7 +89,7 @@ describe('[Header]: Clique PoA Functionality', () => {
it('Signing', () => {
const cliqueSigner = A.privateKey

let header = BlockHeader.fromHeaderData(
let header = createHeader(
{ number: 1, extraData: new Uint8Array(97) },
{ common, freeze: false, cliqueSigner },
)
Expand All @@ -101,7 +98,7 @@ describe('[Header]: Clique PoA Functionality', () => {
assert.ok(header.cliqueVerifySignature([A.address]), 'should verify signature')
assert.ok(header.cliqueSigner().equals(A.address), 'should recover the correct signer address')

header = BlockHeader.fromHeaderData({ extraData: new Uint8Array(97) }, { common })
header = createHeader({ extraData: new Uint8Array(97) }, { common })
assert.ok(
header.cliqueSigner().equals(createZeroAddress()),
'should return zero address on default block',
Expand Down
Loading

0 comments on commit 81577fc

Please sign in to comment.