Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use EF consensus spec v1.5.0-beta.2 test vectors #6909

Merged
merged 1 commit into from
Feb 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
811 changes: 801 additions & 10 deletions ConsensusSpecPreset-mainnet.md

Large diffs are not rendered by default.

934 changes: 923 additions & 11 deletions ConsensusSpecPreset-minimal.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion beacon_chain/spec/datatypes/base.nim
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export
tables, results, endians2, json_serialization, sszTypes, beacon_time, crypto,
digest, presets

const SPEC_VERSION* = "1.5.0-beta.1"
const SPEC_VERSION* = "1.5.0-beta.2"
## Spec version we're aiming to be compatible with, right now

const
Expand Down
25 changes: 0 additions & 25 deletions beacon_chain/spec/forks.nim
Original file line number Diff line number Diff line change
Expand Up @@ -631,31 +631,6 @@ template Forky*(
kind: static ConsensusFork): auto =
kind.SignedBeaconBlock

# Workaround method used for tests that involve walking through
# `nim-eth2-scenarios` fork dirs, to be removed once Fulu is
# included in new release.
template withAllButFulu*(
x: typedesc[ConsensusFork], body: untyped): untyped =
static: doAssert ConsensusFork.high == ConsensusFork.Fulu
block:
const consensusFork {.inject, used.} = ConsensusFork.Electra
body
block:
const consensusFork {.inject, used.} = ConsensusFork.Deneb
body
block:
const consensusFork {.inject, used.} = ConsensusFork.Capella
body
block:
const consensusFork {.inject, used.} = ConsensusFork.Bellatrix
body
block:
const consensusFork {.inject, used.} = ConsensusFork.Altair
body
block:
const consensusFork {.inject, used.} = ConsensusFork.Phase0
body

template withAll*(
x: typedesc[ConsensusFork], body: untyped): untyped =
static: doAssert ConsensusFork.high == ConsensusFork.Fulu
Expand Down
6 changes: 4 additions & 2 deletions tests/consensus_spec/fulu/all_fulu_fixtures.nim
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# beacon_chain
# Copyright (c) 2022-2024 Status Research & Development GmbH
# Copyright (c) 2022-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,4 +9,6 @@
{.used.}

import
./test_fixture_ssz_consensus_objects
./test_fixture_operations,
./test_fixture_ssz_consensus_objects,
./test_fixture_state_transition_epoch
294 changes: 294 additions & 0 deletions tests/consensus_spec/fulu/test_fixture_operations.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,294 @@
# beacon_chain
# Copyright (c) 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).
# at your option. This file may not be copied, modified, or distributed except according to those terms.

{.push raises: [].}
{.used.}

import
# Utilities
chronicles,
unittest2,
# Beacon chain internals
../../../beacon_chain/spec/state_transition_block,
../../../beacon_chain/spec/datatypes/fulu,
# Test utilities
../../testutil,
../fixtures_utils, ../os_ops,
../../helpers/debug_state

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, latest_block_root, process_attestation

const
OpDir = SszTestsDir/const_preset/"fulu"/"operations"
OpAttestationsDir = OpDir/"attestation"
OpAttSlashingDir = OpDir/"attester_slashing"
OpBlockHeaderDir = OpDir/"block_header"
OpBlsToExecutionChangeDir = OpDir/"bls_to_execution_change"
OpConsolidationRequestDir = OpDir/"consolidation_request"
OpDepositRequestDir = OpDir/"deposit_request"
OpDepositsDir = OpDir/"deposit"
OpWithdrawalRequestDir = OpDir/"withdrawal_request"
OpExecutionPayloadDir = OpDir/"execution_payload"
OpProposerSlashingDir = OpDir/"proposer_slashing"
OpSyncAggregateDir = OpDir/"sync_aggregate"
OpVoluntaryExitDir = OpDir/"voluntary_exit"
OpWithdrawalsDir = OpDir/"withdrawals"

baseDescription = "EF - Fulu - Operations - "


const testDirs = toHashSet([
OpAttestationsDir, OpAttSlashingDir, OpBlockHeaderDir,
OpBlsToExecutionChangeDir, OpConsolidationRequestDir, OpDepositRequestDir,
OpDepositsDir, OpWithdrawalRequestDir, OpExecutionPayloadDir,
OpProposerSlashingDir, OpSyncAggregateDir, OpVoluntaryExitDir,
OpWithdrawalsDir])

doAssert toHashSet(
mapIt(toSeq(walkDir(OpDir, relative = false)), it.path)) == testDirs

