Skip to content

Commit

Permalink
block: make withdrawals trie check consistent with txtrie (#3338)
Browse files Browse the repository at this point in the history
* block: make withdrawals trie check consistent with txtrie [no ci]

* Add test for empty withdrawals array code path

* Fix uncle check

* lint

---------

Co-authored-by: acolytec3 <17355484+acolytec3@users.noreply.github.com>
  • Loading branch information
jochem-brouwer and acolytec3 authored Apr 5, 2024
1 parent 93286f3 commit faef42c
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 6 deletions.
25 changes: 20 additions & 5 deletions packages/block/src/block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { BlobEIP4844Transaction, Capability, TransactionFactory } from '@ethereu
import {
BIGINT_0,
KECCAK256_RLP,
KECCAK256_RLP_ARRAY,
Withdrawal,
bigIntToHex,
bytesToHex,
Expand Down Expand Up @@ -62,6 +63,7 @@ export class Block {

protected cache: {
txTrieRoot?: Uint8Array
withdrawalsTrieRoot?: Uint8Array
} = {}

/**
Expand Down Expand Up @@ -720,6 +722,9 @@ export class Block {
* @returns true if the uncle's hash is valid, false otherwise.
*/
uncleHashIsValid(): boolean {
if (this.uncleHeaders.length === 0) {
return equalsBytes(KECCAK256_RLP_ARRAY, this.header.uncleHash)
}
const uncles = this.uncleHeaders.map((uh) => uh.raw())
const raw = RLP.encode(uncles)
return equalsBytes(this.keccakFunction(raw), this.header.uncleHash)
Expand All @@ -733,11 +738,21 @@ export class Block {
if (!this.common.isActivatedEIP(4895)) {
throw new Error('EIP 4895 is not activated')
}
const withdrawalsRoot = await Block.genWithdrawalsTrieRoot(
this.withdrawals!,
new Trie({ common: this.common })
)
return equalsBytes(withdrawalsRoot, this.header.withdrawalsRoot!)

let result
if (this.withdrawals!.length === 0) {
result = equalsBytes(this.header.withdrawalsRoot!, KECCAK256_RLP)
return result
}

if (this.cache.withdrawalsTrieRoot === undefined) {
this.cache.withdrawalsTrieRoot = await Block.genWithdrawalsTrieRoot(
this.withdrawals!,
new Trie({ common: this.common })
)
}
result = equalsBytes(this.cache.withdrawalsTrieRoot, this.header.withdrawalsRoot!)
return result
}

/**
Expand Down
19 changes: 18 additions & 1 deletion packages/block/test/eip4895block.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { Chain, Common, Hardfork } from '@ethereumjs/common'
import { RLP } from '@ethereumjs/rlp'
import { Address, KECCAK256_RLP, Withdrawal, hexToBytes, zeros } from '@ethereumjs/util'
import {
Address,
KECCAK256_RLP,
Withdrawal,
hexToBytes,
randomBytes,
zeros,
} from '@ethereumjs/util'
import { assert, describe, it } from 'vitest'

import { Block } from '../src/block.js'
Expand Down Expand Up @@ -224,4 +231,14 @@ describe('EIP4895 tests', () => {
'should provide withdrawals array when 4895 is active'
)
})

it('should return early when withdrawals root equals KECCAK256_RLP', async () => {
const block = Block.fromBlockData({}, { common })
// Set invalid withdrawalsRoot in cache
block['cache'].withdrawalsTrieRoot = randomBytes(32)
assert.ok(
await block.withdrawalsTrieIsValid(),
'correctly executed code path where withdrawals length is 0'
)
})
})

0 comments on commit faef42c

Please sign in to comment.