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

Deneb block signing #868

Merged
merged 13 commits into from
Aug 18, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,10 @@ public class SignerConfiguration {

private final Optional<Long> bellatrixForkEpoch;
private final Optional<Long> capellaForkEpoch;
private final Optional<Long> denebForkEpoch;
private final Optional<String> network;
private final boolean keyManagerApiEnabled;
private final Optional<String> trustedSetup;
private Optional<WatermarkRepairParameters> watermarkRepairParameters;
private int downstreamHttpPort;
private Optional<ClientTlsOptions> downstreamTlsOptions;
Expand Down Expand Up @@ -111,12 +113,14 @@ public SignerConfiguration(
final Optional<Long> altairForkEpoch,
final Optional<Long> bellatrixForkEpoch,
final Optional<Long> capellaForkEpoch,
final Optional<Long> denebForkEpoch,
final Optional<String> network,
final boolean keyManagerApiEnabled,
final Optional<WatermarkRepairParameters> watermarkRepairParameters,
final int downstreamHttpPort,
final Optional<ClientTlsOptions> downstreamTlsOptions,
final ChainIdProvider chainIdProvider) {
final ChainIdProvider chainIdProvider,
final Optional<String> trustedSetup) {
this.hostname = hostname;
this.logLevel = logLevel;
this.httpRpcPort = httpRpcPort;
Expand Down Expand Up @@ -152,12 +156,14 @@ public SignerConfiguration(
this.altairForkEpoch = altairForkEpoch;
this.bellatrixForkEpoch = bellatrixForkEpoch;
this.capellaForkEpoch = capellaForkEpoch;
this.denebForkEpoch = denebForkEpoch;
this.network = network;
this.keyManagerApiEnabled = keyManagerApiEnabled;
this.watermarkRepairParameters = watermarkRepairParameters;
this.downstreamHttpPort = downstreamHttpPort;
this.downstreamTlsOptions = downstreamTlsOptions;
this.chainIdProvider = chainIdProvider;
this.trustedSetup = trustedSetup;
}

public String hostname() {
Expand Down Expand Up @@ -300,6 +306,10 @@ public Optional<Long> getCapellaForkEpoch() {
return capellaForkEpoch;
}

public Optional<Long> getDenebForkEpoch() {
return denebForkEpoch;
}

public Optional<String> getNetwork() {
return network;
}
Expand Down Expand Up @@ -331,4 +341,8 @@ public Optional<ClientTlsOptions> getDownstreamTlsOptions() {
public ChainIdProvider getChainIdProvider() {
return chainIdProvider;
}

public Optional<String> getTrustedSetup() {
return trustedSetup;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ public class SignerConfigurationBuilder {
private Long altairForkEpoch = null;
private Long bellatrixForkEpoch = null;
private Long capellaForkEpoch = null;
private Long denebForkEpoch = null;
private String network = null;
private boolean keyManagerApiEnabled = false;
private KeystoresParameters keystoresParameters;
Expand All @@ -77,6 +78,7 @@ public class SignerConfigurationBuilder {
private ClientTlsOptions downstreamTlsOptions;

private ChainIdProvider chainIdProvider = new ConfigurationChainId(DEFAULT_CHAIN_ID);
private String trustedSetup;

public SignerConfigurationBuilder withLogLevel(final Level logLevel) {
this.logLevel = logLevel;
Expand Down Expand Up @@ -255,6 +257,11 @@ public SignerConfigurationBuilder withCapellaForkEpoch(final long capellaForkEpo
return this;
}

public SignerConfigurationBuilder withDenebForkEpoch(final long denebForkEpoch) {
this.denebForkEpoch = denebForkEpoch;
return this;
}

public SignerConfigurationBuilder withNetwork(final String network) {
this.network = network;
return this;
Expand Down Expand Up @@ -297,6 +304,11 @@ public SignerConfigurationBuilder withChainIdProvider(final ChainIdProvider chai
return this;
}

public SignerConfigurationBuilder withTrustedSetup(final String trustedSetup) {
this.trustedSetup = trustedSetup;
return this;
}

public SignerConfiguration build() {
if (mode == null) {
throw new IllegalArgumentException("Mode cannot be null");
Expand Down Expand Up @@ -337,11 +349,13 @@ public SignerConfiguration build() {
Optional.ofNullable(altairForkEpoch),
Optional.ofNullable(bellatrixForkEpoch),
Optional.ofNullable(capellaForkEpoch),
Optional.ofNullable(denebForkEpoch),
Optional.ofNullable(network),
keyManagerApiEnabled,
Optional.ofNullable(watermarkRepairParameters),
downstreamHttpPort,
Optional.ofNullable(downstreamTlsOptions),
chainIdProvider);
chainIdProvider,
Optional.ofNullable(trustedSetup));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,20 @@ private String createEth2SlashingProtectionArgs() {
signerConfig.getCapellaForkEpoch().get()));
}

if (signerConfig.getDenebForkEpoch().isPresent()) {
yamlConfig.append(
String.format(
YAML_NUMERIC_FMT,
"eth2.Xnetwork-deneb-fork-epoch",
signerConfig.getDenebForkEpoch().get()));
}

if (signerConfig.getTrustedSetup().isPresent()) {
yamlConfig.append(
String.format(
YAML_STRING_FMT, "eth2.Xtrusted-setup", signerConfig.getTrustedSetup().get()));
}

if (signerConfig.getNetwork().isPresent()) {
yamlConfig.append(
String.format(YAML_STRING_FMT, "eth2.network", signerConfig.getNetwork().get()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,16 @@ private Collection<String> createEth2Args() {
params.add(Long.toString(signerConfig.getCapellaForkEpoch().get()));
}

if (signerConfig.getDenebForkEpoch().isPresent()) {
params.add("--Xnetwork-deneb-fork-epoch");
params.add(Long.toString(signerConfig.getDenebForkEpoch().get()));
}

if (signerConfig.getTrustedSetup().isPresent()) {
params.add("--Xtrusted-setup");
params.add(signerConfig.getTrustedSetup().get());
}

if (signerConfig.getNetwork().isPresent()) {
params.add("--network");
params.add(signerConfig.getNetwork().get());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,8 @@ private ExecutionPayload randomExecutionPayload(final SpecVersion specVersion) {
.blockHash(util.randomBytes32())
.transactions(util.randomExecutionPayloadTransactions())
.withdrawals(() -> randomExecutionPayloadWithdrawals(specVersion))
.excessBlobGas(util::randomUInt64));
.excessBlobGas(util::randomUInt64)
.blobGasUsed(util::randomUInt64));
}

private List<Withdrawal> randomExecutionPayloadWithdrawals(final SpecVersion specVersion) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ public Eth2SigningRequestBody createBlockV2Request() {
return createBlockV2Request(new BlockRequest(specMilestone, getBeaconBlock()));
case BELLATRIX:
case CAPELLA:
case DENEB:
return createBlockV2Request(new BlockRequest(specMilestone, getBeaconBlockHeader()));
default:
throw new IllegalStateException(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ void setup() {
@ParameterizedTest(name = "#{index} - Sign and verify BlockV2 Signature for spec {0}")
@EnumSource(
value = SpecMilestone.class,
names = {"PHASE0", "ALTAIR", "BELLATRIX", "CAPELLA"})
names = {"PHASE0", "ALTAIR", "BELLATRIX", "CAPELLA", "DENEB"})
void signAndVerifyBlockV2Signature(final SpecMilestone specMilestone) throws Exception {
final Eth2BlockSigningRequestUtil util = new Eth2BlockSigningRequestUtil(specMilestone);

Expand Down Expand Up @@ -92,7 +92,7 @@ void signAndVerifyLegacyBlockSignature() throws Exception {
name = "#{index} - Empty block request for spec {0} should return bad request status")
@EnumSource(
value = SpecMilestone.class,
names = {"PHASE0", "ALTAIR", "BELLATRIX", "CAPELLA"})
names = {"PHASE0", "ALTAIR", "BELLATRIX", "CAPELLA", "DENEB"})
void emptyBlockRequestReturnsBadRequestStatus(final SpecMilestone specMilestone)
throws JsonProcessingException {
final Eth2BlockSigningRequestUtil util = new Eth2BlockSigningRequestUtil(specMilestone);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,19 @@
import tech.pegasys.teku.bls.BLSPublicKey;
import tech.pegasys.teku.bls.BLSSecretKey;
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
import tech.pegasys.teku.networks.Eth2NetworkConfiguration;
import tech.pegasys.teku.spec.Spec;
import tech.pegasys.teku.spec.SpecFactory;
import tech.pegasys.teku.spec.datastructures.util.ForkAndSpecMilestone;
import tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.Eth2SigningRequestBody;
import tech.pegasys.web3signer.dsl.signer.SignerConfigurationBuilder;
import tech.pegasys.web3signer.dsl.utils.Eth2BlockSigningRequestUtil;
import tech.pegasys.web3signer.dsl.utils.MetadataFileHelpers;
import tech.pegasys.web3signer.signing.KeyType;

import java.nio.file.Path;
import java.util.List;
import java.util.Objects;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.google.common.io.Resources;
Expand All @@ -50,21 +53,36 @@ public class Eth2CustomNetworkFileAcceptanceTest extends SigningAcceptanceTestBa
BLSSecretKey.fromBytes(Bytes32.fromHexString(PRIVATE_KEY));
private static final BLSKeyPair KEY_PAIR = new BLSKeyPair(KEY);
private static final BLSPublicKey PUBLIC_KEY = KEY_PAIR.getPublicKey();
private static final String TRUSTED_SETUP_PATH =
Objects.requireNonNull(
Eth2NetworkConfiguration.class.getResource("minimal-trusted-setup.txt"))
.toExternalForm();

@BeforeEach
void setup() {
final String configFilename = PUBLIC_KEY.toString().substring(2);
final Path keyConfigFile = testDirectory.resolve(configFilename + ".yaml");
METADATA_FILE_HELPERS.createUnencryptedYamlFileAt(keyConfigFile, PRIVATE_KEY, KeyType.BLS);

setupEth2SignerWithCustomNetworkConfig(NETWORK_CONFIG_PATH);
final SignerConfigurationBuilder builder = new SignerConfigurationBuilder();
builder
.withKeyStoreDirectory(testDirectory)
.withMode("eth2")
.withNetwork(NETWORK_CONFIG_PATH)
.withTrustedSetup(TRUSTED_SETUP_PATH);
startSigner(builder.build());
}

@Test
void signAndVerifyBlockV2SignatureForAllEnabledMilestones() throws Exception {
final Spec spec = SpecFactory.create(NETWORK_CONFIG_PATH.toString());
final Spec spec =
SpecFactory.create(
NETWORK_CONFIG_PATH.toString(),
specConfigBuilder ->
specConfigBuilder.denebBuilder(
denebBuilder -> denebBuilder.trustedSetupPath(TRUSTED_SETUP_PATH)));
final List<ForkAndSpecMilestone> enabledMilestones = spec.getEnabledMilestones();
assertThat(enabledMilestones.size()).isEqualTo(4);
assertThat(enabledMilestones.size()).isEqualTo(5);

for (final ForkAndSpecMilestone forkAndSpecMilestone : enabledMilestones) {
final Eth2SigningRequestBody request =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,15 @@ protected void setupEth2Signer(final Eth2Network eth2Network, final SpecMileston
startSigner(builder.build());
}

protected void setupEth2Signer(final Path networkConfigFile, final SpecMilestone specMilestone) {
final SignerConfigurationBuilder builder = new SignerConfigurationBuilder();
builder.withKeyStoreDirectory(testDirectory).withMode("eth2").withNetwork(networkConfigFile);

setForkEpochs(specMilestone, builder);

startSigner(builder.build());
}

protected void setupEth2SignerWithCustomNetworkConfig(final Path networkConfigFile) {
final SignerConfigurationBuilder builder = new SignerConfigurationBuilder();
builder.withKeyStoreDirectory(testDirectory).withMode("eth2").withNetwork(networkConfigFile);
Expand Down Expand Up @@ -84,6 +93,12 @@ private void setForkEpochs(
builder.withBellatrixForkEpoch(0L);
builder.withCapellaForkEpoch(0L);
break;
case DENEB:
builder.withAltairForkEpoch(0L);
builder.withBellatrixForkEpoch(0L);
builder.withCapellaForkEpoch(0L);
builder.withDenebForkEpoch(0L);
break;
default:
throw new IllegalStateException(
"Setting manual fork epoch is not yet implemented for " + specMilestone);
Expand Down
2 changes: 2 additions & 0 deletions acceptance-tests/src/test/resources/eth2/network_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ BELLATRIX_FORK_EPOCH: 8
BELLATRIX_FORK_VERSION: 0x020000fd
CAPELLA_FORK_EPOCH: 10
CAPELLA_FORK_VERSION: 0x030000fd
DENEB_FORK_VERSION: 0x04000001
DENEB_FORK_EPOCH: 12
SHARDING_FORK_EPOCH: 18446744073709551615
SHARDING_FORK_VERSION: 0x030000fd
INACTIVITY_SCORE_BIAS: 4
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,24 @@ private static class NetworkCliCompletionCandidates extends ArrayList<String> {
converter = UInt64Converter.class)
private UInt64 capellaForkEpoch;

@CommandLine.Option(
names = {"--Xnetwork-deneb-fork-epoch"},
hidden = true,
paramLabel = "<epoch>",
description = "Override the Deneb fork activation epoch.",
arity = "1",
converter = UInt64Converter.class)
private UInt64 denebForkEpoch;

@CommandLine.Option(
names = {"--Xtrusted-setup"},
hidden = true,
paramLabel = "<STRING>",
description =
"The trusted setup which is needed for KZG commitments. Only required when creating a custom network. This value should be a file or URL pointing to a trusted setup.",
arity = "1")
private String trustedSetup = null; // Depends on network configuration

@CommandLine.Option(
names = {"--key-manager-api-enabled", "--enable-key-manager-api"},
paramLabel = "<BOOL>",
Expand Down Expand Up @@ -182,6 +200,12 @@ private Eth2NetworkConfiguration createEth2NetworkConfig() {
if (capellaForkEpoch != null) {
builder.capellaForkEpoch(capellaForkEpoch);
}
if (denebForkEpoch != null) {
builder.denebForkEpoch(denebForkEpoch);
}
if (trustedSetup != null) {
builder.trustedSetup(trustedSetup);
}
return builder.build();
}

Expand Down
15 changes: 15 additions & 0 deletions core/src/main/resources/openapi-specs/eth2/signing/schemas.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -489,13 +489,15 @@ components:
- $ref: '#/components/schemas/BlockRequestAltair'
- $ref: '#/components/schemas/BlockRequestBellatrix'
- $ref: '#/components/schemas/BlockRequestCapella'
- $ref: '#/components/schemas/BlockRequestDeneb'
discriminator:
propertyName: version
mapping:
PHASE0: '#/components/schemas/BlockRequestPhase0'
ALTAIR: '#/components/schemas/BlockRequestAltair'
BELLATRIX: '#/components/schemas/BlockRequestBellatrix'
CAPELLA: '#/components/schemas/BlockRequestCapella'
DENEB: '#/components/schemas/BlockRequestDeneb'
required:
- beacon_block
BlockRequestPhase0:
Expand Down Expand Up @@ -550,6 +552,19 @@ components:
required:
- version
- block_header
BlockRequestDeneb:
type: object
properties:
version:
type: string
enum:
- DENEB
description: 'version to identify block request type.'
block_header:
$ref: "#/components/schemas/BeaconBlockHeader"
required:
- version
- block_header
BeaconBlockAltair:
type: "object"
properties:
Expand Down