From 8fd3556320e7291892e492847c8204a32e22dceb Mon Sep 17 00:00:00 2001 From: Amir Date: Wed, 7 Aug 2024 11:30:49 -0700 Subject: [PATCH 01/40] Move clique.ts into subdirectory --- packages/block/src/{ => consensus}/clique.ts | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/block/src/{ => consensus}/clique.ts (100%) diff --git a/packages/block/src/clique.ts b/packages/block/src/consensus/clique.ts similarity index 100% rename from packages/block/src/clique.ts rename to packages/block/src/consensus/clique.ts From 317ad18ffc807ab0f640c6e261e255b38380f1b2 Mon Sep 17 00:00:00 2001 From: Amir Date: Wed, 7 Aug 2024 11:31:28 -0700 Subject: [PATCH 02/40] Fix import --- packages/block/src/header.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block/src/header.ts b/packages/block/src/header.ts index 88830ab200..7fbffa0332 100644 --- a/packages/block/src/header.ts +++ b/packages/block/src/header.ts @@ -28,7 +28,7 @@ import { } from '@ethereumjs/util' import { keccak256 } from 'ethereum-cryptography/keccak.js' -import { CLIQUE_EXTRA_SEAL, CLIQUE_EXTRA_VANITY } from './clique.js' +import { CLIQUE_EXTRA_SEAL, CLIQUE_EXTRA_VANITY } from './index.js' import { fakeExponential } from './helpers.js' import { paramsBlock } from './params.js' From 84aece0bad48d799b8359b17de7b775af2ad72a2 Mon Sep 17 00:00:00 2001 From: Amir Date: Wed, 7 Aug 2024 11:54:07 -0700 Subject: [PATCH 03/40] Make ethashCanonicalDifficulty, _requireClique, and cliqueSigHash standalone functions --- packages/block/src/block.ts | 9 ------ packages/block/src/consensus/clique.ts | 23 +++++++++++++++ packages/block/src/consensus/ethash.ts | 10 +++++++ packages/block/src/consensus/index.ts | 2 ++ packages/block/src/header.ts | 39 +++++++------------------- packages/block/src/index.ts | 1 + 6 files changed, 46 insertions(+), 38 deletions(-) create mode 100644 packages/block/src/consensus/ethash.ts create mode 100644 packages/block/src/consensus/index.ts diff --git a/packages/block/src/block.ts b/packages/block/src/block.ts index 25848fa589..1c3cb22faf 100644 --- a/packages/block/src/block.ts +++ b/packages/block/src/block.ts @@ -507,15 +507,6 @@ export class Block { } } - /** - * Returns the canonical difficulty for this block. - * - * @param parentBlock - the parent of this `Block` - */ - ethashCanonicalDifficulty(parentBlock: Block): bigint { - return this.header.ethashCanonicalDifficulty(parentBlock.header) - } - /** * Validates if the block gasLimit remains in the boundaries set by the protocol. * Throws if invalid diff --git a/packages/block/src/consensus/clique.ts b/packages/block/src/consensus/clique.ts index 16f1edfcfc..5e7a0d98dd 100644 --- a/packages/block/src/consensus/clique.ts +++ b/packages/block/src/consensus/clique.ts @@ -1,4 +1,27 @@ +import { ConsensusAlgorithm } from '@ethereumjs/common' +import { BlockHeader } from '../index.js' +import { RLP } from '@ethereumjs/rlp' + // Fixed number of extra-data prefix bytes reserved for signer vanity export const CLIQUE_EXTRA_VANITY = 32 // Fixed number of extra-data suffix bytes reserved for signer seal export const CLIQUE_EXTRA_SEAL = 65 + +export function _requireClique(header: BlockHeader, name: string) { + if (header.common.consensusAlgorithm() !== ConsensusAlgorithm.Clique) { + const msg = header['_errorMsg']( + `BlockHeader.${name}() call only supported for clique PoA networks`, + ) + throw new Error(msg) + } +} + +/** + * PoA clique signature hash without the seal. + */ +export function cliqueSigHash(header: BlockHeader) { + _requireClique(header, 'cliqueSigHash') + const raw = header.raw() + raw[12] = header.extraData.subarray(0, header.extraData.length - CLIQUE_EXTRA_SEAL) + return header['keccakFunction'](RLP.encode(raw)) +} diff --git a/packages/block/src/consensus/ethash.ts b/packages/block/src/consensus/ethash.ts new file mode 100644 index 0000000000..d1af2a2131 --- /dev/null +++ b/packages/block/src/consensus/ethash.ts @@ -0,0 +1,10 @@ +import { Block } from '../index.js' + +/** + * Returns the canonical difficulty for this block. + * + * @param parentBlock - the parent of this `Block` + */ +export function ethashCanonicalDifficulty(block: Block, parentBlock: Block): bigint { + return block.header.ethashCanonicalDifficulty(parentBlock.header) +} diff --git a/packages/block/src/consensus/index.ts b/packages/block/src/consensus/index.ts new file mode 100644 index 0000000000..ddbdeaccd0 --- /dev/null +++ b/packages/block/src/consensus/index.ts @@ -0,0 +1,2 @@ +export { CLIQUE_EXTRA_SEAL, CLIQUE_EXTRA_VANITY, cliqueSigHash } from './clique.js' +export * from './ethash.js' diff --git a/packages/block/src/header.ts b/packages/block/src/header.ts index 7fbffa0332..6148a432da 100644 --- a/packages/block/src/header.ts +++ b/packages/block/src/header.ts @@ -28,7 +28,7 @@ import { } from '@ethereumjs/util' import { keccak256 } from 'ethereum-cryptography/keccak.js' -import { CLIQUE_EXTRA_SEAL, CLIQUE_EXTRA_VANITY } from './index.js' +import { CLIQUE_EXTRA_SEAL, CLIQUE_EXTRA_VANITY, _requireClique, cliqueSigHash } from './index.js' import { fakeExponential } from './helpers.js' import { paramsBlock } from './params.js' @@ -669,15 +669,6 @@ export class BlockHeader { return this.number === BIGINT_0 } - protected _requireClique(name: string) { - if (this.common.consensusAlgorithm() !== ConsensusAlgorithm.Clique) { - const msg = this._errorMsg( - `BlockHeader.${name}() call only supported for clique PoA networks`, - ) - throw new Error(msg) - } - } - /** * Returns the canonical difficulty for this block. * @@ -751,22 +742,12 @@ export class BlockHeader { return dif } - /** - * PoA clique signature hash without the seal. - */ - cliqueSigHash() { - this._requireClique('cliqueSigHash') - const raw = this.raw() - raw[12] = this.extraData.subarray(0, this.extraData.length - CLIQUE_EXTRA_SEAL) - return this.keccakFunction(RLP.encode(raw)) - } - /** * Checks if the block header is an epoch transition * header (only clique PoA, throws otherwise) */ cliqueIsEpochTransition(): boolean { - this._requireClique('cliqueIsEpochTransition') + _requireClique(this, 'cliqueIsEpochTransition') const epoch = BigInt((this.common.consensusConfig() as CliqueConfig).epoch) // Epoch transition block if the block number has no // remainder on the division by the epoch length @@ -778,7 +759,7 @@ export class BlockHeader { * (only clique PoA, throws otherwise) */ cliqueExtraVanity(): Uint8Array { - this._requireClique('cliqueExtraVanity') + _requireClique(this, 'cliqueExtraVanity') return this.extraData.subarray(0, CLIQUE_EXTRA_VANITY) } @@ -787,7 +768,7 @@ export class BlockHeader { * (only clique PoA, throws otherwise) */ cliqueExtraSeal(): Uint8Array { - this._requireClique('cliqueExtraSeal') + _requireClique(this, 'cliqueExtraSeal') return this.extraData.subarray(-CLIQUE_EXTRA_SEAL) } @@ -797,10 +778,10 @@ export class BlockHeader { * @hidden */ private cliqueSealBlock(privateKey: Uint8Array) { - this._requireClique('cliqueSealBlock') + _requireClique(this, 'cliqueSealBlock') const ecSignFunction = this.common.customCrypto?.ecsign ?? ecsign - const signature = ecSignFunction(this.cliqueSigHash(), privateKey) + const signature = ecSignFunction(cliqueSigHash(this), privateKey) const signatureB = concatBytes(signature.r, signature.s, bigIntToBytes(signature.v - BIGINT_27)) const extraDataWithoutSeal = this.extraData.subarray( @@ -820,7 +801,7 @@ export class BlockHeader { * in conjunction with {@link BlockHeader.cliqueIsEpochTransition} */ cliqueEpochTransitionSigners(): Address[] { - this._requireClique('cliqueEpochTransitionSigners') + _requireClique(this, 'cliqueEpochTransitionSigners') if (!this.cliqueIsEpochTransition()) { const msg = this._errorMsg('Signers are only included in epoch transition blocks (clique)') throw new Error(msg) @@ -845,7 +826,7 @@ export class BlockHeader { * Method throws if signature is invalid */ cliqueVerifySignature(signerList: Address[]): boolean { - this._requireClique('cliqueVerifySignature') + _requireClique(this, 'cliqueVerifySignature') const signerAddress = this.cliqueSigner() const signerFound = signerList.find((signer) => { return signer.equals(signerAddress) @@ -857,7 +838,7 @@ export class BlockHeader { * Returns the signer address */ cliqueSigner(): Address { - this._requireClique('cliqueSigner') + _requireClique(this, 'cliqueSigner') const extraSeal = this.cliqueExtraSeal() // Reasonable default for default blocks if (extraSeal.length === 0 || equalsBytes(extraSeal, new Uint8Array(65))) { @@ -866,7 +847,7 @@ export class BlockHeader { 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) + const pubKey = ecrecover(cliqueSigHash(this), v, r, s) return createAddressFromPublicKey(pubKey) } diff --git a/packages/block/src/index.ts b/packages/block/src/index.ts index c1a94abb64..98e56cce7e 100644 --- a/packages/block/src/index.ts +++ b/packages/block/src/index.ts @@ -11,3 +11,4 @@ export { } from './helpers.js' export * from './params.js' export * from './types.js' +export * from './consensus/index.js' From 6e67e931fb065c9261fa5710fdb695286547f350 Mon Sep 17 00:00:00 2001 From: Amir Date: Wed, 7 Aug 2024 11:57:55 -0700 Subject: [PATCH 04/40] Make cliqueIsEpochTransition a standalone function --- packages/block/src/consensus/clique.ts | 15 ++++++++++++++- packages/block/src/consensus/index.ts | 7 ++++++- packages/block/src/header.ts | 24 +++++++++--------------- 3 files changed, 29 insertions(+), 17 deletions(-) diff --git a/packages/block/src/consensus/clique.ts b/packages/block/src/consensus/clique.ts index 5e7a0d98dd..0cdd4a5399 100644 --- a/packages/block/src/consensus/clique.ts +++ b/packages/block/src/consensus/clique.ts @@ -1,6 +1,7 @@ -import { ConsensusAlgorithm } from '@ethereumjs/common' +import { CliqueConfig, ConsensusAlgorithm } from '@ethereumjs/common' import { BlockHeader } from '../index.js' import { RLP } from '@ethereumjs/rlp' +import { BIGINT_0 } from '@ethereumjs/util' // Fixed number of extra-data prefix bytes reserved for signer vanity export const CLIQUE_EXTRA_VANITY = 32 @@ -25,3 +26,15 @@ export function cliqueSigHash(header: BlockHeader) { raw[12] = header.extraData.subarray(0, header.extraData.length - CLIQUE_EXTRA_SEAL) return header['keccakFunction'](RLP.encode(raw)) } + +/** + * Checks if the block header is an epoch transition + * header (only clique PoA, throws otherwise) + */ +export function cliqueIsEpochTransition(header: BlockHeader): boolean { + _requireClique(header, 'cliqueIsEpochTransition') + const epoch = BigInt((header.common.consensusConfig() as CliqueConfig).epoch) + // Epoch transition block if the block number has no + // remainder on the division by the epoch length + return header.number % epoch === BIGINT_0 +} diff --git a/packages/block/src/consensus/index.ts b/packages/block/src/consensus/index.ts index ddbdeaccd0..2c37e2af55 100644 --- a/packages/block/src/consensus/index.ts +++ b/packages/block/src/consensus/index.ts @@ -1,2 +1,7 @@ -export { CLIQUE_EXTRA_SEAL, CLIQUE_EXTRA_VANITY, cliqueSigHash } from './clique.js' +export { + CLIQUE_EXTRA_SEAL, + CLIQUE_EXTRA_VANITY, + cliqueSigHash, + cliqueIsEpochTransition, +} from './clique.js' export * from './ethash.js' diff --git a/packages/block/src/header.ts b/packages/block/src/header.ts index 6148a432da..0ff916412f 100644 --- a/packages/block/src/header.ts +++ b/packages/block/src/header.ts @@ -28,7 +28,13 @@ import { } from '@ethereumjs/util' import { keccak256 } from 'ethereum-cryptography/keccak.js' -import { CLIQUE_EXTRA_SEAL, CLIQUE_EXTRA_VANITY, _requireClique, cliqueSigHash } from './index.js' +import { _requireClique } from './consensus/clique.js' +import { + CLIQUE_EXTRA_SEAL, + CLIQUE_EXTRA_VANITY, + cliqueSigHash, + cliqueIsEpochTransition, +} from './index.js' import { fakeExponential } from './helpers.js' import { paramsBlock } from './params.js' @@ -387,7 +393,7 @@ export class BlockHeader { if (this.common.consensusAlgorithm() === ConsensusAlgorithm.Clique) { // PoA/Clique const minLength = CLIQUE_EXTRA_VANITY + CLIQUE_EXTRA_SEAL - if (!this.cliqueIsEpochTransition()) { + if (!cliqueIsEpochTransition(this)) { // ExtraData length on epoch transition if (this.extraData.length !== minLength) { const msg = this._errorMsg( @@ -742,18 +748,6 @@ export class BlockHeader { return dif } - /** - * Checks if the block header is an epoch transition - * header (only clique PoA, throws otherwise) - */ - cliqueIsEpochTransition(): boolean { - _requireClique(this, 'cliqueIsEpochTransition') - const epoch = BigInt((this.common.consensusConfig() as CliqueConfig).epoch) - // Epoch transition block if the block number has no - // remainder on the division by the epoch length - return this.number % epoch === BIGINT_0 - } - /** * Returns extra vanity data * (only clique PoA, throws otherwise) @@ -802,7 +796,7 @@ export class BlockHeader { */ cliqueEpochTransitionSigners(): Address[] { _requireClique(this, 'cliqueEpochTransitionSigners') - if (!this.cliqueIsEpochTransition()) { + if (!cliqueIsEpochTransition(this)) { const msg = this._errorMsg('Signers are only included in epoch transition blocks (clique)') throw new Error(msg) } From 22460a4986d4775ee1cddd0ed9b438aaa0cfe1d9 Mon Sep 17 00:00:00 2001 From: Amir Date: Wed, 7 Aug 2024 11:58:28 -0700 Subject: [PATCH 05/40] Remove unused import --- packages/block/src/header.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/block/src/header.ts b/packages/block/src/header.ts index 0ff916412f..fdd16c479f 100644 --- a/packages/block/src/header.ts +++ b/packages/block/src/header.ts @@ -39,7 +39,6 @@ import { fakeExponential } from './helpers.js' import { paramsBlock } from './params.js' import type { BlockHeaderBytes, BlockOptions, HeaderData, JsonHeader } from './types.js' -import type { CliqueConfig } from '@ethereumjs/common' interface HeaderCache { hash: Uint8Array | undefined From b73dfb5a952b3eb99e3075710e4d489316d871d7 Mon Sep 17 00:00:00 2001 From: Amir Date: Wed, 7 Aug 2024 12:03:30 -0700 Subject: [PATCH 06/40] Make cliqueExtraVanity a standalone function and cleanup --- packages/block/src/consensus/clique.ts | 10 ++++++++++ packages/block/src/consensus/index.ts | 1 + packages/block/src/header.ts | 9 --------- packages/block/test/clique.spec.ts | 13 +++++++------ packages/blockchain/src/consensus/clique.ts | 6 +++--- 5 files changed, 21 insertions(+), 18 deletions(-) diff --git a/packages/block/src/consensus/clique.ts b/packages/block/src/consensus/clique.ts index 0cdd4a5399..46aaf515f0 100644 --- a/packages/block/src/consensus/clique.ts +++ b/packages/block/src/consensus/clique.ts @@ -8,6 +8,7 @@ export const CLIQUE_EXTRA_VANITY = 32 // Fixed number of extra-data suffix bytes reserved for signer seal export const CLIQUE_EXTRA_SEAL = 65 +// This function is not exported in the index file to keep it internal export function _requireClique(header: BlockHeader, name: string) { if (header.common.consensusAlgorithm() !== ConsensusAlgorithm.Clique) { const msg = header['_errorMsg']( @@ -38,3 +39,12 @@ export function cliqueIsEpochTransition(header: BlockHeader): boolean { // remainder on the division by the epoch length return header.number % epoch === BIGINT_0 } + +/** + * Returns extra vanity data + * (only clique PoA, throws otherwise) + */ +export function cliqueExtraVanity(header: BlockHeader): Uint8Array { + _requireClique(header, 'cliqueExtraVanity') + return header.extraData.subarray(0, CLIQUE_EXTRA_VANITY) +} diff --git a/packages/block/src/consensus/index.ts b/packages/block/src/consensus/index.ts index 2c37e2af55..fee58ad34e 100644 --- a/packages/block/src/consensus/index.ts +++ b/packages/block/src/consensus/index.ts @@ -3,5 +3,6 @@ export { CLIQUE_EXTRA_VANITY, cliqueSigHash, cliqueIsEpochTransition, + cliqueExtraVanity, } from './clique.js' export * from './ethash.js' diff --git a/packages/block/src/header.ts b/packages/block/src/header.ts index fdd16c479f..9baafa35c2 100644 --- a/packages/block/src/header.ts +++ b/packages/block/src/header.ts @@ -747,15 +747,6 @@ export class BlockHeader { return dif } - /** - * Returns extra vanity data - * (only clique PoA, throws otherwise) - */ - cliqueExtraVanity(): Uint8Array { - _requireClique(this, 'cliqueExtraVanity') - return this.extraData.subarray(0, CLIQUE_EXTRA_VANITY) - } - /** * Returns extra seal data * (only clique PoA, throws otherwise) diff --git a/packages/block/test/clique.spec.ts b/packages/block/test/clique.spec.ts index e7af1e298a..32295f54c9 100644 --- a/packages/block/test/clique.spec.ts +++ b/packages/block/test/clique.spec.ts @@ -3,6 +3,7 @@ import { Address, createZeroAddress, hexToBytes } from '@ethereumjs/util' import { assert, describe, it } from 'vitest' import { createBlockHeader } from '../src/constructors.js' +import { cliqueExtraVanity, cliqueIsEpochTransition } from '../src/index.js' describe('[Header]: Clique PoA Functionality', () => { const common = new Common({ chain: Goerli, hardfork: Hardfork.Chainstart }) @@ -11,7 +12,7 @@ describe('[Header]: Clique PoA Functionality', () => { let header = createBlockHeader({ number: 1 }) assert.throws( () => { - header.cliqueIsEpochTransition() + cliqueIsEpochTransition(header) }, undefined, undefined, @@ -20,17 +21,17 @@ describe('[Header]: Clique PoA Functionality', () => { header = createBlockHeader({ extraData: new Uint8Array(97) }, { common }) assert.ok( - header.cliqueIsEpochTransition(), + cliqueIsEpochTransition(header), 'cliqueIsEpochTransition() -> should indicate an epoch transition for the genesis block', ) header = createBlockHeader({ number: 1, extraData: new Uint8Array(97) }, { common }) assert.notOk( - header.cliqueIsEpochTransition(), + cliqueIsEpochTransition(header), 'cliqueIsEpochTransition() -> should correctly identify a non-epoch block', ) assert.deepEqual( - header.cliqueExtraVanity(), + cliqueExtraVanity(header), new Uint8Array(32), 'cliqueExtraVanity() -> should return correct extra vanity value', ) @@ -50,11 +51,11 @@ describe('[Header]: Clique PoA Functionality', () => { header = createBlockHeader({ number: 60000, extraData: new Uint8Array(137) }, { common }) assert.ok( - header.cliqueIsEpochTransition(), + cliqueIsEpochTransition(header), 'cliqueIsEpochTransition() -> should correctly identify an epoch block', ) assert.deepEqual( - header.cliqueExtraVanity(), + cliqueExtraVanity(header), new Uint8Array(32), 'cliqueExtraVanity() -> should return correct extra vanity value', ) diff --git a/packages/blockchain/src/consensus/clique.ts b/packages/blockchain/src/consensus/clique.ts index 8d8a163142..d30dda9241 100644 --- a/packages/blockchain/src/consensus/clique.ts +++ b/packages/blockchain/src/consensus/clique.ts @@ -16,7 +16,7 @@ import debugDefault from 'debug' import type { Blockchain } from '../index.js' import type { Consensus, ConsensusOptions } from '../types.js' -import type { Block, BlockHeader } from '@ethereumjs/block' +import type { Block, BlockHeader, cliqueIsEpochTransition } from '@ethereumjs/block' import type { CliqueConfig } from '@ethereumjs/common' const debug = debugDefault('blockchain:clique') @@ -145,7 +145,7 @@ export class CliqueConsensus implements Consensus { } // validate checkpoint signers towards active signers on epoch transition blocks - if (header.cliqueIsEpochTransition()) { + if (cliqueIsEpochTransition(header)) { // note: keep votes on epoch transition blocks in case of reorgs. // only active (non-stale) votes will counted (if vote.blockNumber >= lastEpochBlockNumber @@ -587,7 +587,7 @@ export class CliqueConsensus implements Consensus { * @hidden */ private async _cliqueBuildSnapshots(header: BlockHeader) { - if (!header.cliqueIsEpochTransition()) { + if (!cliqueIsEpochTransition(header)) { await this.cliqueUpdateVotes(header) } await this.cliqueUpdateLatestBlockSigners(header) From 5f4dfe6747551f06671a274fd03656a74ad424c7 Mon Sep 17 00:00:00 2001 From: Amir Date: Wed, 7 Aug 2024 12:11:30 -0700 Subject: [PATCH 07/40] Make cliqueExtraSeal a standalone function --- packages/block/src/consensus/clique.ts | 9 +++++++++ packages/block/src/consensus/index.ts | 1 + packages/block/src/header.ts | 12 ++---------- packages/block/test/clique.spec.ts | 6 +++--- packages/blockchain/src/consensus/clique.ts | 3 ++- 5 files changed, 17 insertions(+), 14 deletions(-) diff --git a/packages/block/src/consensus/clique.ts b/packages/block/src/consensus/clique.ts index 46aaf515f0..c50ef91b60 100644 --- a/packages/block/src/consensus/clique.ts +++ b/packages/block/src/consensus/clique.ts @@ -48,3 +48,12 @@ export function cliqueExtraVanity(header: BlockHeader): Uint8Array { _requireClique(header, 'cliqueExtraVanity') return header.extraData.subarray(0, CLIQUE_EXTRA_VANITY) } + +/** + * Returns extra seal data + * (only clique PoA, throws otherwise) + */ +export function cliqueExtraSeal(header: BlockHeader): Uint8Array { + _requireClique(header, 'cliqueExtraSeal') + return header.extraData.subarray(-CLIQUE_EXTRA_SEAL) +} diff --git a/packages/block/src/consensus/index.ts b/packages/block/src/consensus/index.ts index fee58ad34e..3a0b11c58b 100644 --- a/packages/block/src/consensus/index.ts +++ b/packages/block/src/consensus/index.ts @@ -4,5 +4,6 @@ export { cliqueSigHash, cliqueIsEpochTransition, cliqueExtraVanity, + cliqueExtraSeal, } from './clique.js' export * from './ethash.js' diff --git a/packages/block/src/header.ts b/packages/block/src/header.ts index 9baafa35c2..ee8adc0b75 100644 --- a/packages/block/src/header.ts +++ b/packages/block/src/header.ts @@ -34,6 +34,7 @@ import { CLIQUE_EXTRA_VANITY, cliqueSigHash, cliqueIsEpochTransition, + cliqueExtraSeal, } from './index.js' import { fakeExponential } from './helpers.js' import { paramsBlock } from './params.js' @@ -747,15 +748,6 @@ export class BlockHeader { return dif } - /** - * Returns extra seal data - * (only clique PoA, throws otherwise) - */ - cliqueExtraSeal(): Uint8Array { - _requireClique(this, 'cliqueExtraSeal') - return this.extraData.subarray(-CLIQUE_EXTRA_SEAL) - } - /** * Seal block with the provided signer. * Returns the final extraData field to be assigned to `this.extraData`. @@ -823,7 +815,7 @@ export class BlockHeader { */ cliqueSigner(): Address { _requireClique(this, 'cliqueSigner') - const extraSeal = this.cliqueExtraSeal() + const extraSeal = cliqueExtraSeal(this) // Reasonable default for default blocks if (extraSeal.length === 0 || equalsBytes(extraSeal, new Uint8Array(65))) { return createZeroAddress() diff --git a/packages/block/test/clique.spec.ts b/packages/block/test/clique.spec.ts index 32295f54c9..4d98a30a2c 100644 --- a/packages/block/test/clique.spec.ts +++ b/packages/block/test/clique.spec.ts @@ -3,7 +3,7 @@ import { Address, createZeroAddress, hexToBytes } from '@ethereumjs/util' import { assert, describe, it } from 'vitest' import { createBlockHeader } from '../src/constructors.js' -import { cliqueExtraVanity, cliqueIsEpochTransition } from '../src/index.js' +import { cliqueExtraSeal, cliqueExtraVanity, cliqueIsEpochTransition } from '../src/index.js' describe('[Header]: Clique PoA Functionality', () => { const common = new Common({ chain: Goerli, hardfork: Hardfork.Chainstart }) @@ -36,7 +36,7 @@ describe('[Header]: Clique PoA Functionality', () => { 'cliqueExtraVanity() -> should return correct extra vanity value', ) assert.deepEqual( - header.cliqueExtraSeal(), + cliqueExtraSeal(header), new Uint8Array(65), 'cliqueExtraSeal() -> should return correct extra seal value', ) @@ -60,7 +60,7 @@ describe('[Header]: Clique PoA Functionality', () => { 'cliqueExtraVanity() -> should return correct extra vanity value', ) assert.deepEqual( - header.cliqueExtraSeal(), + cliqueExtraSeal(header), new Uint8Array(65), 'cliqueExtraSeal() -> should return correct extra seal value', ) diff --git a/packages/blockchain/src/consensus/clique.ts b/packages/blockchain/src/consensus/clique.ts index d30dda9241..67e8582e74 100644 --- a/packages/blockchain/src/consensus/clique.ts +++ b/packages/blockchain/src/consensus/clique.ts @@ -1,3 +1,4 @@ +import { cliqueIsEpochTransition } from '@ethereumjs/block' import { ConsensusAlgorithm } from '@ethereumjs/common' import { RLP } from '@ethereumjs/rlp' import { @@ -16,7 +17,7 @@ import debugDefault from 'debug' import type { Blockchain } from '../index.js' import type { Consensus, ConsensusOptions } from '../types.js' -import type { Block, BlockHeader, cliqueIsEpochTransition } from '@ethereumjs/block' +import type { Block, BlockHeader } from '@ethereumjs/block' import type { CliqueConfig } from '@ethereumjs/common' const debug = debugDefault('blockchain:clique') From 32dfad548a90fca4d4119f4915dd2ccb95285400 Mon Sep 17 00:00:00 2001 From: Amir Date: Wed, 7 Aug 2024 12:17:14 -0700 Subject: [PATCH 08/40] Make cliqueEpochTransitionSigners a standalone function --- packages/block/src/consensus/clique.ts | 28 +++++++++++++++++++++ packages/block/src/consensus/index.ts | 1 + packages/block/src/header.ts | 27 -------------------- packages/block/test/clique.spec.ts | 11 +++++--- packages/blockchain/src/consensus/clique.ts | 6 ++--- packages/blockchain/test/clique.spec.ts | 4 +-- 6 files changed, 42 insertions(+), 35 deletions(-) diff --git a/packages/block/src/consensus/clique.ts b/packages/block/src/consensus/clique.ts index c50ef91b60..750898507b 100644 --- a/packages/block/src/consensus/clique.ts +++ b/packages/block/src/consensus/clique.ts @@ -2,6 +2,7 @@ import { CliqueConfig, ConsensusAlgorithm } from '@ethereumjs/common' import { BlockHeader } from '../index.js' import { RLP } from '@ethereumjs/rlp' import { BIGINT_0 } from '@ethereumjs/util' +import { Address } from '@ethereumjs/util' // Fixed number of extra-data prefix bytes reserved for signer vanity export const CLIQUE_EXTRA_VANITY = 32 @@ -57,3 +58,30 @@ export function cliqueExtraSeal(header: BlockHeader): Uint8Array { _requireClique(header, 'cliqueExtraSeal') return header.extraData.subarray(-CLIQUE_EXTRA_SEAL) } + +/** + * Returns a list of signers + * (only clique PoA, throws otherwise) + * + * This function throws if not called on an epoch + * transition block and should therefore be used + * in conjunction with {@link BlockHeader.cliqueIsEpochTransition} + */ +export function cliqueEpochTransitionSigners(header: BlockHeader): Address[] { + _requireClique(header, 'cliqueEpochTransitionSigners') + if (!cliqueIsEpochTransition(header)) { + const msg = header['_errorMsg']('Signers are only included in epoch transition blocks (clique)') + throw new Error(msg) + } + + const start = CLIQUE_EXTRA_VANITY + const end = header.extraData.length - CLIQUE_EXTRA_SEAL + const signerBytes = header.extraData.subarray(start, end) + + const signerList: Uint8Array[] = [] + const signerLength = 20 + for (let start = 0; start <= signerBytes.length - signerLength; start += signerLength) { + signerList.push(signerBytes.subarray(start, start + signerLength)) + } + return signerList.map((buf) => new Address(buf)) +} diff --git a/packages/block/src/consensus/index.ts b/packages/block/src/consensus/index.ts index 3a0b11c58b..fece08ac17 100644 --- a/packages/block/src/consensus/index.ts +++ b/packages/block/src/consensus/index.ts @@ -5,5 +5,6 @@ export { cliqueIsEpochTransition, cliqueExtraVanity, cliqueExtraSeal, + cliqueEpochTransitionSigners, } from './clique.js' export * from './ethash.js' diff --git a/packages/block/src/header.ts b/packages/block/src/header.ts index ee8adc0b75..bf321af510 100644 --- a/packages/block/src/header.ts +++ b/packages/block/src/header.ts @@ -768,33 +768,6 @@ export class BlockHeader { return extraData } - /** - * Returns a list of signers - * (only clique PoA, throws otherwise) - * - * This function throws if not called on an epoch - * transition block and should therefore be used - * in conjunction with {@link BlockHeader.cliqueIsEpochTransition} - */ - cliqueEpochTransitionSigners(): Address[] { - _requireClique(this, 'cliqueEpochTransitionSigners') - if (!cliqueIsEpochTransition(this)) { - const msg = this._errorMsg('Signers are only included in epoch transition blocks (clique)') - throw new Error(msg) - } - - const start = CLIQUE_EXTRA_VANITY - const end = this.extraData.length - CLIQUE_EXTRA_SEAL - const signerBytes = this.extraData.subarray(start, end) - - const signerList: Uint8Array[] = [] - const signerLength = 20 - for (let start = 0; start <= signerBytes.length - signerLength; start += signerLength) { - signerList.push(signerBytes.subarray(start, start + signerLength)) - } - return signerList.map((buf) => new Address(buf)) - } - /** * Verifies the signature of the block (last 65 bytes of extraData field) * (only clique PoA, throws otherwise) diff --git a/packages/block/test/clique.spec.ts b/packages/block/test/clique.spec.ts index 4d98a30a2c..a0408e99ed 100644 --- a/packages/block/test/clique.spec.ts +++ b/packages/block/test/clique.spec.ts @@ -3,7 +3,12 @@ import { Address, createZeroAddress, hexToBytes } from '@ethereumjs/util' import { assert, describe, it } from 'vitest' import { createBlockHeader } from '../src/constructors.js' -import { cliqueExtraSeal, cliqueExtraVanity, cliqueIsEpochTransition } from '../src/index.js' +import { + cliqueEpochTransitionSigners, + cliqueExtraSeal, + cliqueExtraVanity, + cliqueIsEpochTransition, +} from '../src/index.js' describe('[Header]: Clique PoA Functionality', () => { const common = new Common({ chain: Goerli, hardfork: Hardfork.Chainstart }) @@ -42,7 +47,7 @@ describe('[Header]: Clique PoA Functionality', () => { ) assert.throws( () => { - header.cliqueEpochTransitionSigners() + cliqueEpochTransitionSigners(header) }, undefined, undefined, @@ -67,7 +72,7 @@ describe('[Header]: Clique PoA Functionality', () => { const msg = 'cliqueEpochTransitionSigners() -> should return the correct epoch transition signer list on epoch block' assert.deepEqual( - header.cliqueEpochTransitionSigners(), + cliqueEpochTransitionSigners(header), [createZeroAddress(), createZeroAddress()], msg, ) diff --git a/packages/blockchain/src/consensus/clique.ts b/packages/blockchain/src/consensus/clique.ts index 67e8582e74..cde6fd24fd 100644 --- a/packages/blockchain/src/consensus/clique.ts +++ b/packages/blockchain/src/consensus/clique.ts @@ -1,4 +1,4 @@ -import { cliqueIsEpochTransition } from '@ethereumjs/block' +import { cliqueIsEpochTransition, cliqueEpochTransitionSigners } from '@ethereumjs/block' import { ConsensusAlgorithm } from '@ethereumjs/common' import { RLP } from '@ethereumjs/rlp' import { @@ -150,7 +150,7 @@ export class CliqueConsensus implements Consensus { // note: keep votes on epoch transition blocks in case of reorgs. // only active (non-stale) votes will counted (if vote.blockNumber >= lastEpochBlockNumber - const checkpointSigners = header.cliqueEpochTransitionSigners() + const checkpointSigners = cliqueEpochTransitionSigners(header) const activeSigners = this.cliqueActiveSigners(header.number) for (const [i, cSigner] of checkpointSigners.entries()) { if (activeSigners[i]?.equals(cSigner) !== true) { @@ -212,7 +212,7 @@ export class CliqueConsensus implements Consensus { private async cliqueSaveGenesisSigners(genesisBlock: Block) { const genesisSignerState: CliqueSignerState = [ BIGINT_0, - genesisBlock.header.cliqueEpochTransitionSigners(), + cliqueEpochTransitionSigners(genesisBlock.header), ] await this.cliqueUpdateSignerStates(genesisSignerState) debug(`[Block 0] Genesis block -> update signer states`) diff --git a/packages/blockchain/test/clique.spec.ts b/packages/blockchain/test/clique.spec.ts index 3248be5ca5..0e0bfa2a2f 100644 --- a/packages/blockchain/test/clique.spec.ts +++ b/packages/blockchain/test/clique.spec.ts @@ -1,4 +1,4 @@ -import { createBlock } from '@ethereumjs/block' +import { createBlock, cliqueEpochTransitionSigners } from '@ethereumjs/block' import { Common, ConsensusAlgorithm, @@ -206,7 +206,7 @@ describe('Clique: Initialization', () => { assert.deepEqual( (blockchain.consensus as CliqueConsensus).cliqueActiveSigners(head.header.number + BigInt(1)), - head.header.cliqueEpochTransitionSigners(), + cliqueEpochTransitionSigners(head.header), 'correct genesis signers', ) }) From ba0284abe710410fe37b532b529710047b57dd22 Mon Sep 17 00:00:00 2001 From: Amir Date: Wed, 7 Aug 2024 13:12:52 -0700 Subject: [PATCH 09/40] Make cliqueVerifySignature and cliqueSigner standalone functions --- packages/block/src/consensus/clique.ts | 38 +++++++++++++++++++++ packages/block/src/consensus/index.ts | 2 ++ packages/block/src/header.ts | 32 ----------------- packages/block/test/clique.spec.ts | 12 ++++--- packages/blockchain/src/consensus/clique.ts | 19 +++++++---- packages/blockchain/test/reorg.spec.ts | 8 ++--- packages/evm/src/evm.ts | 1 - packages/evm/src/interpreter.ts | 4 ++- packages/evm/src/types.ts | 1 - packages/vm/src/runTx.ts | 4 +-- packages/vm/test/api/buildBlock.spec.ts | 12 +++---- 11 files changed, 74 insertions(+), 59 deletions(-) diff --git a/packages/block/src/consensus/clique.ts b/packages/block/src/consensus/clique.ts index 750898507b..3a18b90d85 100644 --- a/packages/block/src/consensus/clique.ts +++ b/packages/block/src/consensus/clique.ts @@ -3,6 +3,12 @@ import { BlockHeader } from '../index.js' import { RLP } from '@ethereumjs/rlp' import { BIGINT_0 } from '@ethereumjs/util' import { Address } from '@ethereumjs/util' +import { equalsBytes } from '@ethereumjs/util' +import { createZeroAddress } from '@ethereumjs/util' +import { bytesToBigInt } from '@ethereumjs/util' +import { ecrecover } from '@ethereumjs/util' +import { BIGINT_27 } from '@ethereumjs/util' +import { createAddressFromPublicKey } from '@ethereumjs/util' // Fixed number of extra-data prefix bytes reserved for signer vanity export const CLIQUE_EXTRA_VANITY = 32 @@ -85,3 +91,35 @@ export function cliqueEpochTransitionSigners(header: BlockHeader): Address[] { } return signerList.map((buf) => new Address(buf)) } + +/** + * Verifies the signature of the block (last 65 bytes of extraData field) + * (only clique PoA, throws otherwise) + * + * Method throws if signature is invalid + */ +export function cliqueVerifySignature(header: BlockHeader, signerList: Address[]): boolean { + _requireClique(header, 'cliqueVerifySignature') + const signerAddress = cliqueSigner(header) + const signerFound = signerList.find((signer) => { + return signer.equals(signerAddress) + }) + return !!signerFound +} + +/** + * Returns the signer address + */ +export function cliqueSigner(header: BlockHeader): Address { + _requireClique(header, 'cliqueSigner') + const extraSeal = cliqueExtraSeal(header) + // Reasonable default for default blocks + if (extraSeal.length === 0 || equalsBytes(extraSeal, new Uint8Array(65))) { + return createZeroAddress() + } + const r = extraSeal.subarray(0, 32) + const s = extraSeal.subarray(32, 64) + const v = bytesToBigInt(extraSeal.subarray(64, 65)) + BIGINT_27 + const pubKey = ecrecover(cliqueSigHash(header), v, r, s) + return createAddressFromPublicKey(pubKey) +} diff --git a/packages/block/src/consensus/index.ts b/packages/block/src/consensus/index.ts index fece08ac17..10067fb9b4 100644 --- a/packages/block/src/consensus/index.ts +++ b/packages/block/src/consensus/index.ts @@ -6,5 +6,7 @@ export { cliqueExtraVanity, cliqueExtraSeal, cliqueEpochTransitionSigners, + cliqueVerifySignature, + cliqueSigner, } from './clique.js' export * from './ethash.js' diff --git a/packages/block/src/header.ts b/packages/block/src/header.ts index bf321af510..9412ae307b 100644 --- a/packages/block/src/header.ts +++ b/packages/block/src/header.ts @@ -768,38 +768,6 @@ export class BlockHeader { return extraData } - /** - * Verifies the signature of the block (last 65 bytes of extraData field) - * (only clique PoA, throws otherwise) - * - * Method throws if signature is invalid - */ - cliqueVerifySignature(signerList: Address[]): boolean { - _requireClique(this, 'cliqueVerifySignature') - const signerAddress = this.cliqueSigner() - const signerFound = signerList.find((signer) => { - return signer.equals(signerAddress) - }) - return !!signerFound - } - - /** - * Returns the signer address - */ - cliqueSigner(): Address { - _requireClique(this, 'cliqueSigner') - const extraSeal = cliqueExtraSeal(this) - // Reasonable default for default blocks - if (extraSeal.length === 0 || equalsBytes(extraSeal, new Uint8Array(65))) { - return createZeroAddress() - } - const r = extraSeal.subarray(0, 32) - const s = extraSeal.subarray(32, 64) - const v = bytesToBigInt(extraSeal.subarray(64, 65)) + BIGINT_27 - const pubKey = ecrecover(cliqueSigHash(this), v, r, s) - return createAddressFromPublicKey(pubKey) - } - /** * Returns the rlp encoding of the block header. */ diff --git a/packages/block/test/clique.spec.ts b/packages/block/test/clique.spec.ts index a0408e99ed..b2d8cb7ca0 100644 --- a/packages/block/test/clique.spec.ts +++ b/packages/block/test/clique.spec.ts @@ -1,3 +1,4 @@ +import { cliqueSigner } from '../src/index.js' import { Common, Goerli, Hardfork } from '@ethereumjs/common' import { Address, createZeroAddress, hexToBytes } from '@ethereumjs/util' import { assert, describe, it } from 'vitest' @@ -8,6 +9,7 @@ import { cliqueExtraSeal, cliqueExtraVanity, cliqueIsEpochTransition, + cliqueVerifySignature, } from '../src/index.js' describe('[Header]: Clique PoA Functionality', () => { @@ -93,20 +95,20 @@ describe('[Header]: Clique PoA Functionality', () => { } it('Signing', () => { - const cliqueSigner = A.privateKey + const cliqueSignerKey = A.privateKey let header = createBlockHeader( { number: 1, extraData: new Uint8Array(97) }, - { common, freeze: false, cliqueSigner }, + { common, freeze: false, cliqueSigner: cliqueSignerKey }, ) assert.equal(header.extraData.length, 97) - assert.ok(header.cliqueVerifySignature([A.address]), 'should verify signature') - assert.ok(header.cliqueSigner().equals(A.address), 'should recover the correct signer address') + assert.ok(cliqueVerifySignature(header, [A.address]), 'should verify signature') + assert.ok(cliqueSigner(header).equals(A.address), 'should recover the correct signer address') header = createBlockHeader({ extraData: new Uint8Array(97) }, { common }) assert.ok( - header.cliqueSigner().equals(createZeroAddress()), + cliqueSigner(header).equals(createZeroAddress()), 'should return zero address on default block', ) }) diff --git a/packages/blockchain/src/consensus/clique.ts b/packages/blockchain/src/consensus/clique.ts index cde6fd24fd..e1a941c982 100644 --- a/packages/blockchain/src/consensus/clique.ts +++ b/packages/blockchain/src/consensus/clique.ts @@ -1,4 +1,9 @@ -import { cliqueIsEpochTransition, cliqueEpochTransitionSigners } from '@ethereumjs/block' +import { + cliqueIsEpochTransition, + cliqueEpochTransitionSigners, + cliqueVerifySignature, + cliqueSigner, +} from '@ethereumjs/block' import { ConsensusAlgorithm } from '@ethereumjs/common' import { RLP } from '@ethereumjs/rlp' import { @@ -137,7 +142,7 @@ export class CliqueConsensus implements Consensus { } const { header } = block - const valid = header.cliqueVerifySignature(this.cliqueActiveSigners(header.number)) + const valid = cliqueVerifySignature(header, this.cliqueActiveSigners(header.number)) if (!valid) { throw new Error('invalid PoA block signature (clique)') } @@ -179,7 +184,7 @@ export class CliqueConsensus implements Consensus { throw new Error(`${msg} ${header.errorStr()}`) } const signerIndex = signers.findIndex((address: Address) => - address.equals(header.cliqueSigner()), + address.equals(cliqueSigner(header)), ) const inTurn = header.number % BigInt(signers.length) === BigInt(signerIndex) if ( @@ -281,7 +286,7 @@ export class CliqueConsensus implements Consensus { private async cliqueUpdateVotes(header?: BlockHeader) { // Block contains a vote on a new signer if (header && !header.coinbase.isZero()) { - const signer = header.cliqueSigner() + const signer = cliqueSigner(header) const beneficiary = header.coinbase const nonce = header.nonce const latestVote: CliqueVote = [header.number, [signer, beneficiary, nonce]] @@ -470,8 +475,8 @@ export class CliqueConsensus implements Consensus { // we do not have a complete picture of the state to verify if too recently signed return false } - signers.push([header.number, header.cliqueSigner()]) - const seen = signers.filter((s) => s[1].equals(header.cliqueSigner())).length + signers.push([header.number, cliqueSigner(header)]) + const seen = signers.filter((s) => s[1].equals(cliqueSigner(header))).length return seen > 1 } @@ -510,7 +515,7 @@ export class CliqueConsensus implements Consensus { return } // add this block's signer - const signer: CliqueBlockSigner = [header.number, header.cliqueSigner()] + const signer: CliqueBlockSigner = [header.number, cliqueSigner(header)] this._cliqueLatestBlockSigners.push(signer) // trim length to `this.cliqueSignerLimit()` diff --git a/packages/blockchain/test/reorg.spec.ts b/packages/blockchain/test/reorg.spec.ts index 855725d6c1..a142d446b9 100644 --- a/packages/blockchain/test/reorg.spec.ts +++ b/packages/blockchain/test/reorg.spec.ts @@ -1,4 +1,4 @@ -import { createBlock } from '@ethereumjs/block' +import { createBlock, cliqueSigner } from '@ethereumjs/block' import { Common, ConsensusAlgorithm, Goerli, Hardfork, Mainnet } from '@ethereumjs/common' import { Address, equalsBytes, hexToBytes } from '@ethereumjs/util' import { assert, describe, it } from 'vitest' @@ -168,7 +168,7 @@ describe('reorg tests', () => { !signerVotes.find( (v: any) => v[0] === BigInt(2) && - v[1][0].equal(block1_low.header.cliqueSigner()) && + v[1][0].equal(cliqueSigner(block1_low.header)) && v[1][1].equal(beneficiary1) && equalsBytes(v[1][2], CLIQUE_NONCE_AUTH), ), @@ -178,7 +178,7 @@ describe('reorg tests', () => { let blockSigners = (blockchain.consensus as CliqueConsensus)._cliqueLatestBlockSigners assert.ok( !blockSigners.find( - (s: any) => s[0] === BigInt(1) && s[1].equal(block1_low.header.cliqueSigner()), + (s: any) => s[0] === BigInt(1) && s[1].equal(cliqueSigner(block1_low.header)), ), 'should not find reorged block signer', ) @@ -197,7 +197,7 @@ describe('reorg tests', () => { blockSigners = (blockchain.consensus as CliqueConsensus)._cliqueLatestBlockSigners assert.ok( !!blockSigners.find( - (s: any) => s[0] === BigInt(3) && s[1].equals(block3_high.header.cliqueSigner()), + (s: any) => s[0] === BigInt(3) && s[1].equals(cliqueSigner(block3_high.header)), ), 'should find reorged block signer', ) diff --git a/packages/evm/src/evm.ts b/packages/evm/src/evm.ts index 093339bd10..4cf02c1333 100644 --- a/packages/evm/src/evm.ts +++ b/packages/evm/src/evm.ts @@ -1149,7 +1149,6 @@ export function defaultBlock(): Block { return { header: { number: BIGINT_0, - cliqueSigner: () => createZeroAddress(), coinbase: createZeroAddress(), timestamp: BIGINT_0, difficulty: BIGINT_0, diff --git a/packages/evm/src/interpreter.ts b/packages/evm/src/interpreter.ts index ea3332427c..6166d7c8a0 100644 --- a/packages/evm/src/interpreter.ts +++ b/packages/evm/src/interpreter.ts @@ -1,3 +1,4 @@ +import { cliqueSigner, BlockHeader } from '@ethereumjs/block' import { ConsensusAlgorithm } from '@ethereumjs/common' import { Account, @@ -27,6 +28,7 @@ import type { EVM } from './evm.js' import type { Journal } from './journal.js' import type { AsyncOpHandler, Opcode, OpcodeMapEntry } from './opcodes/index.js' import type { Block, Blockchain, EOFEnv, EVMProfilerOpts, EVMResult, Log } from './types.js' +// import type { BlockHeader } from '@etherumjs/block' import type { AccessWitnessInterface, Common, StateManagerInterface } from '@ethereumjs/common' import type { Address, PrefixedHexString } from '@ethereumjs/util' @@ -781,7 +783,7 @@ export class Interpreter { getBlockCoinbase(): bigint { let coinbase: Address if (this.common.consensusAlgorithm() === ConsensusAlgorithm.Clique) { - coinbase = this._env.block.header.cliqueSigner() + coinbase = cliqueSigner(this._env.block.header as any) } else { coinbase = this._env.block.header.coinbase } diff --git a/packages/evm/src/types.ts b/packages/evm/src/types.ts index 109b79129d..3233f0a770 100644 --- a/packages/evm/src/types.ts +++ b/packages/evm/src/types.ts @@ -403,7 +403,6 @@ export type Log = [address: Uint8Array, topics: Uint8Array[], data: Uint8Array] export type Block = { header: { number: bigint - cliqueSigner(): Address coinbase: Address timestamp: bigint difficulty: bigint diff --git a/packages/vm/src/runTx.ts b/packages/vm/src/runTx.ts index 8da4658a25..d64f31957b 100644 --- a/packages/vm/src/runTx.ts +++ b/packages/vm/src/runTx.ts @@ -1,4 +1,4 @@ -import { createBlock } from '@ethereumjs/block' +import { createBlock, cliqueSigner } from '@ethereumjs/block' import { ConsensusType, Hardfork } from '@ethereumjs/common' import { RLP } from '@ethereumjs/rlp' import { StatelessVerkleStateManager } from '@ethereumjs/statemanager' @@ -587,7 +587,7 @@ async function _runTx(vm: VM, opts: RunTxOpts): Promise { // Update miner's balance let miner if (vm.common.consensusType() === ConsensusType.ProofOfAuthority) { - miner = block.header.cliqueSigner() + miner = cliqueSigner(block.header) } else { miner = block.header.coinbase } diff --git a/packages/vm/test/api/buildBlock.spec.ts b/packages/vm/test/api/buildBlock.spec.ts index 2cb480d1c1..39bd70e5c8 100644 --- a/packages/vm/test/api/buildBlock.spec.ts +++ b/packages/vm/test/api/buildBlock.spec.ts @@ -1,4 +1,4 @@ -import { createBlock } from '@ethereumjs/block' +import { createBlock, cliqueVerifySignature, cliqueSigner } from '@ethereumjs/block' import { EthashConsensus, createBlockchain } from '@ethereumjs/blockchain' import { Common, @@ -198,10 +198,10 @@ describe('BlockBuilder', () => { // extraData: [vanity, activeSigner, seal] const extraData = concatBytes(new Uint8Array(32), signer.address.toBytes(), new Uint8Array(65)) - const cliqueSigner = signer.privateKey + const cliqueSignerKey = signer.privateKey const genesisBlock = createBlock( { header: { gasLimit: 50000, extraData } }, - { common, cliqueSigner }, + { common, cliqueSigner: cliqueSignerKey }, ) const blockchain = await createBlockchain({ genesisBlock, common }) const vm = await VM.create({ common, blockchain }) @@ -212,7 +212,7 @@ describe('BlockBuilder', () => { const blockBuilder = await buildBlock(vm, { parentBlock: genesisBlock, headerData: { difficulty: 2, extraData: new Uint8Array(97) }, - blockOpts: { cliqueSigner, freeze: false }, + blockOpts: { cliqueSigner: cliqueSignerKey, freeze: false }, }) // Set up tx @@ -225,9 +225,9 @@ describe('BlockBuilder', () => { const block = await blockBuilder.build() - assert.ok(block.header.cliqueVerifySignature([signer.address]), 'should verify signature') + assert.ok(cliqueVerifySignature(block.header, [signer.address]), 'should verify signature') assert.deepEqual( - block.header.cliqueSigner(), + cliqueSigner(block.header), signer.address, 'should recover the correct signer address', ) From 37fea1f53b84c89e6488b106f36826f1052be915 Mon Sep 17 00:00:00 2001 From: Amir Date: Wed, 7 Aug 2024 13:16:37 -0700 Subject: [PATCH 10/40] Fix linting issues --- packages/block/src/consensus/clique.ts | 54 +++++++++++---------- packages/block/src/consensus/ethash.ts | 2 +- packages/block/src/consensus/index.ts | 10 ++-- packages/block/src/header.ts | 11 ++--- packages/block/src/index.ts | 2 +- packages/block/test/clique.spec.ts | 2 +- packages/blockchain/src/consensus/clique.ts | 4 +- packages/blockchain/test/clique.spec.ts | 2 +- packages/blockchain/test/reorg.spec.ts | 2 +- 9 files changed, 45 insertions(+), 44 deletions(-) diff --git a/packages/block/src/consensus/clique.ts b/packages/block/src/consensus/clique.ts index 3a18b90d85..f140545f8d 100644 --- a/packages/block/src/consensus/clique.ts +++ b/packages/block/src/consensus/clique.ts @@ -1,14 +1,18 @@ -import { CliqueConfig, ConsensusAlgorithm } from '@ethereumjs/common' -import { BlockHeader } from '../index.js' +import { ConsensusAlgorithm } from '@ethereumjs/common' import { RLP } from '@ethereumjs/rlp' -import { BIGINT_0 } from '@ethereumjs/util' -import { Address } from '@ethereumjs/util' -import { equalsBytes } from '@ethereumjs/util' -import { createZeroAddress } from '@ethereumjs/util' -import { bytesToBigInt } from '@ethereumjs/util' -import { ecrecover } from '@ethereumjs/util' -import { BIGINT_27 } from '@ethereumjs/util' -import { createAddressFromPublicKey } from '@ethereumjs/util' +import { + Address, + BIGINT_0, + BIGINT_27, + bytesToBigInt, + createAddressFromPublicKey, + createZeroAddress, + ecrecover, + equalsBytes, +} from '@ethereumjs/util' + +import type { BlockHeader } from '../index.js' +import type { CliqueConfig } from '@ethereumjs/common' // Fixed number of extra-data prefix bytes reserved for signer vanity export const CLIQUE_EXTRA_VANITY = 32 @@ -92,21 +96,6 @@ export function cliqueEpochTransitionSigners(header: BlockHeader): Address[] { return signerList.map((buf) => new Address(buf)) } -/** - * Verifies the signature of the block (last 65 bytes of extraData field) - * (only clique PoA, throws otherwise) - * - * Method throws if signature is invalid - */ -export function cliqueVerifySignature(header: BlockHeader, signerList: Address[]): boolean { - _requireClique(header, 'cliqueVerifySignature') - const signerAddress = cliqueSigner(header) - const signerFound = signerList.find((signer) => { - return signer.equals(signerAddress) - }) - return !!signerFound -} - /** * Returns the signer address */ @@ -123,3 +112,18 @@ export function cliqueSigner(header: BlockHeader): Address { const pubKey = ecrecover(cliqueSigHash(header), v, r, s) return createAddressFromPublicKey(pubKey) } + +/** + * Verifies the signature of the block (last 65 bytes of extraData field) + * (only clique PoA, throws otherwise) + * + * Method throws if signature is invalid + */ +export function cliqueVerifySignature(header: BlockHeader, signerList: Address[]): boolean { + _requireClique(header, 'cliqueVerifySignature') + const signerAddress = cliqueSigner(header) + const signerFound = signerList.find((signer) => { + return signer.equals(signerAddress) + }) + return !!signerFound +} diff --git a/packages/block/src/consensus/ethash.ts b/packages/block/src/consensus/ethash.ts index d1af2a2131..fec0b0378a 100644 --- a/packages/block/src/consensus/ethash.ts +++ b/packages/block/src/consensus/ethash.ts @@ -1,4 +1,4 @@ -import { Block } from '../index.js' +import type { Block } from '../index.js' /** * Returns the canonical difficulty for this block. diff --git a/packages/block/src/consensus/index.ts b/packages/block/src/consensus/index.ts index 10067fb9b4..dd60522000 100644 --- a/packages/block/src/consensus/index.ts +++ b/packages/block/src/consensus/index.ts @@ -1,12 +1,12 @@ export { CLIQUE_EXTRA_SEAL, CLIQUE_EXTRA_VANITY, - cliqueSigHash, - cliqueIsEpochTransition, - cliqueExtraVanity, - cliqueExtraSeal, cliqueEpochTransitionSigners, - cliqueVerifySignature, + cliqueExtraSeal, + cliqueExtraVanity, + cliqueIsEpochTransition, + cliqueSigHash, cliqueSigner, + cliqueVerifySignature, } from './clique.js' export * from './ethash.js' diff --git a/packages/block/src/header.ts b/packages/block/src/header.ts index 9412ae307b..7dfc9c5ebc 100644 --- a/packages/block/src/header.ts +++ b/packages/block/src/header.ts @@ -13,13 +13,10 @@ import { bigIntToBytes, bigIntToHex, bigIntToUnpaddedBytes, - bytesToBigInt, bytesToHex, bytesToUtf8, concatBytes, - createAddressFromPublicKey, createZeroAddress, - ecrecover, ecsign, equalsBytes, hexToBytes, @@ -29,15 +26,15 @@ import { import { keccak256 } from 'ethereum-cryptography/keccak.js' import { _requireClique } from './consensus/clique.js' +import { fakeExponential } from './helpers.js' +import { paramsBlock } from './params.js' + import { CLIQUE_EXTRA_SEAL, CLIQUE_EXTRA_VANITY, - cliqueSigHash, cliqueIsEpochTransition, - cliqueExtraSeal, + cliqueSigHash, } from './index.js' -import { fakeExponential } from './helpers.js' -import { paramsBlock } from './params.js' import type { BlockHeaderBytes, BlockOptions, HeaderData, JsonHeader } from './types.js' diff --git a/packages/block/src/index.ts b/packages/block/src/index.ts index 98e56cce7e..4ea497e515 100644 --- a/packages/block/src/index.ts +++ b/packages/block/src/index.ts @@ -1,4 +1,5 @@ export { Block } from './block.js' +export * from './consensus/index.js' export * from './constructors.js' export { type BeaconPayloadJson, executionPayloadFromBeaconPayload } from './from-beacon-payload.js' export { BlockHeader } from './header.js' @@ -11,4 +12,3 @@ export { } from './helpers.js' export * from './params.js' export * from './types.js' -export * from './consensus/index.js' diff --git a/packages/block/test/clique.spec.ts b/packages/block/test/clique.spec.ts index b2d8cb7ca0..db24821fad 100644 --- a/packages/block/test/clique.spec.ts +++ b/packages/block/test/clique.spec.ts @@ -1,4 +1,3 @@ -import { cliqueSigner } from '../src/index.js' import { Common, Goerli, Hardfork } from '@ethereumjs/common' import { Address, createZeroAddress, hexToBytes } from '@ethereumjs/util' import { assert, describe, it } from 'vitest' @@ -9,6 +8,7 @@ import { cliqueExtraSeal, cliqueExtraVanity, cliqueIsEpochTransition, + cliqueSigner, cliqueVerifySignature, } from '../src/index.js' diff --git a/packages/blockchain/src/consensus/clique.ts b/packages/blockchain/src/consensus/clique.ts index e1a941c982..dc7af67ea9 100644 --- a/packages/blockchain/src/consensus/clique.ts +++ b/packages/blockchain/src/consensus/clique.ts @@ -1,8 +1,8 @@ import { - cliqueIsEpochTransition, cliqueEpochTransitionSigners, - cliqueVerifySignature, + cliqueIsEpochTransition, cliqueSigner, + cliqueVerifySignature, } from '@ethereumjs/block' import { ConsensusAlgorithm } from '@ethereumjs/common' import { RLP } from '@ethereumjs/rlp' diff --git a/packages/blockchain/test/clique.spec.ts b/packages/blockchain/test/clique.spec.ts index 0e0bfa2a2f..0ebcb47654 100644 --- a/packages/blockchain/test/clique.spec.ts +++ b/packages/blockchain/test/clique.spec.ts @@ -1,4 +1,4 @@ -import { createBlock, cliqueEpochTransitionSigners } from '@ethereumjs/block' +import { cliqueEpochTransitionSigners, createBlock } from '@ethereumjs/block' import { Common, ConsensusAlgorithm, diff --git a/packages/blockchain/test/reorg.spec.ts b/packages/blockchain/test/reorg.spec.ts index a142d446b9..19382953b9 100644 --- a/packages/blockchain/test/reorg.spec.ts +++ b/packages/blockchain/test/reorg.spec.ts @@ -1,4 +1,4 @@ -import { createBlock, cliqueSigner } from '@ethereumjs/block' +import { cliqueSigner, createBlock } from '@ethereumjs/block' import { Common, ConsensusAlgorithm, Goerli, Hardfork, Mainnet } from '@ethereumjs/common' import { Address, equalsBytes, hexToBytes } from '@ethereumjs/util' import { assert, describe, it } from 'vitest' From eddfb1d9baa21ba24aeba0c0439d1032544c1f6b Mon Sep 17 00:00:00 2001 From: Amir Date: Wed, 7 Aug 2024 13:25:12 -0700 Subject: [PATCH 11/40] Fix test --- packages/block/test/difficulty.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block/test/difficulty.spec.ts b/packages/block/test/difficulty.spec.ts index 95c9ec2e6d..a9b18e0768 100644 --- a/packages/block/test/difficulty.spec.ts +++ b/packages/block/test/difficulty.spec.ts @@ -13,10 +13,10 @@ import * as difficultyGrayGlacier from '../../ethereum-tests/DifficultyTests/dfG import * as difficultyHomestead from '../../ethereum-tests/DifficultyTests/dfHomestead/difficultyHomestead.json' import { createBlock } from '../src/constructors.js' -import type { Block } from '../src/index.js' +import { ethashCanonicalDifficulty, type Block } from '../src/index.js' function runDifficultyTests(test: any, parentBlock: Block, block: Block, msg: string) { - const dif = block.ethashCanonicalDifficulty(parentBlock) + const dif = ethashCanonicalDifficulty(block, parentBlock) assert.equal(dif, BigInt(test.currentDifficulty), `test ethashCanonicalDifficulty: ${msg}`) } From 7dc74a01b34288208d7b793df5caf8bb4682255f Mon Sep 17 00:00:00 2001 From: Amir Date: Wed, 7 Aug 2024 13:31:22 -0700 Subject: [PATCH 12/40] Remove unused import --- packages/evm/src/interpreter.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/evm/src/interpreter.ts b/packages/evm/src/interpreter.ts index 6166d7c8a0..69a400aa53 100644 --- a/packages/evm/src/interpreter.ts +++ b/packages/evm/src/interpreter.ts @@ -1,4 +1,4 @@ -import { cliqueSigner, BlockHeader } from '@ethereumjs/block' +import { cliqueSigner } from '@ethereumjs/block' import { ConsensusAlgorithm } from '@ethereumjs/common' import { Account, @@ -28,7 +28,6 @@ import type { EVM } from './evm.js' import type { Journal } from './journal.js' import type { AsyncOpHandler, Opcode, OpcodeMapEntry } from './opcodes/index.js' import type { Block, Blockchain, EOFEnv, EVMProfilerOpts, EVMResult, Log } from './types.js' -// import type { BlockHeader } from '@etherumjs/block' import type { AccessWitnessInterface, Common, StateManagerInterface } from '@ethereumjs/common' import type { Address, PrefixedHexString } from '@ethereumjs/util' From ef51a5560ecfccb0565c9f1e5f02fce3c73cbbf5 Mon Sep 17 00:00:00 2001 From: Amir Date: Wed, 7 Aug 2024 13:31:44 -0700 Subject: [PATCH 13/40] Update package and package-lock files --- package-lock.json | 1 + packages/evm/package.json | 1 + 2 files changed, 2 insertions(+) diff --git a/package-lock.json b/package-lock.json index 2cc6aea911..fd2cf78351 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16829,6 +16829,7 @@ "version": "3.0.0", "license": "MPL-2.0", "dependencies": { + "@ethereumjs/block": "^5.2.0", "@ethereumjs/common": "^4.3.0", "@ethereumjs/statemanager": "^2.3.0", "@ethereumjs/tx": "^5.3.0", diff --git a/packages/evm/package.json b/packages/evm/package.json index b136324d2d..e8b639ca30 100644 --- a/packages/evm/package.json +++ b/packages/evm/package.json @@ -56,6 +56,7 @@ "visualize:bundle": "npx vite build --config=./vite.config.bundler.ts --emptyOutDir=false --outDir ." }, "dependencies": { + "@ethereumjs/block": "^5.2.0", "@ethereumjs/common": "^4.3.0", "@ethereumjs/statemanager": "^2.3.0", "@ethereumjs/tx": "^5.3.0", From 50ab7e4a1d82e79cf2a940b8ca5ee4f71ac8a731 Mon Sep 17 00:00:00 2001 From: Amir Date: Wed, 7 Aug 2024 13:33:09 -0700 Subject: [PATCH 14/40] Fix lint issues --- packages/vm/src/runTx.ts | 2 +- packages/vm/test/api/buildBlock.spec.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/vm/src/runTx.ts b/packages/vm/src/runTx.ts index d64f31957b..1fd8317084 100644 --- a/packages/vm/src/runTx.ts +++ b/packages/vm/src/runTx.ts @@ -1,4 +1,4 @@ -import { createBlock, cliqueSigner } from '@ethereumjs/block' +import { cliqueSigner, createBlock } from '@ethereumjs/block' import { ConsensusType, Hardfork } from '@ethereumjs/common' import { RLP } from '@ethereumjs/rlp' import { StatelessVerkleStateManager } from '@ethereumjs/statemanager' diff --git a/packages/vm/test/api/buildBlock.spec.ts b/packages/vm/test/api/buildBlock.spec.ts index 39bd70e5c8..643e38c676 100644 --- a/packages/vm/test/api/buildBlock.spec.ts +++ b/packages/vm/test/api/buildBlock.spec.ts @@ -1,4 +1,4 @@ -import { createBlock, cliqueVerifySignature, cliqueSigner } from '@ethereumjs/block' +import { cliqueSigner, cliqueVerifySignature, createBlock } from '@ethereumjs/block' import { EthashConsensus, createBlockchain } from '@ethereumjs/blockchain' import { Common, From c8f4fc11ffcf6bb579f8f604ca5507cb15e7d857 Mon Sep 17 00:00:00 2001 From: Amir Date: Wed, 7 Aug 2024 13:40:02 -0700 Subject: [PATCH 15/40] Fix linting issue --- packages/block/test/difficulty.spec.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/block/test/difficulty.spec.ts b/packages/block/test/difficulty.spec.ts index a9b18e0768..40fcb27512 100644 --- a/packages/block/test/difficulty.spec.ts +++ b/packages/block/test/difficulty.spec.ts @@ -12,8 +12,7 @@ import * as difficultyFrontier from '../../ethereum-tests/DifficultyTests/dfFron import * as difficultyGrayGlacier from '../../ethereum-tests/DifficultyTests/dfGrayGlacier/difficultyGrayGlacier.json' import * as difficultyHomestead from '../../ethereum-tests/DifficultyTests/dfHomestead/difficultyHomestead.json' import { createBlock } from '../src/constructors.js' - -import { ethashCanonicalDifficulty, type Block } from '../src/index.js' +import { type Block, ethashCanonicalDifficulty } from '../src/index.js' function runDifficultyTests(test: any, parentBlock: Block, block: Block, msg: string) { const dif = ethashCanonicalDifficulty(block, parentBlock) From 41ffe667f6d5247f7e1ed39522bb22d6babb57f5 Mon Sep 17 00:00:00 2001 From: Amir Date: Thu, 8 Aug 2024 11:07:10 -0700 Subject: [PATCH 16/40] Remove block dependency and pass in cliqueSigner as option to evm --- package-lock.json | 1 - packages/evm/package.json | 1 - packages/evm/src/interpreter.ts | 12 ++++++++++-- packages/evm/src/types.ts | 5 +++++ 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index fea1c640b1..f60e95c3e6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16829,7 +16829,6 @@ "version": "3.0.0", "license": "MPL-2.0", "dependencies": { - "@ethereumjs/block": "^5.2.0", "@ethereumjs/common": "^4.3.0", "@ethereumjs/statemanager": "^2.3.0", "@ethereumjs/tx": "^5.3.0", diff --git a/packages/evm/package.json b/packages/evm/package.json index fa12303f5b..a6cc3f5d97 100644 --- a/packages/evm/package.json +++ b/packages/evm/package.json @@ -56,7 +56,6 @@ "visualize:bundle": "npx vite build --config=./vite.config.bundler.ts --emptyOutDir=false --outDir ." }, "dependencies": { - "@ethereumjs/block": "^5.2.0", "@ethereumjs/common": "^4.3.0", "@ethereumjs/statemanager": "^2.3.0", "@ethereumjs/tx": "^5.3.0", diff --git a/packages/evm/src/interpreter.ts b/packages/evm/src/interpreter.ts index 69a400aa53..30266d8b62 100644 --- a/packages/evm/src/interpreter.ts +++ b/packages/evm/src/interpreter.ts @@ -1,4 +1,3 @@ -import { cliqueSigner } from '@ethereumjs/block' import { ConsensusAlgorithm } from '@ethereumjs/common' import { Account, @@ -159,6 +158,15 @@ export class Interpreter { this._evm = evm this._stateManager = stateManager this.common = this._evm.common + + if ( + this.common.consensusType() === 'poa' && + this._evm['_optsCached'].cliqueSigner === undefined + ) + throw new Error( + 'Must include cliqueSigner function if clique/poa is being used for consensus type', + ) + this._runState = { programCounter: 0, opCode: 0xfe, // INVALID opcode @@ -782,7 +790,7 @@ export class Interpreter { getBlockCoinbase(): bigint { let coinbase: Address if (this.common.consensusAlgorithm() === ConsensusAlgorithm.Clique) { - coinbase = cliqueSigner(this._env.block.header as any) + coinbase = this._evm['_optsCached'].cliqueSigner!(this._env.block.header as any) } else { coinbase = this._env.block.header.coinbase } diff --git a/packages/evm/src/types.ts b/packages/evm/src/types.ts index 3ba4dc9253..7ecd0a27d7 100644 --- a/packages/evm/src/types.ts +++ b/packages/evm/src/types.ts @@ -346,6 +346,11 @@ export interface EVMOpts { * */ profiler?: EVMProfilerOpts + + /** + * Must be present if consensus type is clique/poa, else error will be thrown + */ + cliqueSigner?: Function } /** From c7dea5702cad850b03c3a797fe82195210dd0002 Mon Sep 17 00:00:00 2001 From: Amir Date: Thu, 8 Aug 2024 11:58:42 -0700 Subject: [PATCH 17/40] Add more typing for cliqueSigner option --- packages/evm/src/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/evm/src/types.ts b/packages/evm/src/types.ts index 7ecd0a27d7..9f899c641f 100644 --- a/packages/evm/src/types.ts +++ b/packages/evm/src/types.ts @@ -350,7 +350,7 @@ export interface EVMOpts { /** * Must be present if consensus type is clique/poa, else error will be thrown */ - cliqueSigner?: Function + cliqueSigner?: (header: any) => Address } /** From 05a84b5b6ee92c8000a8f3f49b9a536a954da89c Mon Sep 17 00:00:00 2001 From: Amir Date: Thu, 8 Aug 2024 13:41:51 -0700 Subject: [PATCH 18/40] Move cliqueSealBlock functionality into standalone constructor function --- packages/block/src/constructors.ts | 41 +++++++++++++++++++++++++++++- packages/block/src/header.ts | 37 ++------------------------- 2 files changed, 42 insertions(+), 36 deletions(-) diff --git a/packages/block/src/constructors.ts b/packages/block/src/constructors.ts index c6a413cb6e..bf3dd48f47 100644 --- a/packages/block/src/constructors.ts +++ b/packages/block/src/constructors.ts @@ -7,6 +7,7 @@ import { createTxFromTxData, } from '@ethereumjs/tx' import { + BIGINT_27, CLRequestFactory, ConsolidationRequest, DepositRequest, @@ -16,6 +17,8 @@ import { bigIntToHex, bytesToHex, bytesToUtf8, + concatBytes, + ecsign, equalsBytes, fetchFromProvider, getProvider, @@ -24,6 +27,7 @@ import { isHexString, } from '@ethereumjs/util' +import { _requireClique } from './consensus/clique.js' import { createBlockFromRpc } from './from-rpc.js' import { genRequestsTrieRoot, @@ -32,7 +36,14 @@ import { valuesArrayToHeaderData, } from './helpers.js' -import { Block, BlockHeader, executionPayloadFromBeaconPayload } from './index.js' +import { + Block, + BlockHeader, + CLIQUE_EXTRA_SEAL, + CLIQUE_EXTRA_VANITY, + cliqueSigHash, + executionPayloadFromBeaconPayload, +} from './index.js' import type { BeaconPayloadJson } from './from-beacon-payload.js' import type { @@ -515,3 +526,31 @@ export async function createBlockFromBeaconPayloadJson( const executionPayload = executionPayloadFromBeaconPayload(payload) return createBlockFromExecutionPayload(executionPayload, opts) } + +/** + * Method to retrieve a sealed block from the header and clique signer key + * @param header block header to be used for creating sealed block + * @param cliqueSigner clique signer key to be used for creating sealed block + * @returns the block constructed block + */ +export function createSealedCliqueBlock(header: BlockHeader, cliqueSigner: Uint8Array): Uint8Array { + // Ensure extraData is at least length CLIQUE_EXTRA_VANITY + CLIQUE_EXTRA_SEAL + const minExtraDataLength = CLIQUE_EXTRA_VANITY + CLIQUE_EXTRA_SEAL + if (header.extraData.length < minExtraDataLength) { + const remainingLength = minExtraDataLength - header.extraData.length + ;(header.extraData as any) = concatBytes(header.extraData, new Uint8Array(remainingLength)) + } + + _requireClique(header, 'cliqueSealBlock') + + const ecSignFunction = header.common.customCrypto?.ecsign ?? ecsign + const signature = ecSignFunction(cliqueSigHash(header), cliqueSigner) + const signatureB = concatBytes(signature.r, signature.s, bigIntToBytes(signature.v - BIGINT_27)) + + const extraDataWithoutSeal = header.extraData.subarray( + 0, + header.extraData.length - CLIQUE_EXTRA_SEAL, + ) + const extraData = concatBytes(extraDataWithoutSeal, signatureB) + return extraData +} diff --git a/packages/block/src/header.ts b/packages/block/src/header.ts index 7dfc9c5ebc..645151ca86 100644 --- a/packages/block/src/header.ts +++ b/packages/block/src/header.ts @@ -5,19 +5,15 @@ import { BIGINT_0, BIGINT_1, BIGINT_2, - BIGINT_27, BIGINT_7, KECCAK256_RLP, KECCAK256_RLP_ARRAY, TypeOutput, - bigIntToBytes, bigIntToHex, bigIntToUnpaddedBytes, bytesToHex, bytesToUtf8, - concatBytes, createZeroAddress, - ecsign, equalsBytes, hexToBytes, toType, @@ -33,7 +29,7 @@ import { CLIQUE_EXTRA_SEAL, CLIQUE_EXTRA_VANITY, cliqueIsEpochTransition, - cliqueSigHash, + createSealedCliqueBlock, } from './index.js' import type { BlockHeaderBytes, BlockOptions, HeaderData, JsonHeader } from './types.js' @@ -251,16 +247,7 @@ export class BlockHeader { } // If cliqueSigner is provided, seal block with provided privateKey. - if (opts.cliqueSigner) { - // Ensure extraData is at least length CLIQUE_EXTRA_VANITY + CLIQUE_EXTRA_SEAL - const minExtraDataLength = CLIQUE_EXTRA_VANITY + CLIQUE_EXTRA_SEAL - if (this.extraData.length < minExtraDataLength) { - const remainingLength = minExtraDataLength - this.extraData.length - this.extraData = concatBytes(this.extraData, new Uint8Array(remainingLength)) - } - - this.extraData = this.cliqueSealBlock(opts.cliqueSigner) - } + if (opts.cliqueSigner) this.extraData = createSealedCliqueBlock(this, opts.cliqueSigner) // Validate consensus format after block is sealed (if applicable) so extraData checks will pass if (skipValidateConsensusFormat === false) this._consensusFormatValidation() @@ -745,26 +732,6 @@ export class BlockHeader { return dif } - /** - * Seal block with the provided signer. - * Returns the final extraData field to be assigned to `this.extraData`. - * @hidden - */ - private cliqueSealBlock(privateKey: Uint8Array) { - _requireClique(this, 'cliqueSealBlock') - - const ecSignFunction = this.common.customCrypto?.ecsign ?? ecsign - const signature = ecSignFunction(cliqueSigHash(this), privateKey) - const signatureB = concatBytes(signature.r, signature.s, bigIntToBytes(signature.v - BIGINT_27)) - - const extraDataWithoutSeal = this.extraData.subarray( - 0, - this.extraData.length - CLIQUE_EXTRA_SEAL, - ) - const extraData = concatBytes(extraDataWithoutSeal, signatureB) - return extraData - } - /** * Returns the rlp encoding of the block header. */ From 54114e78879caf560c31498f7970b60ab6fdc20a Mon Sep 17 00:00:00 2001 From: Amir Date: Thu, 8 Aug 2024 15:24:10 -0700 Subject: [PATCH 19/40] Fix imports --- packages/block/src/header.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/block/src/header.ts b/packages/block/src/header.ts index 645151ca86..c1424b64f1 100644 --- a/packages/block/src/header.ts +++ b/packages/block/src/header.ts @@ -21,16 +21,15 @@ import { } from '@ethereumjs/util' import { keccak256 } from 'ethereum-cryptography/keccak.js' -import { _requireClique } from './consensus/clique.js' -import { fakeExponential } from './helpers.js' -import { paramsBlock } from './params.js' - import { CLIQUE_EXTRA_SEAL, CLIQUE_EXTRA_VANITY, + _requireClique, cliqueIsEpochTransition, - createSealedCliqueBlock, -} from './index.js' +} from './consensus/clique.js' +import { createSealedCliqueBlock } from './constructors.js' +import { fakeExponential } from './helpers.js' +import { paramsBlock } from './params.js' import type { BlockHeaderBytes, BlockOptions, HeaderData, JsonHeader } from './types.js' From dd58b432b78df8681344987da3314e407f1dd0e1 Mon Sep 17 00:00:00 2001 From: acolytec3 <17355484+acolytec3@users.noreply.github.com> Date: Thu, 8 Aug 2024 20:38:29 -0400 Subject: [PATCH 20/40] fix header typing --- packages/evm/src/interpreter.ts | 2 +- packages/evm/src/types.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/evm/src/interpreter.ts b/packages/evm/src/interpreter.ts index 30266d8b62..67226fca4f 100644 --- a/packages/evm/src/interpreter.ts +++ b/packages/evm/src/interpreter.ts @@ -790,7 +790,7 @@ export class Interpreter { getBlockCoinbase(): bigint { let coinbase: Address if (this.common.consensusAlgorithm() === ConsensusAlgorithm.Clique) { - coinbase = this._evm['_optsCached'].cliqueSigner!(this._env.block.header as any) + coinbase = this._evm['_optsCached'].cliqueSigner!(this._env.block.header) } else { coinbase = this._env.block.header.coinbase } diff --git a/packages/evm/src/types.ts b/packages/evm/src/types.ts index 9f899c641f..35b9e7f423 100644 --- a/packages/evm/src/types.ts +++ b/packages/evm/src/types.ts @@ -350,7 +350,7 @@ export interface EVMOpts { /** * Must be present if consensus type is clique/poa, else error will be thrown */ - cliqueSigner?: (header: any) => Address + cliqueSigner?: (header: Block['header']) => Address } /** From c9204ab628bc13d755bb88a807d330b1d5ff9c9e Mon Sep 17 00:00:00 2001 From: acolytec3 <17355484+acolytec3@users.noreply.github.com> Date: Mon, 12 Aug 2024 14:11:31 -0400 Subject: [PATCH 21/40] remove pointless underscore --- packages/block/src/consensus/clique.ts | 16 ++++++++-------- packages/block/src/constructors.ts | 4 ++-- packages/block/src/header.ts | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/block/src/consensus/clique.ts b/packages/block/src/consensus/clique.ts index f140545f8d..ce453b9e49 100644 --- a/packages/block/src/consensus/clique.ts +++ b/packages/block/src/consensus/clique.ts @@ -20,7 +20,7 @@ export const CLIQUE_EXTRA_VANITY = 32 export const CLIQUE_EXTRA_SEAL = 65 // This function is not exported in the index file to keep it internal -export function _requireClique(header: BlockHeader, name: string) { +export function requireClique(header: BlockHeader, name: string) { if (header.common.consensusAlgorithm() !== ConsensusAlgorithm.Clique) { const msg = header['_errorMsg']( `BlockHeader.${name}() call only supported for clique PoA networks`, @@ -33,7 +33,7 @@ export function _requireClique(header: BlockHeader, name: string) { * PoA clique signature hash without the seal. */ export function cliqueSigHash(header: BlockHeader) { - _requireClique(header, 'cliqueSigHash') + requireClique(header, 'cliqueSigHash') const raw = header.raw() raw[12] = header.extraData.subarray(0, header.extraData.length - CLIQUE_EXTRA_SEAL) return header['keccakFunction'](RLP.encode(raw)) @@ -44,7 +44,7 @@ export function cliqueSigHash(header: BlockHeader) { * header (only clique PoA, throws otherwise) */ export function cliqueIsEpochTransition(header: BlockHeader): boolean { - _requireClique(header, 'cliqueIsEpochTransition') + requireClique(header, 'cliqueIsEpochTransition') const epoch = BigInt((header.common.consensusConfig() as CliqueConfig).epoch) // Epoch transition block if the block number has no // remainder on the division by the epoch length @@ -56,7 +56,7 @@ export function cliqueIsEpochTransition(header: BlockHeader): boolean { * (only clique PoA, throws otherwise) */ export function cliqueExtraVanity(header: BlockHeader): Uint8Array { - _requireClique(header, 'cliqueExtraVanity') + requireClique(header, 'cliqueExtraVanity') return header.extraData.subarray(0, CLIQUE_EXTRA_VANITY) } @@ -65,7 +65,7 @@ export function cliqueExtraVanity(header: BlockHeader): Uint8Array { * (only clique PoA, throws otherwise) */ export function cliqueExtraSeal(header: BlockHeader): Uint8Array { - _requireClique(header, 'cliqueExtraSeal') + requireClique(header, 'cliqueExtraSeal') return header.extraData.subarray(-CLIQUE_EXTRA_SEAL) } @@ -78,7 +78,7 @@ export function cliqueExtraSeal(header: BlockHeader): Uint8Array { * in conjunction with {@link BlockHeader.cliqueIsEpochTransition} */ export function cliqueEpochTransitionSigners(header: BlockHeader): Address[] { - _requireClique(header, 'cliqueEpochTransitionSigners') + requireClique(header, 'cliqueEpochTransitionSigners') if (!cliqueIsEpochTransition(header)) { const msg = header['_errorMsg']('Signers are only included in epoch transition blocks (clique)') throw new Error(msg) @@ -100,7 +100,7 @@ export function cliqueEpochTransitionSigners(header: BlockHeader): Address[] { * Returns the signer address */ export function cliqueSigner(header: BlockHeader): Address { - _requireClique(header, 'cliqueSigner') + requireClique(header, 'cliqueSigner') const extraSeal = cliqueExtraSeal(header) // Reasonable default for default blocks if (extraSeal.length === 0 || equalsBytes(extraSeal, new Uint8Array(65))) { @@ -120,7 +120,7 @@ export function cliqueSigner(header: BlockHeader): Address { * Method throws if signature is invalid */ export function cliqueVerifySignature(header: BlockHeader, signerList: Address[]): boolean { - _requireClique(header, 'cliqueVerifySignature') + requireClique(header, 'cliqueVerifySignature') const signerAddress = cliqueSigner(header) const signerFound = signerList.find((signer) => { return signer.equals(signerAddress) diff --git a/packages/block/src/constructors.ts b/packages/block/src/constructors.ts index bf3dd48f47..ff05a2be54 100644 --- a/packages/block/src/constructors.ts +++ b/packages/block/src/constructors.ts @@ -27,7 +27,7 @@ import { isHexString, } from '@ethereumjs/util' -import { _requireClique } from './consensus/clique.js' +import { requireClique } from './consensus/clique.js' import { createBlockFromRpc } from './from-rpc.js' import { genRequestsTrieRoot, @@ -541,7 +541,7 @@ export function createSealedCliqueBlock(header: BlockHeader, cliqueSigner: Uint8 ;(header.extraData as any) = concatBytes(header.extraData, new Uint8Array(remainingLength)) } - _requireClique(header, 'cliqueSealBlock') + requireClique(header, 'cliqueSealBlock') const ecSignFunction = header.common.customCrypto?.ecsign ?? ecsign const signature = ecSignFunction(cliqueSigHash(header), cliqueSigner) diff --git a/packages/block/src/header.ts b/packages/block/src/header.ts index c1424b64f1..38415abbbb 100644 --- a/packages/block/src/header.ts +++ b/packages/block/src/header.ts @@ -24,7 +24,7 @@ import { keccak256 } from 'ethereum-cryptography/keccak.js' import { CLIQUE_EXTRA_SEAL, CLIQUE_EXTRA_VANITY, - _requireClique, + requireClique, cliqueIsEpochTransition, } from './consensus/clique.js' import { createSealedCliqueBlock } from './constructors.js' From eb89c3c89d250bdfc41e0ebc4c760a29942dc60b Mon Sep 17 00:00:00 2001 From: acolytec3 <17355484+acolytec3@users.noreply.github.com> Date: Mon, 12 Aug 2024 14:13:13 -0400 Subject: [PATCH 22/40] revise codedoc [no ci] --- packages/evm/src/types.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/evm/src/types.ts b/packages/evm/src/types.ts index 35b9e7f423..34a84b9ade 100644 --- a/packages/evm/src/types.ts +++ b/packages/evm/src/types.ts @@ -348,7 +348,9 @@ export interface EVMOpts { profiler?: EVMProfilerOpts /** - * Must be present if consensus type is clique/poa, else error will be thrown + * When running the EVM with PoA consensus, the `cliqueSigner` function from the `@ethereumjs/block` class + * must be provided along with a `BlockHeader` so that the coinbase can be correctly retrieved when the + * `Interpreter.getBlockCoinbase` method is called. */ cliqueSigner?: (header: Block['header']) => Address } From a0bb7056e4f9f3942a5df13bc87c0fc32491b5c2 Mon Sep 17 00:00:00 2001 From: Amir Date: Mon, 12 Aug 2024 14:14:17 -0700 Subject: [PATCH 23/40] Create and use block and header constructor for PoA/cliques --- packages/block/src/constructors.ts | 33 ++++++++++++++++++++++++- packages/block/src/header.ts | 3 --- packages/block/src/types.ts | 5 ---- packages/blockchain/test/clique.spec.ts | 8 ++++-- packages/client/src/miner/miner.ts | 9 +++---- packages/vm/src/types.ts | 5 ++++ 6 files changed, 47 insertions(+), 16 deletions(-) diff --git a/packages/block/src/constructors.ts b/packages/block/src/constructors.ts index bf3dd48f47..8b8377c483 100644 --- a/packages/block/src/constructors.ts +++ b/packages/block/src/constructors.ts @@ -533,7 +533,10 @@ export async function createBlockFromBeaconPayloadJson( * @param cliqueSigner clique signer key to be used for creating sealed block * @returns the block constructed block */ -export function createSealedCliqueBlock(header: BlockHeader, cliqueSigner: Uint8Array): Uint8Array { +export function createSealedCliqueBlockExtraData( + header: BlockHeader, + cliqueSigner: Uint8Array, +): Uint8Array { // Ensure extraData is at least length CLIQUE_EXTRA_VANITY + CLIQUE_EXTRA_SEAL const minExtraDataLength = CLIQUE_EXTRA_VANITY + CLIQUE_EXTRA_SEAL if (header.extraData.length < minExtraDataLength) { @@ -554,3 +557,31 @@ export function createSealedCliqueBlock(header: BlockHeader, cliqueSigner: Uint8 const extraData = concatBytes(extraDataWithoutSeal, signatureB) return extraData } + +export function createSealedCliqueBlock( + blockData: BlockData = {}, + cliqueSigner: Uint8Array, + opts?: BlockOptions, +): Block { + const sealedCliqueBlock = createBlock(blockData, opts) + ;(sealedCliqueBlock.header.extraData as any) = createSealedCliqueBlockExtraData( + sealedCliqueBlock.header, + cliqueSigner, + ) + + return sealedCliqueBlock +} + +export function createSealedCliqueBlockHeader( + headerData: HeaderData = {}, + cliqueSigner: Uint8Array, + opts: BlockOptions = {}, +): BlockHeader { + const sealedCliqueBlockHeader = new BlockHeader(headerData, opts) + ;(sealedCliqueBlockHeader.extraData as any) = createSealedCliqueBlockExtraData( + sealedCliqueBlockHeader, + cliqueSigner, + ) + + return sealedCliqueBlockHeader +} diff --git a/packages/block/src/header.ts b/packages/block/src/header.ts index c1424b64f1..abb8eb033e 100644 --- a/packages/block/src/header.ts +++ b/packages/block/src/header.ts @@ -245,9 +245,6 @@ export class BlockHeader { this.difficulty = this.ethashCanonicalDifficulty(opts.calcDifficultyFromHeader) } - // If cliqueSigner is provided, seal block with provided privateKey. - if (opts.cliqueSigner) this.extraData = createSealedCliqueBlock(this, opts.cliqueSigner) - // Validate consensus format after block is sealed (if applicable) so extraData checks will pass if (skipValidateConsensusFormat === false) this._consensusFormatValidation() diff --git a/packages/block/src/types.ts b/packages/block/src/types.ts index 8957546946..27d15a95b2 100644 --- a/packages/block/src/types.ts +++ b/packages/block/src/types.ts @@ -81,11 +81,6 @@ export interface BlockOptions { * Default: true */ freeze?: boolean - /** - * Provide a clique signer's privateKey to seal this block. - * Will throw if provided on a non-PoA chain. - */ - cliqueSigner?: Uint8Array /** * Skip consensus format validation checks on header if set. Defaults to false. */ diff --git a/packages/blockchain/test/clique.spec.ts b/packages/blockchain/test/clique.spec.ts index 0ebcb47654..19aee30ce0 100644 --- a/packages/blockchain/test/clique.spec.ts +++ b/packages/blockchain/test/clique.spec.ts @@ -1,4 +1,8 @@ -import { cliqueEpochTransitionSigners, createBlock } from '@ethereumjs/block' +import { + cliqueEpochTransitionSigners, + createBlock, + createSealedCliqueBlock, +} from '@ethereumjs/block' import { Common, ConsensusAlgorithm, @@ -155,7 +159,7 @@ function getBlock( // set signer const cliqueSigner = signer.privateKey - return createBlock(blockData, { common, freeze: false, cliqueSigner }) + return createSealedCliqueBlock(blockData, cliqueSigner, { common, freeze: false }) } const addNextBlockReorg = async ( diff --git a/packages/client/src/miner/miner.ts b/packages/client/src/miner/miner.ts index d4acf00e96..3c847ffe7f 100644 --- a/packages/client/src/miner/miner.ts +++ b/packages/client/src/miner/miner.ts @@ -1,4 +1,4 @@ -import { type BlockHeader, createBlockHeader } from '@ethereumjs/block' +import { type BlockHeader, createSealedCliqueBlockHeader } from '@ethereumjs/block' import { ConsensusType, Hardfork } from '@ethereumjs/common' import { Ethash } from '@ethereumjs/ethash' import { BIGINT_0, BIGINT_1, BIGINT_2, bytesToHex, equalsBytes } from '@ethereumjs/util' @@ -208,10 +208,9 @@ export class Miner { if (this.config.chainCommon.consensusType() === ConsensusType.ProofOfAuthority) { // Abort if we have too recently signed const cliqueSigner = this.config.accounts[0][1] - const header = createBlockHeader( - { number }, - { common: this.config.chainCommon, cliqueSigner }, - ) + const header = createSealedCliqueBlockHeader({ number }, cliqueSigner, { + common: this.config.chainCommon, + }) if ( (this.service.chain.blockchain as any).consensus.cliqueCheckRecentlySigned(header) === true ) { diff --git a/packages/vm/src/types.ts b/packages/vm/src/types.ts index 16e59c1bd7..cb736c3a0c 100644 --- a/packages/vm/src/types.ts +++ b/packages/vm/src/types.ts @@ -195,6 +195,11 @@ export interface BuilderOpts extends BlockOptions { * Default: true */ putBlockIntoBlockchain?: boolean + /** + * Provide a clique signer's privateKey to seal this block. + * Will throw if provided on a non-PoA chain. + */ + cliqueSigner?: Uint8Array } /** From 917d48f7d229bc22ad91eb5210eb9e1a50ec1eba Mon Sep 17 00:00:00 2001 From: Amir Date: Mon, 12 Aug 2024 14:21:53 -0700 Subject: [PATCH 24/40] Fix linting issue --- packages/block/src/header.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/block/src/header.ts b/packages/block/src/header.ts index 8bdac3b98f..eed3e04c24 100644 --- a/packages/block/src/header.ts +++ b/packages/block/src/header.ts @@ -24,10 +24,8 @@ import { keccak256 } from 'ethereum-cryptography/keccak.js' import { CLIQUE_EXTRA_SEAL, CLIQUE_EXTRA_VANITY, - requireClique, cliqueIsEpochTransition, } from './consensus/clique.js' -import { createSealedCliqueBlock } from './constructors.js' import { fakeExponential } from './helpers.js' import { paramsBlock } from './params.js' From b95ae3929f1342f19b23d3eb0c118dab2a186143 Mon Sep 17 00:00:00 2001 From: Amir Date: Mon, 12 Aug 2024 14:29:41 -0700 Subject: [PATCH 25/40] Fix tests --- packages/blockchain/test/clique.spec.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/blockchain/test/clique.spec.ts b/packages/blockchain/test/clique.spec.ts index 19aee30ce0..d16578ac1f 100644 --- a/packages/blockchain/test/clique.spec.ts +++ b/packages/blockchain/test/clique.spec.ts @@ -228,10 +228,9 @@ describe('Clique: Initialization', () => { unauthorizedSigner.toBytes(), new Uint8Array(65), ) - const block = createBlock( - { header: { number, extraData } }, - { common: COMMON, cliqueSigner: A.privateKey }, - ) + const block = createSealedCliqueBlock({ header: { number, extraData } }, A.privateKey, { + common: COMMON, + }) try { await blockchain.putBlock(block) assert.fail('should fail') @@ -275,7 +274,7 @@ describe('Clique: Initialization', () => { difficulty = BigInt(1) const cliqueSigner = A.privateKey - block = createBlock( + block = createSealedCliqueBlock( { header: { number, @@ -285,7 +284,8 @@ describe('Clique: Initialization', () => { timestamp: parentHeader.timestamp + BigInt(10000), }, }, - { common: COMMON, cliqueSigner }, + cliqueSigner, + { common: COMMON }, ) try { From aab9b6e18386f41d4ecb7c4599cd672bc92f09e6 Mon Sep 17 00:00:00 2001 From: Amir Date: Mon, 12 Aug 2024 14:35:21 -0700 Subject: [PATCH 26/40] Fix test --- packages/block/test/clique.spec.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/block/test/clique.spec.ts b/packages/block/test/clique.spec.ts index db24821fad..23ad345b01 100644 --- a/packages/block/test/clique.spec.ts +++ b/packages/block/test/clique.spec.ts @@ -2,7 +2,7 @@ import { Common, Goerli, Hardfork } from '@ethereumjs/common' import { Address, createZeroAddress, hexToBytes } from '@ethereumjs/util' import { assert, describe, it } from 'vitest' -import { createBlockHeader } from '../src/constructors.js' +import { createBlockHeader, createSealedCliqueBlockHeader } from '../src/constructors.js' import { cliqueEpochTransitionSigners, cliqueExtraSeal, @@ -97,9 +97,10 @@ describe('[Header]: Clique PoA Functionality', () => { it('Signing', () => { const cliqueSignerKey = A.privateKey - let header = createBlockHeader( + let header = createSealedCliqueBlockHeader( { number: 1, extraData: new Uint8Array(97) }, - { common, freeze: false, cliqueSigner: cliqueSignerKey }, + cliqueSignerKey, + { common, freeze: false }, ) assert.equal(header.extraData.length, 97) From eec50fe61964e4507f1650e652dad462843707eb Mon Sep 17 00:00:00 2001 From: Amir Date: Mon, 12 Aug 2024 14:42:57 -0700 Subject: [PATCH 27/40] Make constructor signatures more similar --- packages/block/src/constructors.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block/src/constructors.ts b/packages/block/src/constructors.ts index 3d7980f88e..e699194bd8 100644 --- a/packages/block/src/constructors.ts +++ b/packages/block/src/constructors.ts @@ -561,7 +561,7 @@ export function createSealedCliqueBlockExtraData( export function createSealedCliqueBlock( blockData: BlockData = {}, cliqueSigner: Uint8Array, - opts?: BlockOptions, + opts: BlockOptions = {}, ): Block { const sealedCliqueBlock = createBlock(blockData, opts) ;(sealedCliqueBlock.header.extraData as any) = createSealedCliqueBlockExtraData( From 598b92207336311d0d5d77884cc4c702012956c4 Mon Sep 17 00:00:00 2001 From: Amir Date: Mon, 12 Aug 2024 14:43:10 -0700 Subject: [PATCH 28/40] Fix read-only error --- packages/client/src/miner/miner.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/client/src/miner/miner.ts b/packages/client/src/miner/miner.ts index 3c847ffe7f..271c92b92d 100644 --- a/packages/client/src/miner/miner.ts +++ b/packages/client/src/miner/miner.ts @@ -210,6 +210,7 @@ export class Miner { const cliqueSigner = this.config.accounts[0][1] const header = createSealedCliqueBlockHeader({ number }, cliqueSigner, { common: this.config.chainCommon, + freeze: false, }) if ( (this.service.chain.blockchain as any).consensus.cliqueCheckRecentlySigned(header) === true From 4818096d6fecfd170646c5a7a25380113abf432e Mon Sep 17 00:00:00 2001 From: acolytec3 <17355484+acolytec3@users.noreply.github.com> Date: Mon, 12 Aug 2024 21:40:48 -0400 Subject: [PATCH 29/40] fix extraData function reference --- packages/block/src/consensus/clique.ts | 34 ++++++++++++++++++ packages/block/src/constructors.ts | 49 +++----------------------- 2 files changed, 38 insertions(+), 45 deletions(-) diff --git a/packages/block/src/consensus/clique.ts b/packages/block/src/consensus/clique.ts index ce453b9e49..37b74db173 100644 --- a/packages/block/src/consensus/clique.ts +++ b/packages/block/src/consensus/clique.ts @@ -4,10 +4,13 @@ import { Address, BIGINT_0, BIGINT_27, + bigIntToBytes, bytesToBigInt, + concatBytes, createAddressFromPublicKey, createZeroAddress, ecrecover, + ecsign, equalsBytes, } from '@ethereumjs/util' @@ -127,3 +130,34 @@ export function cliqueVerifySignature(header: BlockHeader, signerList: Address[] }) return !!signerFound } + +/** + * Retrieves the extraData from a sealed block header + * @param header block header from which to retrieve extraData + * @param cliqueSigner clique signer key used for creating sealed block + * @returns the extradata from the block + */ +export function retrieveCliqueBlockExtraData( + header: BlockHeader, + cliqueSigner: Uint8Array, +): Uint8Array { + // Ensure extraData is at least length CLIQUE_EXTRA_VANITY + CLIQUE_EXTRA_SEAL + const minExtraDataLength = CLIQUE_EXTRA_VANITY + CLIQUE_EXTRA_SEAL + if (header.extraData.length < minExtraDataLength) { + const remainingLength = minExtraDataLength - header.extraData.length + ;(header.extraData as any) = concatBytes(header.extraData, new Uint8Array(remainingLength)) + } + + requireClique(header, 'cliqueSealBlock') + + const ecSignFunction = header.common.customCrypto?.ecsign ?? ecsign + const signature = ecSignFunction(cliqueSigHash(header), cliqueSigner) + const signatureB = concatBytes(signature.r, signature.s, bigIntToBytes(signature.v - BIGINT_27)) + + const extraDataWithoutSeal = header.extraData.subarray( + 0, + header.extraData.length - CLIQUE_EXTRA_SEAL, + ) + const extraData = concatBytes(extraDataWithoutSeal, signatureB) + return extraData +} diff --git a/packages/block/src/constructors.ts b/packages/block/src/constructors.ts index e699194bd8..8152f6323e 100644 --- a/packages/block/src/constructors.ts +++ b/packages/block/src/constructors.ts @@ -7,7 +7,6 @@ import { createTxFromTxData, } from '@ethereumjs/tx' import { - BIGINT_27, CLRequestFactory, ConsolidationRequest, DepositRequest, @@ -17,8 +16,6 @@ import { bigIntToHex, bytesToHex, bytesToUtf8, - concatBytes, - ecsign, equalsBytes, fetchFromProvider, getProvider, @@ -27,7 +24,7 @@ import { isHexString, } from '@ethereumjs/util' -import { requireClique } from './consensus/clique.js' +import { retrieveCliqueBlockExtraData } from './consensus/clique.js' import { createBlockFromRpc } from './from-rpc.js' import { genRequestsTrieRoot, @@ -36,14 +33,7 @@ import { valuesArrayToHeaderData, } from './helpers.js' -import { - Block, - BlockHeader, - CLIQUE_EXTRA_SEAL, - CLIQUE_EXTRA_VANITY, - cliqueSigHash, - executionPayloadFromBeaconPayload, -} from './index.js' +import { Block, BlockHeader, executionPayloadFromBeaconPayload } from './index.js' import type { BeaconPayloadJson } from './from-beacon-payload.js' import type { @@ -527,44 +517,13 @@ export async function createBlockFromBeaconPayloadJson( return createBlockFromExecutionPayload(executionPayload, opts) } -/** - * Method to retrieve a sealed block from the header and clique signer key - * @param header block header to be used for creating sealed block - * @param cliqueSigner clique signer key to be used for creating sealed block - * @returns the block constructed block - */ -export function createSealedCliqueBlockExtraData( - header: BlockHeader, - cliqueSigner: Uint8Array, -): Uint8Array { - // Ensure extraData is at least length CLIQUE_EXTRA_VANITY + CLIQUE_EXTRA_SEAL - const minExtraDataLength = CLIQUE_EXTRA_VANITY + CLIQUE_EXTRA_SEAL - if (header.extraData.length < minExtraDataLength) { - const remainingLength = minExtraDataLength - header.extraData.length - ;(header.extraData as any) = concatBytes(header.extraData, new Uint8Array(remainingLength)) - } - - requireClique(header, 'cliqueSealBlock') - - const ecSignFunction = header.common.customCrypto?.ecsign ?? ecsign - const signature = ecSignFunction(cliqueSigHash(header), cliqueSigner) - const signatureB = concatBytes(signature.r, signature.s, bigIntToBytes(signature.v - BIGINT_27)) - - const extraDataWithoutSeal = header.extraData.subarray( - 0, - header.extraData.length - CLIQUE_EXTRA_SEAL, - ) - const extraData = concatBytes(extraDataWithoutSeal, signatureB) - return extraData -} - export function createSealedCliqueBlock( blockData: BlockData = {}, cliqueSigner: Uint8Array, opts: BlockOptions = {}, ): Block { const sealedCliqueBlock = createBlock(blockData, opts) - ;(sealedCliqueBlock.header.extraData as any) = createSealedCliqueBlockExtraData( + ;(sealedCliqueBlock.header.extraData as any) = retrieveCliqueBlockExtraData( sealedCliqueBlock.header, cliqueSigner, ) @@ -578,7 +537,7 @@ export function createSealedCliqueBlockHeader( opts: BlockOptions = {}, ): BlockHeader { const sealedCliqueBlockHeader = new BlockHeader(headerData, opts) - ;(sealedCliqueBlockHeader.extraData as any) = createSealedCliqueBlockExtraData( + ;(sealedCliqueBlockHeader.extraData as any) = retrieveCliqueBlockExtraData( sealedCliqueBlockHeader, cliqueSigner, ) From 4b7090ad28e9139c1397598fe6c84c26819fd1cb Mon Sep 17 00:00:00 2001 From: acolytec3 <17355484+acolytec3@users.noreply.github.com> Date: Mon, 12 Aug 2024 21:55:45 -0400 Subject: [PATCH 30/40] fix the freeze --- packages/block/src/constructors.ts | 7 +++++-- packages/blockchain/test/clique.spec.ts | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/block/src/constructors.ts b/packages/block/src/constructors.ts index 8152f6323e..2b6094326c 100644 --- a/packages/block/src/constructors.ts +++ b/packages/block/src/constructors.ts @@ -522,12 +522,15 @@ export function createSealedCliqueBlock( cliqueSigner: Uint8Array, opts: BlockOptions = {}, ): Block { - const sealedCliqueBlock = createBlock(blockData, opts) + const sealedCliqueBlock = createBlock(blockData, { ...opts, ...{ freeze: false } }) ;(sealedCliqueBlock.header.extraData as any) = retrieveCliqueBlockExtraData( sealedCliqueBlock.header, cliqueSigner, ) - + if (opts?.freeze === true) { + // We have to freeze here since we can't freeze the block when constructing it since we are overwriting `extraData` + Object.freeze(sealedCliqueBlock) + } return sealedCliqueBlock } diff --git a/packages/blockchain/test/clique.spec.ts b/packages/blockchain/test/clique.spec.ts index d16578ac1f..f4307ac872 100644 --- a/packages/blockchain/test/clique.spec.ts +++ b/packages/blockchain/test/clique.spec.ts @@ -159,7 +159,7 @@ function getBlock( // set signer const cliqueSigner = signer.privateKey - return createSealedCliqueBlock(blockData, cliqueSigner, { common, freeze: false }) + return createSealedCliqueBlock(blockData, cliqueSigner, { common }) } const addNextBlockReorg = async ( @@ -230,6 +230,7 @@ describe('Clique: Initialization', () => { ) const block = createSealedCliqueBlock({ header: { number, extraData } }, A.privateKey, { common: COMMON, + freeze: false, }) try { await blockchain.putBlock(block) From 8d53ea0e73d2b8bf714f3c42a9585609712f2961 Mon Sep 17 00:00:00 2001 From: Amir Date: Mon, 12 Aug 2024 21:20:52 -0700 Subject: [PATCH 31/40] Fix test --- packages/vm/test/api/runBlock.spec.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/vm/test/api/runBlock.spec.ts b/packages/vm/test/api/runBlock.spec.ts index 1d99c14640..e5a52109a9 100644 --- a/packages/vm/test/api/runBlock.spec.ts +++ b/packages/vm/test/api/runBlock.spec.ts @@ -2,6 +2,7 @@ import { createBlock, createBlockFromRLPSerializedBlock, createBlockFromValuesArray, + createSealedCliqueBlock, } from '@ethereumjs/block' import { Common, Goerli, Hardfork, Mainnet, createCustomCommon } from '@ethereumjs/common' import { RLP } from '@ethereumjs/rlp' @@ -387,9 +388,10 @@ describe('runBlock() -> runtime behavior', async () => { ).sign(otherUser.privateKey) // create block with the signer and txs - const block = createBlock( + const block = createSealedCliqueBlock( { header: { extraData: new Uint8Array(97) }, transactions: [tx, tx] }, - { common, cliqueSigner: signer.privateKey }, + signer.privateKey, + { common }, ) await runBlock(vm, { block, skipNonce: true, skipBlockValidation: true, generate: true }) From 6048d8f04687da674008ca11b2da8abadb6bfcf9 Mon Sep 17 00:00:00 2001 From: Amir Date: Mon, 12 Aug 2024 21:58:34 -0700 Subject: [PATCH 32/40] Fix test --- packages/vm/test/api/buildBlock.spec.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/vm/test/api/buildBlock.spec.ts b/packages/vm/test/api/buildBlock.spec.ts index 643e38c676..6c1a8d159e 100644 --- a/packages/vm/test/api/buildBlock.spec.ts +++ b/packages/vm/test/api/buildBlock.spec.ts @@ -1,4 +1,9 @@ -import { cliqueSigner, cliqueVerifySignature, createBlock } from '@ethereumjs/block' +import { + cliqueSigner, + cliqueVerifySignature, + createBlock, + createSealedCliqueBlock, +} from '@ethereumjs/block' import { EthashConsensus, createBlockchain } from '@ethereumjs/blockchain' import { Common, @@ -199,9 +204,10 @@ describe('BlockBuilder', () => { // extraData: [vanity, activeSigner, seal] const extraData = concatBytes(new Uint8Array(32), signer.address.toBytes(), new Uint8Array(65)) const cliqueSignerKey = signer.privateKey - const genesisBlock = createBlock( + const genesisBlock = createSealedCliqueBlock( { header: { gasLimit: 50000, extraData } }, - { common, cliqueSigner: cliqueSignerKey }, + cliqueSignerKey, + { common }, ) const blockchain = await createBlockchain({ genesisBlock, common }) const vm = await VM.create({ common, blockchain }) From c981dafd61420f1333fedb866f6a780f2182f014 Mon Sep 17 00:00:00 2001 From: Amir Date: Mon, 12 Aug 2024 21:58:58 -0700 Subject: [PATCH 33/40] Handle creating a sealed block for PoA blocks in vm block builder --- packages/vm/src/buildBlock.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/vm/src/buildBlock.ts b/packages/vm/src/buildBlock.ts index fa3080afaf..30bea1fa6d 100644 --- a/packages/vm/src/buildBlock.ts +++ b/packages/vm/src/buildBlock.ts @@ -1,5 +1,6 @@ import { createBlock, + createSealedCliqueBlock, genRequestsTrieRoot, genTransactionsTrieRoot, genWithdrawalsTrieRoot, @@ -363,7 +364,16 @@ export class BlockBuilder { requests, } - const block = createBlock(blockData, blockOpts) + let block + if (consensusType === ConsensusType.ProofOfAuthority) { + const cs = this.blockOpts.cliqueSigner + if (cs === undefined) { + throw new Error('cliqueSigner must be included if consensus type being used is PoA') + } + block = createSealedCliqueBlock(blockData, this.blockOpts.cliqueSigner!, this.blockOpts) + } else { + block = createBlock(blockData, blockOpts) + } if (this.blockOpts.putBlockIntoBlockchain === true) { await this.vm.blockchain.putBlock(block) From f6a02d10217ea56ff299e2929814398210dc605c Mon Sep 17 00:00:00 2001 From: Amir Date: Mon, 12 Aug 2024 22:31:38 -0700 Subject: [PATCH 34/40] Fix tests --- packages/vm/src/buildBlock.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/vm/src/buildBlock.ts b/packages/vm/src/buildBlock.ts index 30bea1fa6d..82604b573d 100644 --- a/packages/vm/src/buildBlock.ts +++ b/packages/vm/src/buildBlock.ts @@ -365,12 +365,9 @@ export class BlockBuilder { } let block - if (consensusType === ConsensusType.ProofOfAuthority) { - const cs = this.blockOpts.cliqueSigner - if (cs === undefined) { - throw new Error('cliqueSigner must be included if consensus type being used is PoA') - } - block = createSealedCliqueBlock(blockData, this.blockOpts.cliqueSigner!, this.blockOpts) + const cs = this.blockOpts.cliqueSigner + if (cs !== undefined) { + block = createSealedCliqueBlock(blockData, cs, this.blockOpts) } else { block = createBlock(blockData, blockOpts) } From aec9005f598d6dbf08e23a05d5fc36b20f08ee89 Mon Sep 17 00:00:00 2001 From: Amir Date: Mon, 12 Aug 2024 22:34:05 -0700 Subject: [PATCH 35/40] Update docstring --- packages/block/src/consensus/clique.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block/src/consensus/clique.ts b/packages/block/src/consensus/clique.ts index 37b74db173..0e145c5f46 100644 --- a/packages/block/src/consensus/clique.ts +++ b/packages/block/src/consensus/clique.ts @@ -135,7 +135,7 @@ export function cliqueVerifySignature(header: BlockHeader, signerList: Address[] * Retrieves the extraData from a sealed block header * @param header block header from which to retrieve extraData * @param cliqueSigner clique signer key used for creating sealed block - * @returns the extradata from the block + * @returns extradata from the block */ export function retrieveCliqueBlockExtraData( header: BlockHeader, From fe00092916cfd90d8101c8190e316e7e7a9829bf Mon Sep 17 00:00:00 2001 From: acolytec3 <17355484+acolytec3@users.noreply.github.com> Date: Tue, 13 Aug 2024 12:38:33 -0400 Subject: [PATCH 36/40] reorganize test with proper it-ing [no ci] --- .../client/test/integration/miner.spec.ts | 59 ++++++++++--------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/packages/client/test/integration/miner.spec.ts b/packages/client/test/integration/miner.spec.ts index 07239d73c1..f9dd101829 100644 --- a/packages/client/test/integration/miner.spec.ts +++ b/packages/client/test/integration/miner.spec.ts @@ -82,39 +82,40 @@ async function minerSetup(): Promise<[MockServer, FullEthereumService]> { return [server, service] } -describe( - 'should mine blocks while a peer stays connected to tip of chain', - async () => { - const [server, service] = await minerSetup() - const [remoteServer, remoteService] = await setup({ - location: '127.0.0.2', - height: 0, - common, - }) - ;(remoteService.chain.blockchain.consensus as CliqueConsensus).cliqueActiveSigners = () => [ - accounts[0][0], - ] // stub - ;(remoteService as FullEthereumService).execution.run = async () => 1 // stub - await server.discover('remotePeer1', '127.0.0.2') - const targetHeight = BigInt(5) - await new Promise((resolve) => { - remoteService.config.events.on(Event.SYNC_SYNCHRONIZED, async (chainHeight) => { - if (chainHeight === targetHeight) { - it('should sync blocks', () => { +describe('should mine blocks while a peer stays connected to tip of chain', () => { + it( + 'should work', + async () => { + const [server, service] = await minerSetup() + const [remoteServer, remoteService] = await setup({ + location: '127.0.0.2', + height: 0, + common, + }) + ;(remoteService.chain.blockchain.consensus as CliqueConsensus).cliqueActiveSigners = () => [ + accounts[0][0], + ] // stub + ;(remoteService as FullEthereumService).execution.run = async () => 1 // stub + await server.discover('remotePeer1', '127.0.0.2') + const targetHeight = BigInt(5) + await new Promise((resolve) => { + remoteService.config.events.on(Event.SYNC_SYNCHRONIZED, async (chainHeight) => { + if (chainHeight === targetHeight) { assert.equal( remoteService.chain.blocks.height, targetHeight, 'synced blocks successfully', ) - }) - await destroy(server, service) - await destroy(remoteServer, remoteService) - resolve(undefined) - void remoteService.synchronizer!.start() - } + await destroy(server, service) + await destroy(remoteServer, remoteService) + resolve(undefined) + + void remoteService.synchronizer!.start() + } + }) }) - }) - }, - { timeout: 25000 }, -) + }, + { timeout: 25000 }, + ) +}) From 07342f89d60750c9b8d469d478b37f8f862bfa3f Mon Sep 17 00:00:00 2001 From: acolytec3 <17355484+acolytec3@users.noreply.github.com> Date: Tue, 13 Aug 2024 13:18:54 -0400 Subject: [PATCH 37/40] handle clique consensus validation at correct point --- packages/block/src/constructors.ts | 18 +++++++++++++++--- packages/vm/src/buildBlock.ts | 6 ++++-- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/packages/block/src/constructors.ts b/packages/block/src/constructors.ts index 2b6094326c..06926380f4 100644 --- a/packages/block/src/constructors.ts +++ b/packages/block/src/constructors.ts @@ -522,7 +522,10 @@ export function createSealedCliqueBlock( cliqueSigner: Uint8Array, opts: BlockOptions = {}, ): Block { - const sealedCliqueBlock = createBlock(blockData, { ...opts, ...{ freeze: false } }) + const sealedCliqueBlock = createBlock(blockData, { + ...opts, + ...{ freeze: false, skipConsensusFormatValidation: true }, + }) ;(sealedCliqueBlock.header.extraData as any) = retrieveCliqueBlockExtraData( sealedCliqueBlock.header, cliqueSigner, @@ -531,6 +534,10 @@ export function createSealedCliqueBlock( // We have to freeze here since we can't freeze the block when constructing it since we are overwriting `extraData` Object.freeze(sealedCliqueBlock) } + if (opts?.skipConsensusFormatValidation === false) { + // We need to validate the consensus format here since we skipped it when constructing the block + sealedCliqueBlock.header['_consensusFormatValidation']() + } return sealedCliqueBlock } @@ -539,11 +546,16 @@ export function createSealedCliqueBlockHeader( cliqueSigner: Uint8Array, opts: BlockOptions = {}, ): BlockHeader { - const sealedCliqueBlockHeader = new BlockHeader(headerData, opts) + const sealedCliqueBlockHeader = new BlockHeader(headerData, { + ...opts, + ...{ skipConsensusFormatValidation: true }, + }) ;(sealedCliqueBlockHeader.extraData as any) = retrieveCliqueBlockExtraData( sealedCliqueBlockHeader, cliqueSigner, ) - + if (opts.skipConsensusFormatValidation === false) + // We need to validate the consensus format here since we skipped it when constructing the block header + sealedCliqueBlockHeader['_consensusFormatValidation']() return sealedCliqueBlockHeader } diff --git a/packages/vm/src/buildBlock.ts b/packages/vm/src/buildBlock.ts index 82604b573d..e4bb361a33 100644 --- a/packages/vm/src/buildBlock.ts +++ b/packages/vm/src/buildBlock.ts @@ -5,7 +5,7 @@ import { genTransactionsTrieRoot, genWithdrawalsTrieRoot, } from '@ethereumjs/block' -import { ConsensusType, Hardfork } from '@ethereumjs/common' +import { ConsensusAlgorithm, ConsensusType, Hardfork } from '@ethereumjs/common' import { RLP } from '@ethereumjs/rlp' import { Trie } from '@ethereumjs/trie' import { BlobEIP4844Transaction, createMinimal4844TxFromNetworkWrapper } from '@ethereumjs/tx' @@ -366,7 +366,9 @@ export class BlockBuilder { let block const cs = this.blockOpts.cliqueSigner - if (cs !== undefined) { + if (this.blockOpts.common?.consensusAlgorithm() === ConsensusAlgorithm.Clique) { + if (cs === undefined) + throw new Error('cliqueSigner required for building blocks under PoA consensus') block = createSealedCliqueBlock(blockData, cs, this.blockOpts) } else { block = createBlock(blockData, blockOpts) From be12a25ae7ba7d9d12742bb05e9ac01228832ddc Mon Sep 17 00:00:00 2001 From: acolytec3 <17355484+acolytec3@users.noreply.github.com> Date: Tue, 13 Aug 2024 13:28:14 -0400 Subject: [PATCH 38/40] clean up code docs --- packages/block/src/consensus/clique.ts | 8 ++++---- packages/block/src/constructors.ts | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/block/src/consensus/clique.ts b/packages/block/src/consensus/clique.ts index 0e145c5f46..3a89a46319 100644 --- a/packages/block/src/consensus/clique.ts +++ b/packages/block/src/consensus/clique.ts @@ -132,12 +132,12 @@ export function cliqueVerifySignature(header: BlockHeader, signerList: Address[] } /** - * Retrieves the extraData from a sealed block header + * Generates the extraData from a sealed block header * @param header block header from which to retrieve extraData * @param cliqueSigner clique signer key used for creating sealed block - * @returns extradata from the block + * @returns clique seal (i.e. extradata) for the block */ -export function retrieveCliqueBlockExtraData( +export function generateCliqueBlockExtraData( header: BlockHeader, cliqueSigner: Uint8Array, ): Uint8Array { @@ -148,7 +148,7 @@ export function retrieveCliqueBlockExtraData( ;(header.extraData as any) = concatBytes(header.extraData, new Uint8Array(remainingLength)) } - requireClique(header, 'cliqueSealBlock') + requireClique(header, 'generateCliqueBlockExtraData') const ecSignFunction = header.common.customCrypto?.ecsign ?? ecsign const signature = ecSignFunction(cliqueSigHash(header), cliqueSigner) diff --git a/packages/block/src/constructors.ts b/packages/block/src/constructors.ts index 06926380f4..4f346e1308 100644 --- a/packages/block/src/constructors.ts +++ b/packages/block/src/constructors.ts @@ -24,7 +24,7 @@ import { isHexString, } from '@ethereumjs/util' -import { retrieveCliqueBlockExtraData } from './consensus/clique.js' +import { generateCliqueBlockExtraData } from './consensus/clique.js' import { createBlockFromRpc } from './from-rpc.js' import { genRequestsTrieRoot, @@ -526,7 +526,7 @@ export function createSealedCliqueBlock( ...opts, ...{ freeze: false, skipConsensusFormatValidation: true }, }) - ;(sealedCliqueBlock.header.extraData as any) = retrieveCliqueBlockExtraData( + ;(sealedCliqueBlock.header.extraData as any) = generateCliqueBlockExtraData( sealedCliqueBlock.header, cliqueSigner, ) @@ -550,7 +550,7 @@ export function createSealedCliqueBlockHeader( ...opts, ...{ skipConsensusFormatValidation: true }, }) - ;(sealedCliqueBlockHeader.extraData as any) = retrieveCliqueBlockExtraData( + ;(sealedCliqueBlockHeader.extraData as any) = generateCliqueBlockExtraData( sealedCliqueBlockHeader, cliqueSigner, ) From 831e1d6531a3fd78a0836bdf25a584e60a775ab9 Mon Sep 17 00:00:00 2001 From: acolytec3 <17355484+acolytec3@users.noreply.github.com> Date: Tue, 13 Aug 2024 13:50:43 -0400 Subject: [PATCH 39/40] revert invalid check --- packages/vm/src/buildBlock.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/vm/src/buildBlock.ts b/packages/vm/src/buildBlock.ts index e4bb361a33..71bf05bbd8 100644 --- a/packages/vm/src/buildBlock.ts +++ b/packages/vm/src/buildBlock.ts @@ -366,9 +366,7 @@ export class BlockBuilder { let block const cs = this.blockOpts.cliqueSigner - if (this.blockOpts.common?.consensusAlgorithm() === ConsensusAlgorithm.Clique) { - if (cs === undefined) - throw new Error('cliqueSigner required for building blocks under PoA consensus') + if (cs !== undefined) { block = createSealedCliqueBlock(blockData, cs, this.blockOpts) } else { block = createBlock(blockData, blockOpts) From 8a02fbe9c686553c78f44d0b0248f86e1b791205 Mon Sep 17 00:00:00 2001 From: Amir Date: Tue, 13 Aug 2024 11:05:17 -0700 Subject: [PATCH 40/40] Fix lint issue --- packages/vm/src/buildBlock.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vm/src/buildBlock.ts b/packages/vm/src/buildBlock.ts index 71bf05bbd8..82604b573d 100644 --- a/packages/vm/src/buildBlock.ts +++ b/packages/vm/src/buildBlock.ts @@ -5,7 +5,7 @@ import { genTransactionsTrieRoot, genWithdrawalsTrieRoot, } from '@ethereumjs/block' -import { ConsensusAlgorithm, ConsensusType, Hardfork } from '@ethereumjs/common' +import { ConsensusType, Hardfork } from '@ethereumjs/common' import { RLP } from '@ethereumjs/rlp' import { Trie } from '@ethereumjs/trie' import { BlobEIP4844Transaction, createMinimal4844TxFromNetworkWrapper } from '@ethereumjs/tx'