Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
cb6ba08
validate EL block hash when running consensus block tests
etan-status Jul 3, 2024
a5a1117
fix
etan-status Jul 3, 2024
910915b
Merge branch 'unstable' into dev/etan/ct-elblockhash
etan-status Jul 5, 2024
c8eb5f3
Merge branch 'unstable' into dev/etan/ct-elblockhash
etan-status Jul 8, 2024
91d0c52
Merge branch 'unstable' into dev/etan/ct-elblockhash
etan-status Aug 9, 2024
4c23696
resolve merge conflicts
etan-status Aug 9, 2024
990c990
fix genesis case, and deal with `incorrect_block_hash` test
etan-status Aug 14, 2024
f5e6916
add missing export marker
etan-status Aug 14, 2024
89021d0
fix import
etan-status Aug 14, 2024
66083f5
htr mutates underlying data, messing with differ, create copy in test
etan-status Aug 14, 2024
c7edb72
Merge branch 'stable' into dev/etan/ct-elblockhash
etan-status Oct 1, 2024
57b312c
Merge branch 'stable' into dev/etan/ct-elblockhash
etan-status Oct 30, 2024
bce8c16
Merge branch 'unstable' into dev/etan/ct-elblockhash
etan-status Nov 20, 2024
8a7b077
Handle payloads with empty tx (unsupported in ordered trie tool)
etan-status Nov 21, 2024
c424901
Merge branch 'unstable' into dev/etan/ct-elblockhash
etan-status Nov 25, 2024
c8f8a52
Merge branch 'unstable' into dev/etan/ct-elblockhash
etan-status Dec 16, 2024
4f35c8c
Merge branch 'unstable' into dev/etan/ct-elblockhash
tersec Jan 3, 2025
c743c37
Merge branch 'unstable' into dev/etan/ct-elblockhash
etan-status Jan 6, 2025
5acdbf8
Update copyright years
etan-status Jan 6, 2025
750564d
Merge branch 'unstable' into dev/etan/ct-elblockhash
tersec Jan 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion beacon_chain/spec/beaconstate.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2408,7 +2408,7 @@ func upgrade_to_fulu*(

post

func latest_block_root(state: ForkyBeaconState, state_root: Eth2Digest):
func latest_block_root*(state: ForkyBeaconState, state_root: Eth2Digest):
Eth2Digest =
# The root of the last block that was successfully applied to this state -
# normally, when a block is applied, the data from the header is stored in
Expand Down
38 changes: 24 additions & 14 deletions beacon_chain/spec/helpers.nim
Original file line number Diff line number Diff line change
Expand Up @@ -389,14 +389,17 @@ func is_merge_transition_complete*(
state.latest_execution_payload_header != defaultExecutionPayloadHeader

# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.9/sync/optimistic.md#helpers
func is_execution_block*(blck: SomeForkyBeaconBlock): bool =
when typeof(blck).kind >= ConsensusFork.Bellatrix:
func is_execution_block*(body: SomeForkyBeaconBlockBody): bool =
when typeof(body).kind >= ConsensusFork.Bellatrix:
const defaultExecutionPayload =
default(typeof(blck.body.execution_payload))
blck.body.execution_payload != defaultExecutionPayload
default(typeof(body.execution_payload))
body.execution_payload != defaultExecutionPayload
else:
false

func is_execution_block*(blck: SomeForkyBeaconBlock): bool =
blck.body.is_execution_block

# https://github.com/ethereum/consensus-specs/blob/v1.5.0-alpha.8/specs/bellatrix/beacon-chain.md#is_merge_transition_block
func is_merge_transition_block(
state: bellatrix.BeaconState | capella.BeaconState | deneb.BeaconState |
Expand Down Expand Up @@ -480,9 +483,10 @@ func computeRequestsHash(

requestsHash.to(EthHash32)

proc blockToBlockHeader*(blck: ForkyBeaconBlock): EthHeader =
template payload: auto = blck.body.execution_payload

proc toExecutionBlockHeader(
payload: ForkyExecutionPayload,
parentRoot: Eth2Digest,
requestsHash = Opt.none(EthHash32)): EthHeader =
static: # `GasInt` is signed. We only use it for hashing.
doAssert sizeof(GasInt) == sizeof(payload.gas_limit)
doAssert sizeof(GasInt) == sizeof(payload.gas_used)
Expand All @@ -506,12 +510,7 @@ proc blockToBlockHeader*(blck: ForkyBeaconBlock): EthHeader =
Opt.none(uint64)
parentBeaconBlockRoot =
when typeof(payload).kind >= ConsensusFork.Deneb:
Opt.some EthHash32(blck.parent_root.data)
else:
Opt.none(EthHash32)
requestsHash =
when typeof(payload).kind >= ConsensusFork.Electra:
Opt.some blck.body.execution_requests.computeRequestsHash()
Opt.some EthHash32(parentRoot.data)
else:
Opt.none(EthHash32)

Expand All @@ -538,8 +537,19 @@ proc blockToBlockHeader*(blck: ForkyBeaconBlock): EthHeader =
parentBeaconBlockRoot : parentBeaconBlockRoot, # EIP-4788
requestsHash : requestsHash) # EIP-7685

proc compute_execution_block_hash*(
body: ForkyBeaconBlockBody,
parentRoot: Eth2Digest): Eth2Digest =
when typeof(body).kind >= ConsensusFork.Electra:
body.execution_payload.toExecutionBlockHeader(
parentRoot, Opt.some body.execution_requests.computeRequestsHash())
.rlpHash().to(Eth2Digest)
else:
body.execution_payload.toExecutionBlockHeader(parentRoot)
.rlpHash().to(Eth2Digest)

proc compute_execution_block_hash*(blck: ForkyBeaconBlock): Eth2Digest =
rlpHash(blockToBlockHeader(blck)).to(Eth2Digest)
blck.body.compute_execution_block_hash(blck.parent_root)

from std/math import exp, ln
from std/sequtils import foldl
Expand Down
18 changes: 14 additions & 4 deletions tests/consensus_spec/bellatrix/test_fixture_operations.nim
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ import
../fixtures_utils, ../os_ops,
../../helpers/debug_state

from std/sequtils import mapIt, toSeq
from std/sequtils import anyIt, mapIt, toSeq
from std/strutils import contains
from ../../../beacon_chain/spec/beaconstate import
get_base_reward_per_increment, get_state_exit_queue_info,
get_total_active_balance, process_attestation
get_total_active_balance, latest_block_root, process_attestation

const
OpDir = SszTestsDir/const_preset/"bellatrix"/"operations"
Expand Down Expand Up @@ -110,9 +110,12 @@ suite baseDescription & "Attester Slashing " & preset():
applyAttesterSlashing, path)

suite baseDescription & "Block Header " & preset():
func applyBlockHeader(
proc applyBlockHeader(
preState: var bellatrix.BeaconState, blck: bellatrix.BeaconBlock):
Result[void, cstring] =
if blck.is_execution_block:
check blck.body.execution_payload.block_hash ==
blck.compute_execution_block_hash()
var cache: StateCache
process_block_header(preState, blck, {}, cache)

Expand Down Expand Up @@ -144,6 +147,13 @@ suite baseDescription & "Execution Payload " & preset():
let payloadValid = os_ops.readFile(
OpExecutionPayloadDir/"pyspec_tests"/path/"execution.yaml"
).contains("execution_valid: true")
if payloadValid and body.is_execution_block and
not body.execution_payload.transactions.anyIt(it.len == 0):
let expectedOk = (path != "incorrect_block_hash")
check expectedOk == (body.execution_payload.block_hash ==
body.compute_execution_block_hash(
preState.latest_block_root(
assignClone(preState)[].hash_tree_root())))
func executePayload(_: bellatrix.ExecutionPayload): bool = payloadValid
process_execution_payload(
preState, body.execution_payload, executePayload)
Expand Down Expand Up @@ -199,4 +209,4 @@ suite baseDescription & "Voluntary Exit " & preset():
for path in walkTests(OpVoluntaryExitDir):
runTest[SignedVoluntaryExit, typeof applyVoluntaryExit](
OpVoluntaryExitDir, suiteName, "Voluntary Exit", "voluntary_exit",
applyVoluntaryExit, path)
applyVoluntaryExit, path)
18 changes: 14 additions & 4 deletions tests/consensus_spec/capella/test_fixture_operations.nim
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ import
../fixtures_utils, ../os_ops,
../../helpers/debug_state

from std/sequtils import mapIt, toSeq
from std/sequtils import anyIt, mapIt, toSeq
from std/strutils import contains
from ../../../beacon_chain/spec/beaconstate import
get_base_reward_per_increment, get_state_exit_queue_info,
get_total_active_balance, process_attestation
get_total_active_balance, latest_block_root, process_attestation

const
OpDir = SszTestsDir/const_preset/"capella"/"operations"
Expand Down Expand Up @@ -114,9 +114,12 @@ suite baseDescription & "Attester Slashing " & preset():
applyAttesterSlashing, path)

suite baseDescription & "Block Header " & preset():
func applyBlockHeader(
proc applyBlockHeader(
preState: var capella.BeaconState, blck: capella.BeaconBlock):
Result[void, cstring] =
if blck.is_execution_block:
check blck.body.execution_payload.block_hash ==
blck.compute_execution_block_hash()
var cache: StateCache
process_block_header(preState, blck, {}, cache)

Expand Down Expand Up @@ -161,6 +164,13 @@ suite baseDescription & "Execution Payload " & preset():
let payloadValid = os_ops.readFile(
OpExecutionPayloadDir/"pyspec_tests"/path/"execution.yaml"
).contains("execution_valid: true")
if payloadValid and body.is_execution_block and
not body.execution_payload.transactions.anyIt(it.len == 0):
let expectedOk = (path != "incorrect_block_hash")
check expectedOk == (body.execution_payload.block_hash ==
body.compute_execution_block_hash(
preState.latest_block_root(
assignClone(preState)[].hash_tree_root())))
func executePayload(_: capella.ExecutionPayload): bool = payloadValid
process_execution_payload(
preState, body.execution_payload, executePayload)
Expand Down Expand Up @@ -227,4 +237,4 @@ suite baseDescription & "Withdrawals " & preset():
for path in walkTests(OpWithdrawalsDir):
runTest[capella.ExecutionPayload, typeof applyWithdrawals](
OpWithdrawalsDir, suiteName, "Withdrawals", "execution_payload",
applyWithdrawals, path)
applyWithdrawals, path)
18 changes: 14 additions & 4 deletions tests/consensus_spec/deneb/test_fixture_operations.nim
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ import
../fixtures_utils, ../os_ops,
../../helpers/debug_state

from std/sequtils import mapIt, toSeq
from std/sequtils import anyIt, mapIt, toSeq
from std/strutils import contains
from ../../../beacon_chain/spec/beaconstate import
get_base_reward_per_increment, get_state_exit_queue_info,
get_total_active_balance, process_attestation
get_total_active_balance, latest_block_root, process_attestation

const
OpDir = SszTestsDir/const_preset/"deneb"/"operations"
Expand Down Expand Up @@ -114,9 +114,12 @@ suite baseDescription & "Attester Slashing " & preset():
applyAttesterSlashing, path)