proc runTest[T, U](
testSuiteDir, suiteName, opName, applyFile: string,
applyProc: U, identifier: string) =
let testDir = testSuiteDir / "pyspec_tests" / identifier

let prefix =
if fileExists(testDir/"post.ssz_snappy"):
"[Valid] "
else:
"[Invalid] "

test prefix & baseDescription & opName & " - " & identifier:
let preState = newClone(
parseTest(testDir/"pre.ssz_snappy", SSZ, fulu.BeaconState))
let done = applyProc(
preState[], parseTest(testDir/(applyFile & ".ssz_snappy"), SSZ, T))

if fileExists(testDir/"post.ssz_snappy"):
let postState =
newClone(parseTest(
testDir/"post.ssz_snappy", SSZ, fulu.BeaconState))

reportDiff(preState, postState)
check:
done.isOk()
preState[].hash_tree_root() == postState[].hash_tree_root()
else:
check: done.isErr() # No post state = processing should fail

suite baseDescription & "Attestation " & preset():
proc applyAttestation(
preState: var fulu.BeaconState, attestation: electra.Attestation):
Result[void, cstring] =
var cache: StateCache
let
total_active_balance = get_total_active_balance(preState, cache)
base_reward_per_increment =
get_base_reward_per_increment(total_active_balance)

# This returns the proposer reward for including the attestation, which
# isn't tested here.
discard ? process_attestation(
preState, attestation, {strictVerification}, base_reward_per_increment, cache)
ok()

for path in walkTests(OpAttestationsDir):
runTest[electra.Attestation, typeof applyAttestation](
OpAttestationsDir, suiteName, "Attestation", "attestation",
applyAttestation, path)

suite baseDescription & "Attester Slashing " & preset():
proc applyAttesterSlashing(
preState: var fulu.BeaconState,
attesterSlashing: electra.AttesterSlashing): Result[void, cstring] =
var cache: StateCache
doAssert (? process_attester_slashing(
defaultRuntimeConfig, preState, attesterSlashing, {},
get_state_exit_queue_info(preState), cache))[0] > 0.Gwei
ok()

for path in walkTests(OpAttSlashingDir):
runTest[electra.AttesterSlashing, typeof applyAttesterSlashing](
OpAttSlashingDir, suiteName, "Attester Slashing", "attester_slashing",
applyAttesterSlashing, path)

suite baseDescription & "Block Header " & preset():
proc applyBlockHeader(
preState: var fulu.BeaconState, blck: fulu.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)

for path in walkTests(OpBlockHeaderDir):
runTest[fulu.BeaconBlock, typeof applyBlockHeader](
OpBlockHeaderDir, suiteName, "Block Header", "block",
applyBlockHeader, path)

from ../../../beacon_chain/spec/datatypes/capella import
SignedBLSToExecutionChange

suite baseDescription & "BLS to execution change " & preset():
proc applyBlsToExecutionChange(
preState: var fulu.BeaconState,
signed_address_change: SignedBLSToExecutionChange):
Result[void, cstring] =
process_bls_to_execution_change(
defaultRuntimeConfig, preState, signed_address_change)

for path in walkTests(OpBlsToExecutionChangeDir):
runTest[SignedBLSToExecutionChange, typeof applyBlsToExecutionChange](
OpBlsToExecutionChangeDir, suiteName, "BLS to execution change", "address_change",
applyBlsToExecutionChange, path)

from ".."/".."/".."/beacon_chain/validator_bucket_sort import
sortValidatorBuckets

suite baseDescription & "Consolidation Request " & preset():
proc applyConsolidationRequest(
preState: var fulu.BeaconState,
consolidation_request: ConsolidationRequest): Result[void, cstring] =
var cache: StateCache
process_consolidation_request(
defaultRuntimeConfig, preState,
sortValidatorBuckets(preState.validators.asSeq)[],
consolidation_request, cache)
ok()

for path in walkTests(OpConsolidationRequestDir):
runTest[ConsolidationRequest, typeof applyConsolidationRequest](
OpConsolidationRequestDir, suiteName, "Consolidation Request",
"consolidation_request", applyConsolidationRequest, path)

suite baseDescription & "Deposit " & preset():
func applyDeposit(
preState: var fulu.BeaconState, deposit: Deposit):
Result[void, cstring] =
process_deposit(
defaultRuntimeConfig, preState,
sortValidatorBuckets(preState.validators.asSeq)[], deposit, {})

