Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into no-keys
Browse files Browse the repository at this point in the history
  • Loading branch information
courtneyeh committed Nov 23, 2023
2 parents 3ad8390 + 4c20f78 commit 6354a1c
Show file tree
Hide file tree
Showing 4 changed files with 184 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public SignedBlockContents(
final SignedBeaconBlock signedBeaconBlock,
final List<KZGProof> kzgProofs,
final List<Blob> blobs) {
super(
this(
schema,
signedBeaconBlock,
schema
Expand All @@ -46,6 +46,14 @@ public SignedBlockContents(
schema.getBlobsSchema().createFromElements(blobs));
}

public SignedBlockContents(
final SignedBlockContentsSchema schema,
final SignedBeaconBlock signedBeaconBlock,
final SszList<SszKZGProof> kzgProofs,
final SszList<Blob> blobs) {
super(schema, signedBeaconBlock, kzgProofs, blobs);
}

@Override
public SignedBeaconBlock getSignedBlock() {
return getField0();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ public SignedBlockContents create(
return new SignedBlockContents(this, signedBeaconBlock, kzgProofs, blobs);
}

public SignedBlockContents create(
final SignedBeaconBlock signedBeaconBlock,
final SszList<SszKZGProof> kzgProofs,
final SszList<Blob> blobs) {
return new SignedBlockContents(this, signedBeaconBlock, kzgProofs, blobs);
}

@Override
public SignedBlockContents createFromBackingNode(final TreeNode node) {
return new SignedBlockContents(this, node);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,16 @@

package tech.pegasys.teku.validator.client.signer;

import java.util.Collections;
import tech.pegasys.teku.infrastructure.async.SafeFuture;
import tech.pegasys.teku.infrastructure.ssz.SszList;
import tech.pegasys.teku.spec.Spec;
import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.Blob;
import tech.pegasys.teku.spec.datastructures.blocks.BeaconBlock;
import tech.pegasys.teku.spec.datastructures.blocks.BlockContainer;
import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock;
import tech.pegasys.teku.spec.datastructures.blocks.SignedBlockContainer;
import tech.pegasys.teku.spec.datastructures.state.ForkInfo;
import tech.pegasys.teku.spec.datastructures.type.SszKZGProof;
import tech.pegasys.teku.spec.schemas.SchemaDefinitionsDeneb;
import tech.pegasys.teku.validator.client.Validator;

Expand All @@ -44,15 +46,31 @@ public SafeFuture<SignedBlockContainer> sign(
return signBlock(unsignedBlock, validator, forkInfo)
.thenApply(
signedBlock -> {
// Blinded flow
if (signedBlock.isBlinded()) {
return signedBlock;
} else {
final SszList<SszKZGProof> kzgProofs =
unsignedBlockContainer
.getKzgProofs()
.orElseThrow(
() ->
new RuntimeException(
String.format(
"Unable to get KZG Proofs when signing Deneb block at slot %d",
unsignedBlockContainer.getSlot().longValue())));
final SszList<Blob> blobs =
unsignedBlockContainer
.getBlobs()
.orElseThrow(
() ->
new RuntimeException(
String.format(
"Unable to get blobs when signing Deneb block at slot %d",
unsignedBlockContainer.getSlot().longValue())));
return schemaDefinitions
.getSignedBlockContentsSchema()
.create(signedBlock, kzgProofs, blobs);
}
// Unblinded flow
// TODO: add proofs and blobs
return schemaDefinitions
.getSignedBlockContentsSchema()
.create(signedBlock, Collections.emptyList(), Collections.emptyList());
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import static tech.pegasys.teku.infrastructure.async.SafeFutureAssert.safeJoin;
import static tech.pegasys.teku.infrastructure.unsigned.UInt64.ZERO;

import java.util.List;
import java.util.Optional;
import java.util.Set;
import org.apache.tuweni.bytes.Bytes;
Expand All @@ -44,9 +45,11 @@
import tech.pegasys.teku.infrastructure.logging.ValidatorLogger;
import tech.pegasys.teku.infrastructure.metrics.StubMetricsSystem;
import tech.pegasys.teku.infrastructure.metrics.Validator.ValidatorDutyMetricsSteps;
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.TestSpecFactory;
import tech.pegasys.teku.spec.datastructures.blobs.versions.deneb.Blob;
import tech.pegasys.teku.spec.datastructures.blocks.BeaconBlock;
import tech.pegasys.teku.spec.datastructures.blocks.SignedBeaconBlock;
import tech.pegasys.teku.spec.datastructures.blocks.SignedBlockContainer;
Expand All @@ -55,6 +58,7 @@
import tech.pegasys.teku.spec.datastructures.blocks.versions.deneb.SignedBlockContents;
import tech.pegasys.teku.spec.datastructures.execution.ExecutionPayloadSummary;
import tech.pegasys.teku.spec.datastructures.state.ForkInfo;
import tech.pegasys.teku.spec.datastructures.type.SszKZGProof;
import tech.pegasys.teku.spec.datastructures.validator.BroadcastValidationLevel;
import tech.pegasys.teku.spec.signatures.Signer;
import tech.pegasys.teku.spec.util.DataStructureUtil;
Expand Down Expand Up @@ -180,6 +184,10 @@ public void forDeneb_shouldCreateAndPublishBlockContents() {
// can create BlockContents only post-Deneb
final BlockContents unsignedBlockContents = dataStructureUtil.randomBlockContents(denebSlot);
final BeaconBlock unsignedBlock = unsignedBlockContents.getBlock();
final List<Blob> blobsFromUnsignedBlockContents =
unsignedBlockContents.getBlobs().orElseThrow().asList();
final List<SszKZGProof> kzgProofsFromUnsignedBlockContents =
unsignedBlockContents.getKzgProofs().orElseThrow().asList();
when(signer.createRandaoReveal(spec.computeEpochAtSlot(denebSlot), fork))
.thenReturn(completedFuture(randaoReveal));
when(signer.signBlock(unsignedBlockContents.getBlock(), fork))
Expand Down Expand Up @@ -218,7 +226,23 @@ public void forDeneb_shouldCreateAndPublishBlockContents() {
assertThat(signedBlock.getMessage()).isEqualTo(unsignedBlock);
assertThat(signedBlock.getSignature()).isEqualTo(blockSignature);

// TODO Add test for blobs and kzg proofs once added
assertThat(signedBlockContents.getKzgProofs()).isPresent();

final SszList<SszKZGProof> kzgProofsFromSignedBlockContent =
signedBlockContents.getKzgProofs().get();

assertThat(kzgProofsFromSignedBlockContent).isNotEmpty();

assertThat(kzgProofsFromUnsignedBlockContents)
.isEqualTo(kzgProofsFromSignedBlockContent.asList());

assertThat(signedBlockContents.getBlobs()).isPresent();

final SszList<Blob> blobsFromSignedBlockContents = signedBlockContents.getBlobs().get();

assertThat(blobsFromSignedBlockContents).isNotEmpty();

assertThat(blobsFromUnsignedBlockContents).isEqualTo(blobsFromSignedBlockContents.asList());

verify(validatorDutyMetrics)
.record(any(), any(BlockProductionDuty.class), eq(ValidatorDutyMetricsSteps.CREATE));
Expand Down Expand Up @@ -291,6 +315,90 @@ public void forDeneb_shouldCreateAndPublishBlindedBlock() {
.record(any(), any(BlockProductionDuty.class), eq(ValidatorDutyMetricsSteps.SEND));
}

@Test
public void forDeneb_shouldFailWhenNoKzgProofs() {
duty =
new BlockProductionDuty(
validator,
denebSlot,
forkProvider,
validatorApiChannel,
blockContainerSigner,
false,
false,
spec,
validatorDutyMetrics);

final BLSSignature randaoReveal = dataStructureUtil.randomSignature();
final BLSSignature blockSignature = dataStructureUtil.randomSignature();
// can create BlockContents only post-Deneb
final BlockContents unsignedBlockContents = dataStructureUtil.randomBlockContents(denebSlot);
final BlockContents unsignedBlockContentsMock = mock(BlockContents.class);
when(unsignedBlockContentsMock.getKzgProofs()).thenReturn(Optional.empty());
final Bytes32 blockRoot = dataStructureUtil.randomBytes32();
when(unsignedBlockContentsMock.getSlot()).thenReturn(unsignedBlockContents.getSlot());
when(unsignedBlockContentsMock.getBlock()).thenReturn(unsignedBlockContents.getBlock());
when(signer.createRandaoReveal(spec.computeEpochAtSlot(denebSlot), fork))
.thenReturn(completedFuture(randaoReveal));
when(signer.signBlock(unsignedBlockContentsMock.getBlock(), fork))
.thenReturn(completedFuture(blockSignature));
when(validatorApiChannel.createUnsignedBlock(
denebSlot, randaoReveal, Optional.of(graffiti), false))
.thenReturn(completedFuture(Optional.of(unsignedBlockContentsMock)));
when(validatorApiChannel.sendSignedBlock(any(), any()))
.thenReturn(completedFuture(SendSignedBlockResult.success(blockRoot)));

final RuntimeException error =
new RuntimeException(
String.format(
"Unable to get KZG Proofs when signing Deneb block at slot %d",
denebSlot.longValue()));

assertDutyFails(error, denebSlot);
}

@Test
public void forDeneb_shouldFailWhenNoBlobs() {
duty =
new BlockProductionDuty(
validator,
denebSlot,
forkProvider,
validatorApiChannel,
blockContainerSigner,
false,
false,
spec,
validatorDutyMetrics);

final BLSSignature randaoReveal = dataStructureUtil.randomSignature();
final BLSSignature blockSignature = dataStructureUtil.randomSignature();
// can create BlockContents only post-Deneb
final BlockContents unsignedBlockContents = dataStructureUtil.randomBlockContents(denebSlot);
final BlockContents unsignedBlockContentsMock = mock(BlockContents.class);
when(unsignedBlockContentsMock.getBlobs()).thenReturn(Optional.empty());
when(unsignedBlockContentsMock.getKzgProofs()).thenReturn(unsignedBlockContents.getKzgProofs());
final Bytes32 blockRoot = dataStructureUtil.randomBytes32();
when(unsignedBlockContentsMock.getSlot()).thenReturn(unsignedBlockContents.getSlot());
when(unsignedBlockContentsMock.getBlock()).thenReturn(unsignedBlockContents.getBlock());
when(signer.createRandaoReveal(spec.computeEpochAtSlot(denebSlot), fork))
.thenReturn(completedFuture(randaoReveal));
when(signer.signBlock(unsignedBlockContentsMock.getBlock(), fork))
.thenReturn(completedFuture(blockSignature));
when(validatorApiChannel.createUnsignedBlock(
denebSlot, randaoReveal, Optional.of(graffiti), false))
.thenReturn(completedFuture(Optional.of(unsignedBlockContentsMock)));
when(validatorApiChannel.sendSignedBlock(any(), any()))
.thenReturn(completedFuture(SendSignedBlockResult.success(blockRoot)));

final RuntimeException error =
new RuntimeException(
String.format(
"Unable to get blobs when signing Deneb block at slot %d", denebSlot.longValue()));

assertDutyFails(error, denebSlot);
}

@Test
public void shouldFailWhenCreateRandaoFails() {
final RuntimeException error = new RuntimeException("Sorry!");
Expand Down Expand Up @@ -454,6 +562,10 @@ public void forDeneb_shouldUseBlockV3ToCreateAndPublishBlockContents() {
// can create BlockContents only post-Deneb
final BlockContents unsignedBlockContents = dataStructureUtil.randomBlockContents(denebSlot);
final BeaconBlock unsignedBlock = unsignedBlockContents.getBlock();
final List<Blob> blobsFromUnsignedBlockContents =
unsignedBlockContents.getBlobs().orElseThrow().asList();
final List<SszKZGProof> kzgProofsFromUnsignedBlockContents =
unsignedBlockContents.getKzgProofs().orElseThrow().asList();

when(signer.createRandaoReveal(spec.computeEpochAtSlot(denebSlot), fork))
.thenReturn(completedFuture(randaoReveal));
Expand Down Expand Up @@ -491,7 +603,23 @@ public void forDeneb_shouldUseBlockV3ToCreateAndPublishBlockContents() {
assertThat(signedBlock.getMessage()).isEqualTo(unsignedBlock);
assertThat(signedBlock.getSignature()).isEqualTo(blockSignature);

// TODO Add test for blobs and kzg proofs once added
assertThat(signedBlockContents.getKzgProofs()).isPresent();

final SszList<SszKZGProof> kzgProofsFromSignedBlockContent =
signedBlockContents.getKzgProofs().get();

assertThat(kzgProofsFromSignedBlockContent).isNotEmpty();

assertThat(kzgProofsFromUnsignedBlockContents)
.isEqualTo(kzgProofsFromSignedBlockContent.asList());

assertThat(signedBlockContents.getBlobs()).isPresent();

final SszList<Blob> blobsFromSignedBlockContents = signedBlockContents.getBlobs().get();

assertThat(blobsFromSignedBlockContents).isNotEmpty();

assertThat(blobsFromUnsignedBlockContents).isEqualTo(blobsFromSignedBlockContents.asList());

verify(validatorDutyMetrics)
.record(any(), any(BlockProductionDuty.class), eq(ValidatorDutyMetricsSteps.CREATE));
Expand All @@ -502,10 +630,21 @@ public void forDeneb_shouldUseBlockV3ToCreateAndPublishBlockContents() {
}

public void assertDutyFails(final RuntimeException error) {
performAndReportDuty();
assertDutyFails(error, CAPELLA_SLOT);
}

public void assertDutyFails(final RuntimeException expectedError, final UInt64 slot) {
performAndReportDuty(slot);
final ArgumentCaptor<Throwable> errorCaptor = ArgumentCaptor.forClass(Throwable.class);
verify(validatorLogger)
.dutyFailed(
TYPE, CAPELLA_SLOT, Set.of(validator.getPublicKey().toAbbreviatedString()), error);
eq(TYPE),
eq(slot),
eq(Set.of(validator.getPublicKey().toAbbreviatedString())),
errorCaptor.capture());
final Throwable actualError = errorCaptor.getValue();
assertThat(expectedError.getCause()).isEqualTo(actualError.getCause());
assertThat(expectedError.getMessage()).isEqualTo(actualError.getMessage());
verifyNoMoreInteractions(validatorLogger);
}

Expand Down

0 comments on commit 6354a1c

Please sign in to comment.