diff --git a/packages/blockchain/src/consensus/casper.ts b/packages/blockchain/src/consensus/casper.ts index 8d55461886..8d006e7367 100644 --- a/packages/blockchain/src/consensus/casper.ts +++ b/packages/blockchain/src/consensus/casper.ts @@ -1,6 +1,8 @@ import { ConsensusAlgorithm } from '@ethereumjs/common' +import { BIGINT_0 } from '@ethereumjs/util' import type { Consensus } from '../types.js' +import type { BlockHeader } from '@ethereumjs/block' /** * This class encapsulates Casper-related consensus functionality when used with the Blockchain class. @@ -18,6 +20,14 @@ export class CasperConsensus implements Consensus { public async validateConsensus(): Promise {} - public async validateDifficulty(): Promise {} + public async validateDifficulty(header: BlockHeader): Promise { + // TODO: This is not really part of consensus validation and it should be analyzed + // if it is possible to replace by a more generic hardfork check between block and + // blockchain along adding new blocks or headers + if (header.difficulty !== BIGINT_0) { + const msg = 'invalid difficulty. PoS blocks must have difficulty 0' + throw new Error(`${msg} ${header.errorStr()}`) + } + } public async newBlock(): Promise {} } diff --git a/packages/blockchain/test/pos.spec.ts b/packages/blockchain/test/pos.spec.ts index 8f5a893b12..406ebbe122 100644 --- a/packages/blockchain/test/pos.spec.ts +++ b/packages/blockchain/test/pos.spec.ts @@ -1,5 +1,5 @@ import { createBlockFromBlockData } from '@ethereumjs/block' -import { Common, Hardfork } from '@ethereumjs/common' +import { Chain, Common, Hardfork } from '@ethereumjs/common' import { bytesToHex } from '@ethereumjs/util' import { assert, describe, it } from 'vitest' @@ -88,6 +88,29 @@ describe('Proof of Stake - inserting blocks into blockchain', () => { BigInt(1313601), 'should have calculated the correct post-Merge total difficulty' ) + + const common = new Common({ chain: Chain.Mainnet, hardfork: Hardfork.London }) + const powBlock = createBlockFromBlockData( + { + header: { + number: 16, + difficulty: BigInt(1), + parentHash: latestHeader.hash(), + timestamp: latestHeader.timestamp + BigInt(1), + gasLimit: BigInt(10000), + }, + }, + { common } + ) + try { + await blockchain.putBlock(powBlock) + assert.fail('should throw when inserting PoW block') + } catch (err: any) { + assert.ok( + err.message.includes('invalid difficulty'), + 'should throw with invalid difficulty message' + ) + } }) } })