suite baseDescription & "Block Header " & preset():
func applyBlockHeader(
proc applyBlockHeader(
preState: var deneb.BeaconState, blck: deneb.BeaconBlock):
Result[void, cstring] =
if blck.is_execution_block:
check blck.body.execution_payload.block_hash ==
blck.compute_execution_block_hash()
var cache: StateCache
process_block_header(preState, blck, {}, cache)

Expand Down Expand Up @@ -164,6 +167,13 @@ suite baseDescription & "Execution Payload " & preset():
let payloadValid = os_ops.readFile(
OpExecutionPayloadDir/"pyspec_tests"/path/"execution.yaml"
).contains("execution_valid: true")
if payloadValid and body.is_execution_block and
not body.execution_payload.transactions.anyIt(it.len == 0):
let expectedOk = (path != "incorrect_block_hash")
check expectedOk == (body.execution_payload.block_hash ==
body.compute_execution_block_hash(
preState.latest_block_root(
assignClone(preState)[].hash_tree_root())))
func executePayload(_: deneb.ExecutionPayload): bool = payloadValid
process_execution_payload(preState, body, executePayload)

Expand Down Expand Up @@ -229,4 +239,4 @@ suite baseDescription & "Withdrawals " & preset():
for path in walkTests(OpWithdrawalsDir):
runTest[deneb.ExecutionPayload, typeof applyWithdrawals](
OpWithdrawalsDir, suiteName, "Withdrawals", "execution_payload",
applyWithdrawals, path)
applyWithdrawals, path)
18 changes: 14 additions & 4 deletions tests/consensus_spec/electra/test_fixture_operations.nim
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ import
../fixtures_utils, ../os_ops,
../../helpers/debug_state

