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

Add BlindBlockUtil for EIP-4844 #6532

Merged
merged 5 commits into from
Dec 2, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

package tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.eip4844;

import static com.google.common.base.Preconditions.checkArgument;

import java.util.Optional;
import org.apache.tuweni.bytes.Bytes32;
import tech.pegasys.teku.bls.BLSSignature;
Expand All @@ -21,6 +23,7 @@
import tech.pegasys.teku.infrastructure.ssz.primitive.SszBytes32;
import tech.pegasys.teku.infrastructure.ssz.tree.TreeNode;
import tech.pegasys.teku.spec.datastructures.blocks.Eth1Data;
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.versions.eip4844.ExecutionPayloadEip4844;
import tech.pegasys.teku.spec.datastructures.execution.versions.eip4844.ExecutionPayloadEip4844Impl;
Expand Down Expand Up @@ -89,6 +92,14 @@ public class BeaconBlockBodyEip4844Impl
super(type, backingNode);
}

public static BeaconBlockBodyEip4844Impl required(final BeaconBlockBody body) {
checkArgument(
body instanceof BeaconBlockBodyEip4844Impl,
"Expected EIP-4844 block body but got %s",
body.getClass());
return (BeaconBlockBodyEip4844Impl) body;
}

@Override
public BLSSignature getRandaoReveal() {
return getField0().getSignature();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Copyright ConsenSys Software Inc., 2022
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/

package tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.eip4844;

import static com.google.common.base.Preconditions.checkState;

import tech.pegasys.teku.spec.datastructures.blocks.BeaconBlock;
import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock;
import tech.pegasys.teku.spec.datastructures.blocks.blockbody.common.AbstractSignedBeaconBlockBlinder;
import tech.pegasys.teku.spec.schemas.SchemaDefinitionsEip4844;

public class SignedBeaconBlockBlinderEip4844 extends AbstractSignedBeaconBlockBlinder {

public SignedBeaconBlockBlinderEip4844(final SchemaDefinitionsEip4844 schemaDefinitions) {
super(schemaDefinitions);
}

@Override
public SignedBeaconBlock blind(final SignedBeaconBlock signedUnblindedBock) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason we can't just use SignedBeaconBlock.blind method here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice question. Will check why it's not called also in Bellatrix, I've followed

final BeaconBlockBodyEip4844Impl unblindedBlockBody =
BeaconBlockBodyEip4844Impl.required(signedUnblindedBock.getMessage().getBody());

final BlindedBeaconBlockBodySchemaEip4844Impl schema =
(BlindedBeaconBlockBodySchemaEip4844Impl)
schemaDefinitions.getBlindedBeaconBlockBodySchema();

final BlindedBeaconBlockBodyEip4844Impl blindedBody =
new BlindedBeaconBlockBodyEip4844Impl(
schema,
unblindedBlockBody.getRandaoRevealSsz(),
unblindedBlockBody.getEth1Data(),
unblindedBlockBody.getGraffitiSsz(),
unblindedBlockBody.getProposerSlashings(),
unblindedBlockBody.getAttesterSlashings(),
unblindedBlockBody.getAttestations(),
unblindedBlockBody.getDeposits(),
unblindedBlockBody.getVoluntaryExits(),
unblindedBlockBody.getSyncAggregate(),
schema
.getExecutionPayloadHeaderSchema()
.createFromExecutionPayload(unblindedBlockBody.getExecutionPayload()),
unblindedBlockBody.getBlsToExecutionChanges(),
unblindedBlockBody.getBlobKzgCommitments());

final BeaconBlock blindedBeaconBlock =
schemaDefinitions
.getBlindedBeaconBlockSchema()
.create(
signedUnblindedBock.getSlot(),
signedUnblindedBock.getProposerIndex(),
signedUnblindedBock.getParentRoot(),
signedUnblindedBock.getStateRoot(),
blindedBody);

checkState(
blindedBeaconBlock.hashTreeRoot().equals(signedUnblindedBock.getMessage().hashTreeRoot()),
"blinded block root do not match original unblinded block root");

return schemaDefinitions
.getSignedBlindedBeaconBlockSchema()
.create(blindedBeaconBlock, signedUnblindedBock.getSignature());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright ConsenSys Software Inc., 2022
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/

package tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.eip4844;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;

import java.util.function.Supplier;
import tech.pegasys.teku.infrastructure.async.SafeFuture;
import tech.pegasys.teku.spec.datastructures.blocks.BeaconBlock;
import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock;
import tech.pegasys.teku.spec.datastructures.blocks.blockbody.common.AbstractSignedBeaconBlockUnblinder;
import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayload;
import tech.pegasys.teku.spec.datastructures.execution.versions.eip4844.ExecutionPayloadEip4844;
import tech.pegasys.teku.spec.schemas.SchemaDefinitionsBellatrix;

public class SignedBeaconBlockUnblinderEip4844 extends AbstractSignedBeaconBlockUnblinder {
protected SafeFuture<ExecutionPayload> executionPayloadFuture;

public SignedBeaconBlockUnblinderEip4844(
final SchemaDefinitionsBellatrix schemaDefinitions,
final SignedBeaconBlock signedBlindedBeaconBlock) {
super(schemaDefinitions, signedBlindedBeaconBlock);
}

@Override
public void setExecutionPayloadSupplier(
final Supplier<SafeFuture<ExecutionPayload>> executionPayloadSupplier) {
this.executionPayloadFuture = executionPayloadSupplier.get();
}

@Override
public SafeFuture<SignedBeaconBlock> unblind() {
BeaconBlock blindedBeaconBlock = signedBlindedBeaconBlock.getMessage();
if (!blindedBeaconBlock.getBody().isBlinded()) {
return SafeFuture.completedFuture(signedBlindedBeaconBlock);
}

checkNotNull(executionPayloadFuture, "executionPayload must be set");

return executionPayloadFuture.thenApply(
executionPayload -> {
ExecutionPayloadEip4844.required(executionPayload);
final BlindedBeaconBlockBodyEip4844 blindedBody =
BlindedBeaconBlockBodyEip4844.required(blindedBeaconBlock.getBody());
checkState(
executionPayload
.hashTreeRoot()
.equals(blindedBody.getExecutionPayloadHeader().hashTreeRoot()),
"executionPayloadHeader root in blinded block do not match provided executionPayload root");
return signedBlindedBeaconBlock.unblind(schemaDefinitions, executionPayload);
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@
import tech.pegasys.teku.spec.logic.versions.bellatrix.helpers.BeaconStateMutatorsBellatrix;
import tech.pegasys.teku.spec.logic.versions.bellatrix.helpers.BellatrixTransitionHelpers;
import tech.pegasys.teku.spec.logic.versions.bellatrix.statetransition.epoch.EpochProcessorBellatrix;
import tech.pegasys.teku.spec.logic.versions.bellatrix.util.BlindBlockUtilBellatrix;
import tech.pegasys.teku.spec.logic.versions.capella.block.BlockProcessorCapella;
import tech.pegasys.teku.spec.logic.versions.eip4844.block.BlockProcessorEip4844;
import tech.pegasys.teku.spec.logic.versions.eip4844.forktransition.Eip4844StateUpgrade;
import tech.pegasys.teku.spec.logic.versions.eip4844.helpers.MiscHelpersEip4844;
import tech.pegasys.teku.spec.logic.versions.eip4844.util.BlindBlockUtilEip4844;
import tech.pegasys.teku.spec.schemas.SchemaDefinitionsEip4844;

public class SpecLogicEip4844 extends AbstractSpecLogic {
Expand Down Expand Up @@ -146,7 +146,7 @@ public static SpecLogicEip4844 create(
final BlockProposalUtil blockProposalUtil =
new BlockProposalUtil(schemaDefinitions, blockProcessor);

final BlindBlockUtilBellatrix blindBlockUtil = new BlindBlockUtilBellatrix(schemaDefinitions);
final BlindBlockUtilEip4844 blindBlockUtil = new BlindBlockUtilEip4844(schemaDefinitions);

// State upgrade
final Eip4844StateUpgrade stateUpgrade =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright ConsenSys Software Inc., 2022
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/

package tech.pegasys.teku.spec.logic.versions.eip4844.util;

import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock;
import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlockBlinder;
import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlockUnblinder;
import tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.eip4844.SignedBeaconBlockBlinderEip4844;
import tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.eip4844.SignedBeaconBlockUnblinderEip4844;
import tech.pegasys.teku.spec.logic.common.util.BlindBlockUtil;
import tech.pegasys.teku.spec.schemas.SchemaDefinitionsEip4844;

public class BlindBlockUtilEip4844 extends BlindBlockUtil {
private final SchemaDefinitionsEip4844 schemaDefinitions;
private final SignedBeaconBlockBlinder signedBeaconBlockBlinder;

public BlindBlockUtilEip4844(final SchemaDefinitionsEip4844 schemaDefinitions) {
this.schemaDefinitions = schemaDefinitions;
this.signedBeaconBlockBlinder = new SignedBeaconBlockBlinderEip4844(schemaDefinitions);
}

@Override
protected SignedBeaconBlockUnblinder createSignedBeaconBlockUnblinder(
final SignedBeaconBlock signedBeaconBlock) {
return new SignedBeaconBlockUnblinderEip4844(schemaDefinitions, signedBeaconBlock);
}

@Override
protected SignedBeaconBlockBlinder getSignedBeaconBlockBlinder() {
return signedBeaconBlockBlinder;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* Copyright ConsenSys Software Inc., 2022
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/

package tech.pegasys.teku.spec.logic.common.util;

import static org.assertj.core.api.Assertions.assertThat;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.TestTemplate;
import tech.pegasys.teku.infrastructure.async.SafeFuture;
import tech.pegasys.teku.spec.Spec;
import tech.pegasys.teku.spec.SpecMilestone;
import tech.pegasys.teku.spec.SpecVersion;
import tech.pegasys.teku.spec.TestSpecContext;
import tech.pegasys.teku.spec.TestSpecInvocationContextProvider.SpecContext;
import tech.pegasys.teku.spec.datastructures.blocks.BeaconBlock;
import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock;
import tech.pegasys.teku.spec.schemas.SchemaDefinitionsBellatrix;
import tech.pegasys.teku.spec.util.DataStructureUtil;

@TestSpecContext(milestone = {SpecMilestone.BELLATRIX, SpecMilestone.EIP4844})
class BlindBlockUtilTest {

private Spec spec;
private DataStructureUtil dataStructureUtil;
private BlindBlockUtil blindBlockUtil;

@BeforeEach
void setUp(final SpecContext specContext) {
spec = specContext.getSpec();
dataStructureUtil = specContext.getDataStructureUtil();
final SpecVersion specVersion = spec.forMilestone(specContext.getSpecMilestone());
blindBlockUtil = specVersion.getBlindBlockUtil().orElseThrow();
}

@TestTemplate
void shouldBlindAndUnblindBlock(final SpecContext specContext) {
Fixed Show fixed Hide fixed
final SignedBeaconBlock signedBeaconBlock = dataStructureUtil.randomSignedBeaconBlock();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CodeQL is actually right :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

assertThat(signedBeaconBlock.isBlinded()).isFalse();
final SignedBeaconBlock blindSignedBeaconBlock =
blindBlockUtil.blindSignedBeaconBlock(signedBeaconBlock);
assertThat(blindSignedBeaconBlock.isBlinded()).isTrue();
assertThat(blindSignedBeaconBlock.getBodyRoot()).isEqualTo(signedBeaconBlock.getBodyRoot());
assertThat(blindSignedBeaconBlock.getMessage().getBody().getOptionalExecutionPayload())
.isEmpty();
assertThat(blindSignedBeaconBlock.getMessage().getBody().getOptionalExecutionPayloadHeader())
.isNotEmpty();

final SafeFuture<SignedBeaconBlock> signedBeaconBlockSafeFuture =
blindBlockUtil.unblindSignedBeaconBlock(
blindSignedBeaconBlock,
unblinder -> {
final BeaconBlock block = unblinder.getSignedBlindedBeaconBlock().getMessage();

if (block
.getBody()
.getOptionalExecutionPayloadHeader()
.orElseThrow()
.isHeaderOfDefaultPayload()) {
// Terminal block not reached, provide default payload
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

youre providing a random block, so you'll never fall in this code path so you can leave only the code in the else

unblinder.setExecutionPayloadSupplier(
() ->
SafeFuture.completedFuture(
SchemaDefinitionsBellatrix.required(
spec.atSlot(block.getSlot()).getSchemaDefinitions())
.getExecutionPayloadSchema()
.getDefault()));
} else {
unblinder.setExecutionPayloadSupplier(
() ->
SafeFuture.completedFuture(
signedBeaconBlock
.getBeaconBlock()
.orElseThrow()
.getBody()
.getOptionalExecutionPayload()
.orElseThrow()));
}
});

final SignedBeaconBlock unblindedSignedBeaconBlock =
signedBeaconBlockSafeFuture.getImmediately();
assertThat(unblindedSignedBeaconBlock).isEqualTo(signedBeaconBlock);
assertThat(
unblindedSignedBeaconBlock
.getBeaconBlock()
.orElseThrow()
.getBody()
.getOptionalExecutionPayload())
.isNotEmpty();
assertThat(
unblindedSignedBeaconBlock
.getBeaconBlock()
.orElseThrow()
.getBody()
.getOptionalExecutionPayloadHeader())
.isEmpty();
}
}