Skip to content

Commit

Permalink
[Decoupling] Implement BlockFactoryDeneb (part 2) (#7161)
Browse files Browse the repository at this point in the history
  • Loading branch information
StefanBratanov authored May 22, 2023
1 parent 021e33d commit 87d7095
Show file tree
Hide file tree
Showing 29 changed files with 967 additions and 397 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright ConsenSys Software Inc., 2023
*
* 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.validator.coordinator;

import tech.pegasys.teku.infrastructure.async.SafeFuture;
import tech.pegasys.teku.spec.Spec;
import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock;

public abstract class AbstractBlockFactory implements BlockFactory {

protected final Spec spec;
protected final BlockOperationSelectorFactory operationSelector;

protected AbstractBlockFactory(
final Spec spec, final BlockOperationSelectorFactory operationSelector) {
this.spec = spec;
this.operationSelector = operationSelector;
}

@Override
public SafeFuture<SignedBeaconBlock> unblindSignedBeaconBlockIfBlinded(
final SignedBeaconBlock blindedSignedBeaconBlock) {
if (blindedSignedBeaconBlock.isBlinded()) {
return spec.unblindSignedBeaconBlock(
blindedSignedBeaconBlock, operationSelector.createUnblinderSelector());
}
return SafeFuture.completedFuture(blindedSignedBeaconBlock);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,70 +13,24 @@

package tech.pegasys.teku.validator.coordinator;

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

import java.util.Optional;
import org.apache.tuweni.bytes.Bytes32;
import tech.pegasys.teku.bls.BLSSignature;
import tech.pegasys.teku.infrastructure.async.SafeFuture;
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
import tech.pegasys.teku.spec.Spec;
import tech.pegasys.teku.spec.datastructures.blocks.BeaconBlock;
import tech.pegasys.teku.spec.datastructures.blocks.BeaconBlockAndState;
import tech.pegasys.teku.spec.datastructures.blocks.BlockContainer;
import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock;
import tech.pegasys.teku.spec.datastructures.state.beaconstate.BeaconState;

public class BlockFactory {
private final Spec spec;
private final BlockOperationSelectorFactory operationSelector;

public BlockFactory(final Spec spec, final BlockOperationSelectorFactory operationSelector) {
this.spec = spec;
this.operationSelector = operationSelector;
}

public SafeFuture<BeaconBlock> createUnsignedBlock(
final BeaconState blockSlotState,
final UInt64 newSlot,
final BLSSignature randaoReveal,
final Optional<Bytes32> optionalGraffiti,
final boolean blinded) {
checkArgument(
blockSlotState.getSlot().equals(newSlot),
"Block slot state for slot %s but should be for slot %s",
blockSlotState.getSlot(),
newSlot);

// Process empty slots up to the one before the new block slot
final UInt64 slotBeforeBlock = newSlot.minus(UInt64.ONE);

final Bytes32 parentRoot = spec.getBlockRootAtSlot(blockSlotState, slotBeforeBlock);

return spec.createNewUnsignedBlock(
newSlot,
spec.getBeaconProposerIndex(blockSlotState, newSlot),
blockSlotState,
parentRoot,
operationSelector.createSelector(
parentRoot, blockSlotState, randaoReveal, optionalGraffiti),
blinded)
.thenApply(BeaconBlockAndState::getBlock);
}
public interface BlockFactory {

public SafeFuture<SignedBeaconBlock> unblindSignedBeaconBlockIfBlinded(
final SignedBeaconBlock blindedSignedBeaconBlock) {
if (blindedSignedBeaconBlock.isBlinded()) {
return spec.unblindSignedBeaconBlock(
blindedSignedBeaconBlock, operationSelector.createUnblinderSelector());
}
return SafeFuture.completedFuture(blindedSignedBeaconBlock);
}
SafeFuture<BlockContainer> createUnsignedBlock(
BeaconState blockSlotState,
UInt64 newSlot,
BLSSignature randaoReveal,
Optional<Bytes32> optionalGraffiti,
boolean blinded);

public SignedBeaconBlock blindSignedBeaconBlockIfUnblinded(
final SignedBeaconBlock unblindedSignedBeaconBlock) {
if (unblindedSignedBeaconBlock.isBlinded()) {
return unblindedSignedBeaconBlock;
}
return spec.blindSignedBeaconBlock(unblindedSignedBeaconBlock);
}
SafeFuture<SignedBeaconBlock> unblindSignedBeaconBlockIfBlinded(
SignedBeaconBlock blindedSignedBeaconBlock);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright ConsenSys Software Inc., 2023
*
* 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.validator.coordinator;

import java.util.List;
import java.util.Optional;
import org.apache.tuweni.bytes.Bytes32;
import tech.pegasys.teku.bls.BLSSignature;
import tech.pegasys.teku.infrastructure.async.SafeFuture;
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
import tech.pegasys.teku.spec.Spec;
import tech.pegasys.teku.spec.SpecMilestone;
import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlindedBlobSidecar;
import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecar;
import tech.pegasys.teku.spec.datastructures.blocks.BeaconBlock;
import tech.pegasys.teku.spec.datastructures.blocks.BlockContainer;
import tech.pegasys.teku.spec.datastructures.blocks.versions.deneb.BlindedBlockContents;
import tech.pegasys.teku.spec.datastructures.blocks.versions.deneb.BlockContents;
import tech.pegasys.teku.spec.datastructures.state.beaconstate.BeaconState;
import tech.pegasys.teku.spec.schemas.SchemaDefinitionsDeneb;

public class BlockFactoryDeneb extends BlockFactoryPhase0 {

private final SchemaDefinitionsDeneb schemaDefinitionsDeneb;

public BlockFactoryDeneb(final Spec spec, final BlockOperationSelectorFactory operationSelector) {
super(spec, operationSelector);
this.schemaDefinitionsDeneb =
SchemaDefinitionsDeneb.required(
spec.forMilestone(SpecMilestone.DENEB).getSchemaDefinitions());
}

@Override
public SafeFuture<BlockContainer> createUnsignedBlock(
final BeaconState blockSlotState,
final UInt64 newSlot,
final BLSSignature randaoReveal,
final Optional<Bytes32> optionalGraffiti,
final boolean blinded) {
return super.createUnsignedBlock(
blockSlotState, newSlot, randaoReveal, optionalGraffiti, blinded)
.thenApply(BlockContainer::getBlock)
.thenCompose(
block -> {
if (block.isBlinded()) {
return operationSelector
.createBlindedBlobSidecarsSelector()
.apply(block)
.thenApply(
blindedBlobSidecars ->
createBlindedBlockContents(block, blindedBlobSidecars));
}
return operationSelector
.createBlobSidecarsSelector()
.apply(block)
.thenApply(blobSidecars -> createBlockContents(block, blobSidecars));
});
}

private BlockContents createBlockContents(
final BeaconBlock block, final List<BlobSidecar> blobSidecars) {
return schemaDefinitionsDeneb.getBlockContentsSchema().create(block, blobSidecars);
}

private BlindedBlockContents createBlindedBlockContents(
final BeaconBlock block, final List<BlindedBlobSidecar> blindedBlobSidecars) {
return schemaDefinitionsDeneb
.getBlindedBlockContentsSchema()
.create(block, blindedBlobSidecars);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright ConsenSys Software Inc., 2023
*
* 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.validator.coordinator;

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

import java.util.Optional;
import org.apache.tuweni.bytes.Bytes32;
import tech.pegasys.teku.bls.BLSSignature;
import tech.pegasys.teku.infrastructure.async.SafeFuture;
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
import tech.pegasys.teku.spec.Spec;
import tech.pegasys.teku.spec.datastructures.blocks.BeaconBlockAndState;
import tech.pegasys.teku.spec.datastructures.blocks.BlockContainer;
import tech.pegasys.teku.spec.datastructures.state.beaconstate.BeaconState;

public class BlockFactoryPhase0 extends AbstractBlockFactory {

public BlockFactoryPhase0(
final Spec spec, final BlockOperationSelectorFactory operationSelector) {
super(spec, operationSelector);
}

@Override
public SafeFuture<BlockContainer> createUnsignedBlock(
final BeaconState blockSlotState,
final UInt64 newSlot,
final BLSSignature randaoReveal,
final Optional<Bytes32> optionalGraffiti,
final boolean blinded) {
checkArgument(
blockSlotState.getSlot().equals(newSlot),
"Block slot state for slot %s but should be for slot %s",
blockSlotState.getSlot(),
newSlot);

// Process empty slots up to the one before the new block slot
final UInt64 slotBeforeBlock = newSlot.minus(UInt64.ONE);

final Bytes32 parentRoot = spec.getBlockRootAtSlot(blockSlotState, slotBeforeBlock);

return spec.createNewUnsignedBlock(
newSlot,
spec.getBeaconProposerIndex(blockSlotState, newSlot),
blockSlotState,
parentRoot,
operationSelector.createSelector(
parentRoot, blockSlotState, randaoReveal, optionalGraffiti),
blinded)
.thenApply(BeaconBlockAndState::getBlock);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,25 @@
package tech.pegasys.teku.validator.coordinator;

import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import org.apache.tuweni.bytes.Bytes32;
import tech.pegasys.teku.bls.BLSSignature;
import tech.pegasys.teku.infrastructure.async.SafeFuture;
import tech.pegasys.teku.infrastructure.ssz.SszList;
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
import tech.pegasys.teku.spec.Spec;
import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlindedBlobSidecar;
import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlindedBlobSidecarSchema;
import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecar;
import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobSidecarSchema;
import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.BlobsBundle;
import tech.pegasys.teku.spec.datastructures.blocks.BeaconBlock;
import tech.pegasys.teku.spec.datastructures.blocks.Eth1Data;
import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlockUnblinder;
Expand Down Expand Up @@ -280,17 +288,17 @@ private void builderSetKzgCommitments(
executionPayloadResultFuture.thenCompose(
executionPayloadResult ->
executionPayloadResult
.getCommitmentsFuture()
.getBlobsBundleFuture()
.orElseThrow()
.thenApply(
commitments ->
blobsBundle ->
schemaDefinitionsDeneb
.getBeaconBlockBodySchema()
.toVersionDeneb()
.orElseThrow()
.getBlobKzgCommitmentsSchema()
.createFromElements(
commitments.stream()
blobsBundle.getCommitments().stream()
.map(SszKZGCommitment::new)
.collect(Collectors.toList()))));
bodyBuilder.blobKzgCommitments(blobKzgCommitments);
Expand Down Expand Up @@ -321,4 +329,65 @@ public Consumer<SignedBeaconBlockUnblinder> createUnblinderSelector() {
}
};
}

public Function<BeaconBlock, SafeFuture<List<BlobSidecar>>> createBlobSidecarsSelector() {
return block -> {
final BlobSidecarSchema blobSidecarSchema =
SchemaDefinitionsDeneb.required(spec.atSlot(block.getSlot()).getSchemaDefinitions())
.getBlobSidecarSchema();
return getCachedBlobsBundle(block.getSlot())
.thenApply(
blobsBundle ->
IntStream.range(0, blobsBundle.getNumberOfBlobs())
.mapToObj(
index ->
blobSidecarSchema.create(
block.getRoot(),
UInt64.valueOf(index),
block.getSlot(),
block.getParentRoot(),
block.getProposerIndex(),
blobsBundle.getBlobs().get(index).getBytes(),
blobsBundle.getCommitments().get(index).getBytesCompressed(),
blobsBundle.getProofs().get(index).getBytesCompressed()))
.collect(Collectors.toUnmodifiableList()));
};
}

public Function<BeaconBlock, SafeFuture<List<BlindedBlobSidecar>>>
createBlindedBlobSidecarsSelector() {
return block -> {
final BlindedBlobSidecarSchema blindedBlobSidecarSchema =
SchemaDefinitionsDeneb.required(spec.atSlot(block.getSlot()).getSchemaDefinitions())
.getBlindedBlobSidecarSchema();
return getCachedBlobsBundle(block.getSlot())
.thenApply(
blobsBundle ->
IntStream.range(0, blobsBundle.getNumberOfBlobs())
.mapToObj(
index ->
blindedBlobSidecarSchema.create(
block.getRoot(),
UInt64.valueOf(index),
block.getSlot(),
block.getParentRoot(),
block.getProposerIndex(),
blobsBundle.getBlobs().get(index).hashTreeRoot(),
blobsBundle.getCommitments().get(index).getBytesCompressed(),
blobsBundle.getProofs().get(index).getBytesCompressed()))
.collect(Collectors.toUnmodifiableList()));
};
}

private SafeFuture<BlobsBundle> getCachedBlobsBundle(final UInt64 slot) {
return executionLayerBlockProductionManager
.getCachedPayloadResult(slot)
.orElseThrow(
() ->
new IllegalStateException(
"ExecutionPayloadResult is not available for slot " + slot))
.getBlobsBundleFuture()
.orElseThrow(
() -> new IllegalStateException("BlobsBundle is not available for slot " + slot));
}
}
Loading

0 comments on commit 87d7095

Please sign in to comment.