from std/sequtils import mapIt, toSeq
from std/sequtils import anyIt, mapIt, toSeq
from std/strutils import contains
from ../../../beacon_chain/spec/beaconstate import
get_base_reward_per_increment, get_state_exit_queue_info,
get_total_active_balance, process_attestation
get_total_active_balance, latest_block_root, process_attestation

const
OpDir = SszTestsDir/const_preset/"electra"/"operations"
Expand Down Expand Up @@ -121,9 +121,12 @@ suite baseDescription & "Attester Slashing " & preset():
applyAttesterSlashing, path)

suite baseDescription & "Block Header " & preset():
func applyBlockHeader(
proc applyBlockHeader(
preState: var electra.BeaconState, blck: electra.BeaconBlock):
Result[void, cstring] =
if blck.is_execution_block:
check blck.body.execution_payload.block_hash ==
blck.compute_execution_block_hash()
var cache: StateCache
process_block_header(preState, blck, {}, cache)

Expand Down Expand Up @@ -199,6 +202,13 @@ suite baseDescription & "Execution Payload " & preset():
let payloadValid = os_ops.readFile(
OpExecutionPayloadDir/"pyspec_tests"/path/"execution.yaml"
).contains("execution_valid: true")
if payloadValid and body.is_execution_block and
not body.execution_payload.transactions.anyIt(it.len == 0):
let expectedOk = (path != "incorrect_block_hash")
check expectedOk == (body.execution_payload.block_hash ==
body.compute_execution_block_hash(
preState.latest_block_root(
assignClone(preState)[].hash_tree_root())))
func executePayload(_: electra.ExecutionPayload): bool = payloadValid
process_execution_payload(
defaultRuntimeConfig, preState, body, executePayload)
Expand Down Expand Up @@ -281,4 +291,4 @@ suite baseDescription & "Withdrawals " & preset():
for path in walkTests(OpWithdrawalsDir):
runTest[electra.ExecutionPayload, typeof applyWithdrawals](
OpWithdrawalsDir, suiteName, "Withdrawals", "execution_payload",
applyWithdrawals, path)
applyWithdrawals, path)
28 changes: 23 additions & 5 deletions tests/consensus_spec/fixtures_utils.nim
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# beacon_chain
# Copyright (c) 2018-2024 Status Research & Development GmbH
# Copyright (c) 2018-2025 Status Research & Development GmbH
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
Expand All @@ -9,18 +9,18 @@

