diff --git a/eth-reference-tests/src/referenceTest/java/tech/pegasys/teku/reference/common/operations/DefaultOperationProcessor.java b/eth-reference-tests/src/referenceTest/java/tech/pegasys/teku/reference/common/operations/DefaultOperationProcessor.java index d905d97f528..7ef04910664 100644 --- a/eth-reference-tests/src/referenceTest/java/tech/pegasys/teku/reference/common/operations/DefaultOperationProcessor.java +++ b/eth-reference-tests/src/referenceTest/java/tech/pegasys/teku/reference/common/operations/DefaultOperationProcessor.java @@ -14,14 +14,19 @@ package tech.pegasys.teku.reference.common.operations; import java.util.Optional; +import java.util.function.Supplier; import tech.pegasys.teku.bls.BLSSignatureVerifier; +import tech.pegasys.teku.infrastructure.ssz.SszList; import tech.pegasys.teku.spec.Spec; import tech.pegasys.teku.spec.datastructures.blocks.BeaconBlockSummary; import tech.pegasys.teku.spec.datastructures.blocks.blockbody.BeaconBlockBody; import tech.pegasys.teku.spec.datastructures.blocks.blockbody.BeaconBlockBodySchema; import tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.altair.SyncAggregate; import tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.capella.BeaconBlockBodySchemaCapella; +import tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.electra.BeaconBlockBodySchemaElectra; import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadSummary; +import tech.pegasys.teku.spec.datastructures.execution.versions.electra.DepositReceipt; +import tech.pegasys.teku.spec.datastructures.execution.versions.electra.ExecutionLayerExit; import tech.pegasys.teku.spec.datastructures.operations.Attestation; import tech.pegasys.teku.spec.datastructures.operations.AttesterSlashing; import tech.pegasys.teku.spec.datastructures.operations.Deposit; @@ -29,10 +34,12 @@ import tech.pegasys.teku.spec.datastructures.operations.SignedBlsToExecutionChange; import tech.pegasys.teku.spec.datastructures.operations.SignedVoluntaryExit; import tech.pegasys.teku.spec.datastructures.state.beaconstate.MutableBeaconState; +import tech.pegasys.teku.spec.logic.common.helpers.BeaconStateMutators.ValidatorExitContext; import tech.pegasys.teku.spec.logic.common.statetransition.exceptions.BlockProcessingException; import tech.pegasys.teku.spec.logic.versions.bellatrix.block.OptimisticExecutionPayloadExecutor; public class DefaultOperationProcessor implements OperationProcessor { + private final Spec spec; private final BeaconBlockBodySchema beaconBlockBodySchema; @@ -132,4 +139,34 @@ public void processWithdrawals( throws BlockProcessingException { spec.getBlockProcessor(state.getSlot()).processWithdrawals(state, payloadSummary); } + + @Override + public void processDepositReceipt( + final MutableBeaconState state, final DepositReceipt depositReceipt) + throws BlockProcessingException { + final SszList depositReceiptList = + BeaconBlockBodySchemaElectra.required(beaconBlockBodySchema) + .getExecutionPayloadSchema() + .getDepositReceiptsSchemaRequired() + .of(depositReceipt); + + spec.getBlockProcessor(state.getSlot()).processDepositReceipts(state, depositReceiptList); + } + + @Override + public void processExecutionLayerExit( + final MutableBeaconState state, final ExecutionLayerExit executionLayerExit) + throws BlockProcessingException { + final SszList exits = + BeaconBlockBodySchemaElectra.required(beaconBlockBodySchema) + .getExecutionPayloadSchema() + .getExecutionLayerExitsSchemaRequired() + .of(executionLayerExit); + final Supplier validatorExitContextSupplier = + spec.atSlot(state.getSlot()) + .beaconStateMutators() + .createValidatorExitContextSupplier(state); + spec.getBlockProcessor(state.getSlot()) + .processExecutionLayerExits(state, exits, validatorExitContextSupplier); + } } diff --git a/eth-reference-tests/src/referenceTest/java/tech/pegasys/teku/reference/common/operations/OperationProcessor.java b/eth-reference-tests/src/referenceTest/java/tech/pegasys/teku/reference/common/operations/OperationProcessor.java index de6475205a0..fe6be3115b9 100644 --- a/eth-reference-tests/src/referenceTest/java/tech/pegasys/teku/reference/common/operations/OperationProcessor.java +++ b/eth-reference-tests/src/referenceTest/java/tech/pegasys/teku/reference/common/operations/OperationProcessor.java @@ -18,6 +18,8 @@ import tech.pegasys.teku.spec.datastructures.blocks.blockbody.BeaconBlockBody; import tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.altair.SyncAggregate; import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadSummary; +import tech.pegasys.teku.spec.datastructures.execution.versions.electra.DepositReceipt; +import tech.pegasys.teku.spec.datastructures.execution.versions.electra.ExecutionLayerExit; import tech.pegasys.teku.spec.datastructures.operations.Attestation; import tech.pegasys.teku.spec.datastructures.operations.AttesterSlashing; import tech.pegasys.teku.spec.datastructures.operations.Deposit; @@ -62,4 +64,10 @@ void processBlsToExecutionChange( void processWithdrawals(MutableBeaconState state, ExecutionPayloadSummary payloadSummary) throws BlockProcessingException; + + void processDepositReceipt(final MutableBeaconState state, final DepositReceipt depositReceipt) + throws BlockProcessingException; + + void processExecutionLayerExit(MutableBeaconState state, ExecutionLayerExit executionLayerExit) + throws BlockProcessingException; } diff --git a/eth-reference-tests/src/referenceTest/java/tech/pegasys/teku/reference/common/operations/OperationsTestExecutor.java b/eth-reference-tests/src/referenceTest/java/tech/pegasys/teku/reference/common/operations/OperationsTestExecutor.java index 61caa502ae2..dc58e25846c 100644 --- a/eth-reference-tests/src/referenceTest/java/tech/pegasys/teku/reference/common/operations/OperationsTestExecutor.java +++ b/eth-reference-tests/src/referenceTest/java/tech/pegasys/teku/reference/common/operations/OperationsTestExecutor.java @@ -34,6 +34,8 @@ import tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.altair.BeaconBlockBodySchemaAltair; import tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.altair.SyncAggregate; import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayload; +import tech.pegasys.teku.spec.datastructures.execution.versions.electra.DepositReceipt; +import tech.pegasys.teku.spec.datastructures.execution.versions.electra.ExecutionLayerExit; import tech.pegasys.teku.spec.datastructures.operations.Attestation; import tech.pegasys.teku.spec.datastructures.operations.AttesterSlashing; import tech.pegasys.teku.spec.datastructures.operations.Deposit; @@ -71,7 +73,9 @@ private enum Operation { SYNC_AGGREGATE, EXECUTION_PAYLOAD, BLS_TO_EXECUTION_CHANGE, - WITHDRAWAL + WITHDRAWAL, + DEPOSIT_RECEIPT, + EXECUTION_LAYER_EXIT } public static final ImmutableMap OPERATIONS_TEST_TYPES = @@ -112,6 +116,13 @@ private enum Operation { .put( "operations/withdrawals", new OperationsTestExecutor<>("execution_payload.ssz_snappy", Operation.WITHDRAWAL)) + .put( + "operations/deposit_receipt", + new OperationsTestExecutor<>("deposit_receipt.ssz_snappy", Operation.DEPOSIT_RECEIPT)) + .put( + "operations/execution_layer_exit", + new OperationsTestExecutor<>( + "execution_layer_exit.ssz_snappy", Operation.EXECUTION_LAYER_EXIT)) .build(); private final String dataFileName; @@ -298,6 +309,8 @@ private void processOperation( } case BLS_TO_EXECUTION_CHANGE -> processBlsToExecutionChange(testDefinition, state, processor); case WITHDRAWAL -> processWithdrawal(testDefinition, state, processor); + case DEPOSIT_RECEIPT -> processDepositReceipt(testDefinition, state, processor); + case EXECUTION_LAYER_EXIT -> processExecutionLayerExit(testDefinition, state, processor); default -> throw new UnsupportedOperationException( "Operation " + operation + " not implemented in OperationTestExecutor"); } @@ -325,6 +338,26 @@ private void processBlsToExecutionChange( processor.processBlsToExecutionChange(state, blsToExecutionChange); } + private void processDepositReceipt( + final TestDefinition testDefinition, + final MutableBeaconState state, + final OperationProcessor processor) + throws BlockProcessingException { + final DepositReceipt depositReceipt = + loadSsz(testDefinition, dataFileName, DepositReceipt.SSZ_SCHEMA); + processor.processDepositReceipt(state, depositReceipt); + } + + private void processExecutionLayerExit( + final TestDefinition testDefinition, + final MutableBeaconState state, + final OperationProcessor processor) + throws BlockProcessingException { + final ExecutionLayerExit executionLayerExit = + loadSsz(testDefinition, dataFileName, ExecutionLayerExit.SSZ_SCHEMA); + processor.processExecutionLayerExit(state, executionLayerExit); + } + private SignedVoluntaryExit loadVoluntaryExit(final TestDefinition testDefinition) { return loadSsz(testDefinition, dataFileName, SignedVoluntaryExit.SSZ_SCHEMA); } diff --git a/eth-tests/src/main/java/tech/pegasys/teku/ethtests/TestFork.java b/eth-tests/src/main/java/tech/pegasys/teku/ethtests/TestFork.java index 620c1355be9..e69ddbe4b85 100644 --- a/eth-tests/src/main/java/tech/pegasys/teku/ethtests/TestFork.java +++ b/eth-tests/src/main/java/tech/pegasys/teku/ethtests/TestFork.java @@ -19,4 +19,5 @@ public class TestFork { public static final String BELLATRIX = "bellatrix"; public static final String CAPELLA = "capella"; public static final String DENEB = "deneb"; + public static final String ELECTRA = "electra"; } diff --git a/eth-tests/src/main/java/tech/pegasys/teku/ethtests/finder/ReferenceTestFinder.java b/eth-tests/src/main/java/tech/pegasys/teku/ethtests/finder/ReferenceTestFinder.java index 1edf610da6e..656471c79c4 100644 --- a/eth-tests/src/main/java/tech/pegasys/teku/ethtests/finder/ReferenceTestFinder.java +++ b/eth-tests/src/main/java/tech/pegasys/teku/ethtests/finder/ReferenceTestFinder.java @@ -31,7 +31,12 @@ public class ReferenceTestFinder { Path.of("src", "referenceTest", "resources", "consensus-spec-tests", "tests"); private static final List SUPPORTED_FORKS = List.of( - TestFork.PHASE0, TestFork.ALTAIR, TestFork.BELLATRIX, TestFork.CAPELLA, TestFork.DENEB); + TestFork.PHASE0, + TestFork.ALTAIR, + TestFork.BELLATRIX, + TestFork.CAPELLA, + TestFork.DENEB, + TestFork.ELECTRA); @MustBeClosed public static Stream findReferenceTests() throws IOException { diff --git a/eth-tests/src/main/java/tech/pegasys/teku/ethtests/finder/TestDefinition.java b/eth-tests/src/main/java/tech/pegasys/teku/ethtests/finder/TestDefinition.java index 5a79766d0a6..951bbe64e55 100644 --- a/eth-tests/src/main/java/tech/pegasys/teku/ethtests/finder/TestDefinition.java +++ b/eth-tests/src/main/java/tech/pegasys/teku/ethtests/finder/TestDefinition.java @@ -72,6 +72,7 @@ private void createSpec() { case TestFork.BELLATRIX -> SpecMilestone.BELLATRIX; case TestFork.CAPELLA -> SpecMilestone.CAPELLA; case TestFork.DENEB -> SpecMilestone.DENEB; + case TestFork.ELECTRA -> SpecMilestone.ELECTRA; default -> throw new IllegalArgumentException("Unknown fork: " + fork); }; spec = TestSpecFactory.create(milestone, network); diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/common/block/AbstractBlockProcessor.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/common/block/AbstractBlockProcessor.java index 8cf8fea7fd3..252a9ff2448 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/common/block/AbstractBlockProcessor.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/common/block/AbstractBlockProcessor.java @@ -47,6 +47,7 @@ import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock; import tech.pegasys.teku.spec.datastructures.blocks.blockbody.BeaconBlockBody; import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayload; +import tech.pegasys.teku.spec.datastructures.execution.versions.electra.DepositReceipt; import tech.pegasys.teku.spec.datastructures.execution.versions.electra.ExecutionLayerExit; import tech.pegasys.teku.spec.datastructures.operations.Attestation; import tech.pegasys.teku.spec.datastructures.operations.AttestationData; @@ -884,11 +885,19 @@ protected void processExecutionLayerExits( // No ExecutionLayer exits until Electra } + @Override + public void processDepositReceipts( + final MutableBeaconState state, final SszList depositReceipts) + throws BlockProcessingException { + // No DepositReceipts until Electra + } + @Override public void processExecutionLayerExits( final MutableBeaconState state, final SszList exits, - final Supplier validatorExitContextSupplier) { + final Supplier validatorExitContextSupplier) + throws BlockProcessingException { // No ExecutionLayer exits until Electra } diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/common/block/BlockProcessor.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/common/block/BlockProcessor.java index e7c10800f26..d125c5b938a 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/common/block/BlockProcessor.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/common/block/BlockProcessor.java @@ -32,6 +32,7 @@ import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadSummary; import tech.pegasys.teku.spec.datastructures.execution.NewPayloadRequest; import tech.pegasys.teku.spec.datastructures.execution.versions.capella.Withdrawal; +import tech.pegasys.teku.spec.datastructures.execution.versions.electra.DepositReceipt; import tech.pegasys.teku.spec.datastructures.execution.versions.electra.ExecutionLayerExit; import tech.pegasys.teku.spec.datastructures.operations.Attestation; import tech.pegasys.teku.spec.datastructures.operations.AttestationData; @@ -167,10 +168,15 @@ void processBlsToExecutionChanges( void processWithdrawals(MutableBeaconState state, ExecutionPayloadSummary payloadSummary) throws BlockProcessingException; + void processDepositReceipts( + final MutableBeaconState state, final SszList depositReceipts) + throws BlockProcessingException; + void processExecutionLayerExits( final MutableBeaconState state, final SszList exits, - final Supplier validatorExitContextSupplier); + final Supplier validatorExitContextSupplier) + throws BlockProcessingException; Optional> getExpectedWithdrawals(BeaconState preState); diff --git a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/electra/block/BlockProcessorElectra.java b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/electra/block/BlockProcessorElectra.java index ca2b7c66363..2cbab8393d1 100644 --- a/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/electra/block/BlockProcessorElectra.java +++ b/ethereum/spec/src/main/java/tech/pegasys/teku/spec/logic/versions/electra/block/BlockProcessorElectra.java @@ -142,7 +142,8 @@ protected void processExecutionLayerExits( public void processExecutionLayerExits( final MutableBeaconState state, final SszList exits, - final Supplier validatorExitContextSupplier) { + final Supplier validatorExitContextSupplier) + throws BlockProcessingException { final UInt64 currentEpoch = miscHelpers.computeEpochAtSlot(state.getSlot()); exits.forEach( @@ -210,14 +211,17 @@ private SszList getExecutionLayerExitsFromBlock( /* Implements process_deposit_receipt from consensus-specs (EIP-6110) */ + @Override public void processDepositReceipts( - final MutableBeaconStateElectra state, final SszList depositReceipts) { + final MutableBeaconState state, final SszList depositReceipts) + throws BlockProcessingException { + final MutableBeaconStateElectra electraState = MutableBeaconStateElectra.required(state); for (DepositReceipt depositReceipt : depositReceipts) { // process_deposit_receipt - if (state + if (electraState .getDepositReceiptsStartIndex() .equals(SpecConfigElectra.UNSET_DEPOSIT_RECEIPTS_START_INDEX)) { - state.setDepositReceiptsStartIndex(depositReceipt.getIndex()); + electraState.setDepositReceiptsStartIndex(depositReceipt.getIndex()); } applyDeposit( state, diff --git a/ethereum/spec/src/test/java/tech/pegasys/teku/spec/logic/versions/electra/block/BlockProcessorElectraTest.java b/ethereum/spec/src/test/java/tech/pegasys/teku/spec/logic/versions/electra/block/BlockProcessorElectraTest.java index 73ddd0ba8b4..cff70721b67 100644 --- a/ethereum/spec/src/test/java/tech/pegasys/teku/spec/logic/versions/electra/block/BlockProcessorElectraTest.java +++ b/ethereum/spec/src/test/java/tech/pegasys/teku/spec/logic/versions/electra/block/BlockProcessorElectraTest.java @@ -105,7 +105,7 @@ public void verifiesOutstandingEth1DepositsAreProcessed() { } @Test - public void processesDepositReceipts() { + public void processesDepositReceipts() throws BlockProcessingException { final BeaconStateElectra preState = BeaconStateElectra.required( createBeaconState() @@ -129,7 +129,7 @@ public void processesDepositReceipts() { UInt64.valueOf(firstElectraDepositReceiptIndex + i))) .toList(); - final BeaconStateElectra state = + final BeaconState state = BeaconStateElectra.required( preState.updated( mutableState -> @@ -139,7 +139,7 @@ public void processesDepositReceipts() { depositReceiptsSchema.createFromElements(depositReceipts)))); // verify deposit_receipts_start_index has been set - assertThat(state.getDepositReceiptsStartIndex()) + assertThat(BeaconStateElectra.required(state).getDepositReceiptsStartIndex()) .isEqualTo(UInt64.valueOf(firstElectraDepositReceiptIndex)); // verify validators have been added to the state assertThat(state.getValidators().size())