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

Commit boost API - Generate Proxy Key, Signing Request #1033

Closed
Closed
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
764517e
feat: Commit boost API - Get Public Keys
usmansaleem Oct 20, 2024
82ce60b
Cli options for commit boost. Load proxy signers
usmansaleem Oct 20, 2024
cd20c6c
Unit test for DefaultArtifactSignerProvider loading proxy keys
usmansaleem Oct 20, 2024
94d9be4
empty proxy signers unit test
usmansaleem Oct 21, 2024
3433f75
changelog
usmansaleem Oct 21, 2024
9277a3e
feat: Commit boost API - Generate Proxy Key
usmansaleem Oct 21, 2024
ca5cc03
Generate proxy keys based on scheme
usmansaleem Oct 22, 2024
62b26a9
code fix
usmansaleem Oct 22, 2024
ec91f2e
skeleton for compute signing root
usmansaleem Oct 22, 2024
16277ed
Commit Boost - Gen Proxy Key - BLS Signing root
usmansaleem Oct 22, 2024
5267e71
Rewrite EthPublicKeyUtils to use compressed and uncompressed public keys
usmansaleem Oct 23, 2024
20daaad
Use updated EthPublicKeyUtils methods
usmansaleem Oct 23, 2024
92108da
EthSecpArtifactSigner to use compressed identifier or public key
usmansaleem Oct 23, 2024
1f18946
Commit Boost - Compute signing root for ECPublicKey
usmansaleem Oct 23, 2024
b261b84
Seperate out SigningRootGenerator for Commit Boost
usmansaleem Oct 23, 2024
a2b0c15
Fix EthAccountsResultProviderTest to use proper ECPublicKeys
usmansaleem Oct 23, 2024
afc10d9
Fix Eth1AddressSignerIdentifierTest to use proper SECP keys
usmansaleem Oct 23, 2024
bfb35d3
Fix Eth1AddressSignerIdentifier and unit test
usmansaleem Oct 24, 2024
501e3d8
prepping for unit test
usmansaleem Oct 24, 2024
a740c68
refactoring DefaultArtifactSignerProvider and unit test
usmansaleem Oct 24, 2024
9de3c02
fix json encoding in publickeysroot for 500
usmansaleem Oct 24, 2024
574f104
Merge branch 'commit_boost_support' into commit_boost_gen_proxy
usmansaleem Oct 24, 2024
ac50178
cleaning up ProxyKeyGenerator to use BLS and SECP256k1 and subdirecto…
usmansaleem Oct 24, 2024
eed0048
simplify bulk loading for proxy keys
usmansaleem Oct 24, 2024
3f9e82c
default gvr to zero for minimal networks
usmansaleem Oct 24, 2024
836b6ec
Merge remote-tracking branch 'upstream/master' into commit_boost_gen_…
usmansaleem Oct 24, 2024
b9360e1
refactor eth2 network override to mixin class
usmansaleem Oct 25, 2024
81611e6
Refactor to specify genesis validators root in commit boost api param…
usmansaleem Oct 25, 2024
e3066aa
fix password file path in DefaultArtifactSignerProvider
usmansaleem Oct 29, 2024
9b535c9
Use --genesis-state instead of gvr value from cli
usmansaleem Oct 29, 2024
4c9a144
Fix custom genesis cli option
usmansaleem Oct 29, 2024
eb81e87
refactor EthPublicKeyUtils methods. Add unit test for ProxykeyGenerator
usmansaleem Oct 29, 2024
02562a0
commit boost signing root generator unit test
usmansaleem Oct 29, 2024
40d2c27
unit test for signing root generator
usmansaleem Oct 29, 2024
6611ecd
Use GVR as ZERO. Update Signing root generator tests
usmansaleem Oct 30, 2024
41e781b
Update Signing Root Generator Test to verify bls signature
usmansaleem Oct 30, 2024
300cc68
Update unit tests
usmansaleem Oct 30, 2024
b196f63
Refactor ProxyDelegation names and getEncoded method
usmansaleem Oct 30, 2024
0ab780a
Refactor Eth2SubCommand
usmansaleem Oct 30, 2024
27c9188
Delete Unused Bytes32Converter
usmansaleem Oct 30, 2024
6c0e3b1
changelog
usmansaleem Oct 30, 2024
64b20d1
minor refactoring
usmansaleem Oct 30, 2024
ebccf38
Merge remote-tracking branch 'upstream/master' into commit_boost_gen_…
usmansaleem Oct 31, 2024
5a8a343
Commit Boost - Request Signature
usmansaleem Nov 1, 2024
d0c1119
refactor code
usmansaleem Nov 4, 2024
b8f7910
rename to CommitBoostSignerProvider
usmansaleem Nov 4, 2024
0ddab6e
refactor public keys route and handler
usmansaleem Nov 4, 2024
71435c9
Use CommitBoostSignerProvider
usmansaleem Nov 6, 2024
4cd9ef7
Simplify SignerForIdentifier
usmansaleem Nov 7, 2024
ad2e0ef
Delete SignatureFormatter
usmansaleem Nov 7, 2024
30c6f1b
cleaning SignerForIdentifier generic usage
usmansaleem Nov 7, 2024
b8aa52d
simplifying code
usmansaleem Nov 7, 2024
6dd046b
illegal state exception
usmansaleem Nov 7, 2024
0cce568
Introduce K256ArtifactSigner that generates R+S signature
usmansaleem Nov 10, 2024
45da58b
K256ArtifactSigner that matches Rust K-256 signature generation
usmansaleem Nov 11, 2024
53f2c59
K256ArtifactSigner that matches Rust K-256 signature generation
usmansaleem Nov 11, 2024
a2a16f8
Use K256ArtifactSigner for commit boost api usages
usmansaleem Nov 11, 2024
8ea96fc
Commit Boost Acceptance Tests List and Generate
usmansaleem Nov 14, 2024
a1ed50c
Commit Boost Acceptance Test
usmansaleem Nov 14, 2024
75c3e50
minor cleanup
usmansaleem Nov 14, 2024
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
### Features Added
- Java 21 for build and runtime. [#995](https://github.com/Consensys/web3signer/pull/995)
- Electra fork support. [#1020](https://github.com/Consensys/web3signer/pull/1020) and [#1023](https://github.com/Consensys/web3signer/pull/1023)
- Commit boost API - Get Public Keys. [#1031](https://github.com/Consensys/web3signer/pull/1031)

### Bugs fixed
- Override protobuf-java to 3.25.5 which is a transitive dependency from google-cloud-secretmanager. It fixes CVE-2024-7254.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* Copyright 2022 ConsenSys AG.
*
* 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.web3signer.commandline.config;

import static tech.pegasys.web3signer.commandline.DefaultCommandValues.PATH_FORMAT_HELP;

import tech.pegasys.web3signer.signing.config.KeystoresParameters;

import java.nio.file.Path;

import picocli.CommandLine;
import picocli.CommandLine.Model.CommandSpec;
import picocli.CommandLine.Option;
import picocli.CommandLine.ParameterException;
import picocli.CommandLine.Spec;

public class PicoCommitBoostApiParameters implements KeystoresParameters {
@Spec private CommandSpec commandSpec; // injected by picocli

@CommandLine.Option(
names = {"--commit-boost-api-enabled"},
paramLabel = "<BOOL>",
description = "Enable the commit boost API (default: ${DEFAULT-VALUE}).",
arity = "1")
private boolean isCommitBoostApiEnabled = false;

@Option(
names = {"--proxy-keystores-path"},
description =
"The path to a writeable directory to store v3 and v4 proxy keystores for commit boost API.",
paramLabel = PATH_FORMAT_HELP)
private Path keystoresPath;

@Option(
names = {"--proxy-keystores-password-file"},
description =
"The path to the password file used to encrypt/decrypt proxy keystores for commit boost API.",
paramLabel = PATH_FORMAT_HELP)
private Path keystoresPasswordFile;

@Override
public Path getKeystoresPath() {
return keystoresPath;
}

@Override
public Path getKeystoresPasswordsPath() {
return null;
}

@Override
public Path getKeystoresPasswordFile() {
return keystoresPasswordFile;
}

@Override
public boolean isEnabled() {
return isCommitBoostApiEnabled;
}

public void validateParameters() throws ParameterException {
if (!isCommitBoostApiEnabled) {
return;
}

if (keystoresPath == null) {
throw new ParameterException(
commandSpec.commandLine(),
"Commit boost API is enabled, but --proxy-keystores-path not set");
}

if (keystoresPasswordFile == null) {
throw new ParameterException(
commandSpec.commandLine(),
"Commit boost API is enabled, but --proxy-keystores-password-file not set");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,22 @@
import tech.pegasys.teku.networks.Eth2NetworkConfiguration;
import tech.pegasys.teku.spec.ForkSchedule;
import tech.pegasys.teku.spec.SpecMilestone;
import tech.pegasys.teku.spec.datastructures.state.beaconstate.BeaconState;
import tech.pegasys.teku.spec.datastructures.util.ChainDataLoader;
import tech.pegasys.teku.spec.networks.Eth2Network;
import tech.pegasys.web3signer.commandline.PicoCliAwsSecretsManagerParameters;
import tech.pegasys.web3signer.commandline.PicoCliEth2AzureKeyVaultParameters;
import tech.pegasys.web3signer.commandline.PicoCliGcpSecretManagerParameters;
import tech.pegasys.web3signer.commandline.PicoCliSlashingProtectionParameters;
import tech.pegasys.web3signer.commandline.config.PicoCommitBoostApiParameters;
import tech.pegasys.web3signer.commandline.config.PicoKeystoresParameters;
import tech.pegasys.web3signer.common.config.AwsAuthenticationMode;
import tech.pegasys.web3signer.core.Eth2Runner;
import tech.pegasys.web3signer.core.Runner;
import tech.pegasys.web3signer.signing.config.KeystoresParameters;
import tech.pegasys.web3signer.slashingprotection.SlashingProtectionParameters;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
Expand All @@ -44,8 +48,10 @@

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.tuweni.bytes.Bytes32;
import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.HelpCommand;
Expand Down Expand Up @@ -90,6 +96,15 @@ private static class NetworkCliCompletionCandidates extends ArrayList<String> {
arity = "1")
private String network;

@CommandLine.Option(
names = {"--genesis-state"},
paramLabel = "<STRING>",
description =
"The genesis state. This value should be a file or URL pointing to an SSZ-encoded finalized checkpoint "
+ "state.",
arity = "1")
private String genesisState;

@CommandLine.Option(
names = {"--Xnetwork-altair-fork-epoch"},
hidden = true,
Expand Down Expand Up @@ -164,7 +179,9 @@ private static class NetworkCliCompletionCandidates extends ArrayList<String> {
@Mixin private PicoKeystoresParameters keystoreParameters;
@Mixin private PicoCliAwsSecretsManagerParameters awsSecretsManagerParameters;
@Mixin private PicoCliGcpSecretManagerParameters gcpSecretManagerParameters;
@Mixin private PicoCommitBoostApiParameters commitBoostApiParameters;
private tech.pegasys.teku.spec.Spec eth2Spec;
private Bytes32 genesisValidatorRoot;

public Eth2SubCommand() {
network = "mainnet";
Expand All @@ -182,8 +199,10 @@ public Runner createRunner() {
awsSecretsManagerParameters,
gcpSecretManagerParameters,
eth2Spec,
genesisValidatorRoot,
isKeyManagerApiEnabled,
signingExtEnabled);
signingExtEnabled,
commitBoostApiParameters);
}

private void logNetworkSpecInformation() {
Expand Down Expand Up @@ -230,20 +249,15 @@ private Eth2NetworkConfiguration createEth2NetworkConfig() {
if (trustedSetup != null) {
builder.trustedSetup(trustedSetup);
}
if (StringUtils.isNotBlank(genesisState)) {
builder.customGenesisState(genesisState);
}
return builder.build();
}

@Override
protected void validateArgs() {
try {
Eth2NetworkConfiguration eth2NetworkConfig = createEth2NetworkConfig();
eth2Spec = eth2NetworkConfig.getSpec();
} catch (final IllegalArgumentException e) {
throw new ParameterException(
commandSpec.commandLine(),
"Failed to load network " + network + " due to " + e.getMessage(),
e);
}
validateAndInitGenesisValidatorRoot(validateAndInitSpec());

if (slashingProtectionParameters.isEnabled()
&& slashingProtectionParameters.getDbUrl() == null) {
Expand All @@ -261,6 +275,49 @@ protected void validateArgs() {
validateKeystoreParameters(keystoreParameters);
validateAwsSecretsManageParameters();
validateGcpSecretManagerParameters();
commitBoostApiParameters.validateParameters();
}

private void validateAndInitGenesisValidatorRoot(
final Eth2NetworkConfiguration eth2NetworkConfig) {
final String genesisState =
eth2NetworkConfig
.getNetworkBoostrapConfig()
.getGenesisState()
.orElseThrow(
() ->
new ParameterException(
commandSpec.commandLine(),
"Unable to load genesis state for network "
+ network
+ ". Please provide a valid genesis state resource."));
Fixed Show fixed Hide fixed
try {
final BeaconState beaconState = ChainDataLoader.loadState(eth2Spec, genesisState);
this.genesisValidatorRoot = beaconState.getGenesisValidatorsRoot();
} catch (final IOException | NullPointerException e) {
throw new ParameterException(
commandSpec.commandLine(),
"Unable to load genesis state for network "
+ network
+ " from "
+ genesisState
+ ": "
+ e.getMessage());
}
}

private Eth2NetworkConfiguration validateAndInitSpec() {
final Eth2NetworkConfiguration eth2NetworkConfig;
try {
eth2NetworkConfig = createEth2NetworkConfig();
eth2Spec = eth2NetworkConfig.getSpec();
} catch (final IllegalArgumentException e) {
throw new ParameterException(
commandSpec.commandLine(),
"Failed to load network " + network + " due to " + e.getMessage(),
e);
}
return eth2NetworkConfig;
}

private void validateGcpSecretManagerParameters() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import java.net.InetAddress;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.function.Supplier;

import io.vertx.core.Vertx;
Expand Down Expand Up @@ -612,6 +613,47 @@ void vertxWorkerPoolSizeParsesSuccessfully() {
assertThat(mockEth2SubCommand.getConfig().getVertxWorkerPoolSize()).isEqualTo(40);
}

@Test
void commitBoostApiEnabledWithoutKeystorePathFailsToParse() {
String cmdline = validBaseCommandOptions();
cmdline += "eth2 --slashing-protection-enabled=false --commit-boost-api-enabled=true";

parser.registerSubCommands(new MockEth2SubCommand());
final int result = parser.parseCommandLine(cmdline.split(" "));

assertThat(result).isNotZero();
assertThat(commandError.toString())
.contains(
"Error parsing parameters: Commit boost API is enabled, but --proxy-keystores-path not set");
}

@Test
void commitBoostApiEnabledWithoutKeystorePasswordFileFailsToParse() {
String cmdline = validBaseCommandOptions();
cmdline +=
"eth2 --slashing-protection-enabled=false --commit-boost-api-enabled=true --proxy-keystores-path=./keystore";

parser.registerSubCommands(new MockEth2SubCommand());
final int result = parser.parseCommandLine(cmdline.split(" "));

assertThat(result).isNotZero();
assertThat(commandError.toString())
.contains(
"Error parsing parameters: Commit boost API is enabled, but --proxy-keystores-password-file not set");
}

@Test
void commitBoostApiEnabledWithKeystorePathAndKeystorePasswordFileParsesSuccessfully() {
String cmdline = validBaseCommandOptions();
cmdline +=
"eth2 --slashing-protection-enabled=false --commit-boost-api-enabled=true --proxy-keystores-path=./keystore --proxy-keystores-password-file=./password";

parser.registerSubCommands(new MockEth2SubCommand());
final int result = parser.parseCommandLine(cmdline.split(" "));

assertThat(result).isZero();
}

private <T> void missingOptionalParameterIsValidAndMeetsDefault(
final String paramToRemove, final Supplier<T> actualValueGetter, final T expectedValue) {

Expand Down Expand Up @@ -646,7 +688,7 @@ public void run() {}
@Override
protected List<ArtifactSignerProvider> createArtifactSignerProvider(
final Vertx vertx, final MetricsSystem metricsSystem) {
return List.of(new DefaultArtifactSignerProvider(Collections::emptyList));
return List.of(new DefaultArtifactSignerProvider(Collections::emptyList, Optional.empty()));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

import io.vertx.core.Vertx;
import io.vertx.core.json.JsonObject;
Expand Down Expand Up @@ -114,7 +115,8 @@ protected List<ArtifactSignerProvider> createArtifactSignerProvider(
awsKmsSignerFactory)
.getValues());
return signers;
});
},
Optional.empty());

// uses eth1 address as identifier
final ArtifactSignerProvider secpArtifactSignerProvider =
Expand Down
19 changes: 17 additions & 2 deletions core/src/main/java/tech/pegasys/web3signer/core/Eth2Runner.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import tech.pegasys.web3signer.core.config.BaseConfig;
import tech.pegasys.web3signer.core.routes.PublicKeysListRoute;
import tech.pegasys.web3signer.core.routes.ReloadRoute;
import tech.pegasys.web3signer.core.routes.eth2.CommitBoostGenerateProxyKeyRoute;
import tech.pegasys.web3signer.core.routes.eth2.CommitBoostPublicKeysRoute;
import tech.pegasys.web3signer.core.routes.eth2.Eth2SignExtensionRoute;
import tech.pegasys.web3signer.core.routes.eth2.Eth2SignRoute;
import tech.pegasys.web3signer.core.routes.eth2.HighWatermarkRoute;
Expand Down Expand Up @@ -86,8 +88,10 @@ public class Eth2Runner extends Runner {
private final boolean pruningEnabled;
private final KeystoresParameters keystoresParameters;
private final Spec eth2Spec;
private final Bytes32 genesisValidatorsRoot;
private final boolean isKeyManagerApiEnabled;
private final boolean signingExtEnabled;
private final KeystoresParameters commitBoostApiParameters;

public Eth2Runner(
final BaseConfig baseConfig,
Expand All @@ -97,19 +101,23 @@ public Eth2Runner(
final AwsVaultParameters awsVaultParameters,
final GcpSecretManagerParameters gcpSecretManagerParameters,
final Spec eth2Spec,
final Bytes32 genesisValidatorsRoot,
final boolean isKeyManagerApiEnabled,
final boolean signingExtEnabled) {
final boolean signingExtEnabled,
final KeystoresParameters commitBoostApiParameters) {
super(baseConfig);
this.slashingProtectionContext = createSlashingProtection(slashingProtectionParameters);
this.azureKeyVaultParameters = azureKeyVaultParameters;
this.slashingProtectionParameters = slashingProtectionParameters;
this.pruningEnabled = slashingProtectionParameters.isPruningEnabled();
this.keystoresParameters = keystoresParameters;
this.eth2Spec = eth2Spec;
this.genesisValidatorsRoot = genesisValidatorsRoot;
this.isKeyManagerApiEnabled = isKeyManagerApiEnabled;
this.awsVaultParameters = awsVaultParameters;
this.gcpSecretManagerParameters = gcpSecretManagerParameters;
this.signingExtEnabled = signingExtEnabled;
this.commitBoostApiParameters = commitBoostApiParameters;
}

private Optional<SlashingProtectionContext> createSlashingProtection(
Expand Down Expand Up @@ -137,6 +145,12 @@ public void populateRouter(final Context context) {
if (isKeyManagerApiEnabled) {
new KeyManagerApiRoute(context, baseConfig, slashingProtectionContext).register();
}
if (commitBoostApiParameters.isEnabled()) {
new CommitBoostPublicKeysRoute(context).register();
new CommitBoostGenerateProxyKeyRoute(
context, commitBoostApiParameters, eth2Spec, genesisValidatorsRoot)
.register();
}
}

@Override
Expand Down Expand Up @@ -166,7 +180,8 @@ protected List<ArtifactSignerProvider> createArtifactSignerProvider(

return signers;
}
}));
},
Optional.of(commitBoostApiParameters)));
}

private MappedResults<ArtifactSigner> loadSignersFromKeyConfigFiles(
Expand Down
Loading
Loading