for path in walkTests(OpDepositsDir):
runTest[Deposit, typeof applyDeposit](
OpDepositsDir, suiteName, "Deposit", "deposit", applyDeposit, path)

suite baseDescription & "Deposit Request " & preset():
func applyDepositRequest(
preState: var fulu.BeaconState, depositRequest: DepositRequest):
Result[void, cstring] =
process_deposit_request(
defaultRuntimeConfig, preState, depositRequest, {})

for path in walkTests(OpDepositRequestDir):
runTest[DepositRequest, typeof applyDepositRequest](
OpDepositRequestDir, suiteName, "Deposit Request", "deposit_request",
applyDepositRequest, path)

suite baseDescription & "Execution Payload " & preset():
func makeApplyExecutionPayloadCb(path: string): auto =
return proc(
preState: var fulu.BeaconState, body: fulu.BeaconBlockBody):
Result[void, cstring] {.raises: [IOError].} =
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(_: fulu.ExecutionPayload): bool = payloadValid
process_execution_payload(
defaultRuntimeConfig, preState, body, executePayload)

for path in walkTests(OpExecutionPayloadDir):
let applyExecutionPayload = makeApplyExecutionPayloadCb(path)
runTest[fulu.BeaconBlockBody, typeof applyExecutionPayload](
OpExecutionPayloadDir, suiteName, "Execution Payload", "body",
applyExecutionPayload, path)

suite baseDescription & "Withdrawal Request " & preset():
func applyWithdrawalRequest(
preState: var fulu.BeaconState, withdrawalRequest: WithdrawalRequest):
Result[void, cstring] =
var cache: StateCache
process_withdrawal_request(
defaultRuntimeConfig, preState,
sortValidatorBuckets(preState.validators.asSeq)[], withdrawalRequest,
cache)
ok()

for path in walkTests(OpWithdrawalRequestDir):
runTest[WithdrawalRequest, typeof applyWithdrawalRequest](
OpWithdrawalRequestDir, suiteName, "Withdrawal Request",
"withdrawal_request", applyWithdrawalRequest, path)

suite baseDescription & "Proposer Slashing " & preset():
proc applyProposerSlashing(
preState: var fulu.BeaconState, proposerSlashing: ProposerSlashing):
Result[void, cstring] =
var cache: StateCache
doAssert (? process_proposer_slashing(
defaultRuntimeConfig, preState, proposerSlashing, {},
get_state_exit_queue_info(preState), cache))[0] > 0.Gwei
ok()

for path in walkTests(OpProposerSlashingDir):
runTest[ProposerSlashing, typeof applyProposerSlashing](
OpProposerSlashingDir, suiteName, "Proposer Slashing", "proposer_slashing",
applyProposerSlashing, path)

suite baseDescription & "Sync Aggregate " & preset():
proc applySyncAggregate(
preState: var fulu.BeaconState, syncAggregate: SyncAggregate):
Result[void, cstring] =
var cache: StateCache
discard ? process_sync_aggregate(
preState, syncAggregate, get_total_active_balance(preState, cache),
{}, cache)
ok()

for path in walkTests(OpSyncAggregateDir):
runTest[SyncAggregate, typeof applySyncAggregate](
OpSyncAggregateDir, suiteName, "Sync Aggregate", "sync_aggregate",
applySyncAggregate, path)

suite baseDescription & "Voluntary Exit " & preset():
proc applyVoluntaryExit(
preState: var fulu.BeaconState, voluntaryExit: SignedVoluntaryExit):
Result[void, cstring] =
var cache: StateCache
if process_voluntary_exit(
defaultRuntimeConfig, preState, voluntaryExit, {},
get_state_exit_queue_info(preState), cache).isOk:
ok()
else:
err("")

for path in walkTests(OpVoluntaryExitDir):
runTest[SignedVoluntaryExit, typeof applyVoluntaryExit](
OpVoluntaryExitDir, suiteName, "Voluntary Exit", "voluntary_exit",
applyVoluntaryExit, path)

suite baseDescription & "Withdrawals " & preset():
func applyWithdrawals(
preState: var fulu.BeaconState,
executionPayload: fulu.ExecutionPayload): Result[void, cstring] =
process_withdrawals(preState, executionPayload)

for path in walkTests(OpWithdrawalsDir):
runTest[fulu.ExecutionPayload, typeof applyWithdrawals](
OpWithdrawalsDir, suiteName, "Withdrawals", "execution_payload",
applyWithdrawals, path)
Loading
Loading