import
# Standard library
std/[strutils, typetraits],
std/[sequtils, strutils, typetraits],
# Internals
./os_ops,
../../beacon_chain/spec/datatypes/[phase0, altair, bellatrix],
../../beacon_chain/spec/[
eth2_merkleization, eth2_ssz_serialization, forks],
eth2_merkleization, eth2_ssz_serialization, forks, helpers],
# Status libs,
snappy,
stew/byteutils

export
eth2_merkleization, eth2_ssz_serialization
eth2_merkleization, eth2_ssz_serialization, helpers

# Process current EF test format
# ---------------------------------------------
Expand Down Expand Up @@ -173,4 +173,22 @@ proc loadForkedState*(
withState(state[]):
forkyState.data = parseTest(path, SSZ, consensusFork.BeaconState)
forkyState.root = hash_tree_root(forkyState.data)
state
state

proc loadBlock*(
path: string,
consensusFork: static ConsensusFork,
validateBlockHash = true): auto =
var blck = parseTest(path, SSZ, consensusFork.SignedBeaconBlock)
blck.root = hash_tree_root(blck.message)
when consensusFork >= ConsensusFork.Bellatrix:
if blck.message.is_execution_block and
not blck.message.body.execution_payload.transactions.anyIt(it.len == 0):
if blck.message.body.execution_payload.block_hash !=
blck.message.compute_execution_block_hash():
try:
stderr.write "Invalid `block_hash`: ", path, "\n"
except IOError:
discard
quit 1
blck
7 changes: 2 additions & 5 deletions tests/consensus_spec/test_fixture_fork_choice.nim
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# beacon_chain
# Copyright (c) 2018-2024 Status Research & Development GmbH
# Copyright (c) 2018-2025 Status Research & Development GmbH
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
Expand Down Expand Up @@ -119,10 +119,7 @@ proc loadOps(
doAssert step.hasKey"blobs" == step.hasKey"proofs"
withConsensusFork(fork):
let
blck = parseTest(
path/filename & ".ssz_snappy",
SSZ, consensusFork.SignedBeaconBlock)

blck = loadBlock(path/filename & ".ssz_snappy", consensusFork)
blobData =
when consensusFork >= ConsensusFork.Deneb:
if step.hasKey"blobs":
Expand Down
4 changes: 2 additions & 2 deletions tests/consensus_spec/test_fixture_kzg.nim
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ proc runComputeCellsAndKzgProofsTest(suiteName, suitePath, path: string) =
check output.kind == JNull
else:
let p_val = p[].get
for i in 0..<CELLS_PER_EXT_BLOB:
for i in 0..<kzg_abi.CELLS_PER_EXT_BLOB:
check p_val.cells[i].bytes == fromHex[2048](output[0][i].getStr).get
check p_val.proofs[i].bytes == fromHex[48](output[1][i].getStr).get

Expand Down Expand Up @@ -281,7 +281,7 @@ proc runRecoverCellsAndKzgProofsTest(suiteName, suitePath, path: string) =
check output.kind == JNull
else:
let val = v[].get
for i in 0..<CELLS_PER_EXT_BLOB:
for i in 0..<kzg_abi.CELLS_PER_EXT_BLOB:
check val.cells[i].bytes == fromHex[2048](output[0][i].getStr).get
check val.proofs[i].bytes == fromHex[48](output[1][i].getStr).get

Expand Down
Loading
Loading