Skip to content

Commit

Permalink
Use GVR as ZERO. Update Signing root generator tests
Browse files Browse the repository at this point in the history
  • Loading branch information
usmansaleem committed Oct 30, 2024
1 parent 40d2c27 commit 6611ecd
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 93 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import tech.pegasys.teku.networks.Eth2NetworkConfiguration;
import tech.pegasys.web3signer.commandline.subcommands.Eth2SubCommand;

import org.apache.commons.lang3.StringUtils;
import picocli.CommandLine;

/** Mixin class to hold network overrides for the PicoCLI parser. */
Expand Down Expand Up @@ -74,6 +75,16 @@ public class PicoCliNetworkOverrides {
arity = "1")
private String trustedSetup = null; // Depends on network configuration

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

public void applyOverrides(final Eth2NetworkConfiguration.Builder builder) {
if (altairForkEpoch != null) {
builder.altairForkEpoch(altairForkEpoch);
Expand All @@ -93,5 +104,8 @@ public void applyOverrides(final Eth2NetworkConfiguration.Builder builder) {
if (trustedSetup != null) {
builder.trustedSetup(trustedSetup);
}
if (StringUtils.isNotBlank(genesisState)) {
builder.customGenesisState(genesisState);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@

import java.nio.file.Path;

import org.apache.commons.lang3.StringUtils;
import org.apache.tuweni.bytes.Bytes32;
import picocli.CommandLine;
import picocli.CommandLine.Model.CommandSpec;
Expand All @@ -30,6 +29,11 @@
import picocli.CommandLine.Spec;

public class PicoCommitBoostApiParameters implements CommitBoostParameters {
// commit boost client defaults gvr to ZERO for its domain calculations. Set this to `false` to
// use the actual network's gvr value
private static final boolean USE_ZERO_GENESIS_VALIDATORS_ROOT = true;
private Bytes32 genesisValidatorsRoot = Bytes32.ZERO;

@Spec private CommandSpec commandSpec; // injected by picocli

@CommandLine.Option(
Expand All @@ -53,19 +57,6 @@ public class PicoCommitBoostApiParameters implements CommitBoostParameters {
paramLabel = PATH_FORMAT_HELP)
private Path proxyKeystoresPasswordFile;

// note: In the future, this can be moved to PicoCliNetworkOverrides if we want to determine gvr
// for slashing protection etc. in advance before getting the first signing call from CL.
@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. It is used to determine the value of genesis validators root for Commit Boost API.",
arity = "1")
private String genesisState;

private Bytes32 genesisValidatorsRoot;

@Override
public boolean isEnabled() {
return isCommitBoostApiEnabled;
Expand All @@ -83,23 +74,9 @@ public Path getProxyKeystoresPasswordFile() {

@Override
public Bytes32 getGenesisValidatorsRoot() {
if (genesisValidatorsRoot == null) {
throw new IllegalStateException("Genesis validators root not set");
}
return genesisValidatorsRoot;
}

/**
* Apply genesis state overrides to the network configuration only if commit boost API is enabled.
*
* @param builder The network configuration builder to apply overrides to.
*/
public void applyOverrides(final Eth2NetworkConfiguration.Builder builder) {
if (isCommitBoostApiEnabled && StringUtils.isNotBlank(genesisState)) {
builder.customGenesisState(genesisState);
}
}

/**
* Validate the parameters for the commit boost API and initialize parameters which will be used
* during run operation.
Expand Down Expand Up @@ -127,20 +104,20 @@ public void validateParameters(final Eth2NetworkConfiguration eth2NetworkConfig)

/** Load genesis state and obtain genesis validators root. */
private void loadGenesisValidatorsRoot(final Eth2NetworkConfiguration eth2NetworkConfig) {
final String parameterExceptionMessage =
"Unable to load genesis state to determine genesis validators root. Please provide custom genesis state using --genesis-state";
final String genesisState =
eth2NetworkConfig
.getNetworkBoostrapConfig()
.getGenesisState()
.orElseThrow(
() -> new ParameterException(commandSpec.commandLine(), parameterExceptionMessage));
if (USE_ZERO_GENESIS_VALIDATORS_ROOT) {
return;
}
try {
final String genesisState =
eth2NetworkConfig.getNetworkBoostrapConfig().getGenesisState().orElseThrow();

final BeaconState beaconState =
ChainDataLoader.loadState(eth2NetworkConfig.getSpec(), genesisState);
genesisValidatorsRoot = beaconState.getGenesisValidatorsRoot();
this.genesisValidatorsRoot = beaconState.getGenesisValidatorsRoot();
} catch (final Exception e) {
throw new ParameterException(commandSpec.commandLine(), parameterExceptionMessage);
throw new ParameterException(
commandSpec.commandLine(),
"Unable to load genesis state to determine genesis validators root. Please provide custom genesis state using --Xgenesis-state");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,6 @@ private Eth2NetworkConfiguration.Builder createEth2NetworkConfigBuilder() {
final Eth2NetworkConfiguration.Builder builder = Eth2NetworkConfiguration.builder();
builder.applyNetworkDefaults(network);
networkOverrides.applyOverrides(builder); // custom fork epochs
commitBoostApiParameters.applyOverrides(builder); // genesis state
return builder;
} catch (final IllegalArgumentException e) {
throw new ParameterException(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import java.nio.file.Files;
import java.nio.file.Path;

import org.apache.tuweni.bytes.Bytes32;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
Expand Down Expand Up @@ -94,10 +93,5 @@ public Path getProxyKeystoresPath() {
public Path getProxyKeystoresPasswordFile() {
return passwordFile;
}

@Override
public Bytes32 getGenesisValidatorsRoot() {
return Bytes32.ZERO;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,63 +19,72 @@
import tech.pegasys.teku.bls.BLSSecretKey;
import tech.pegasys.teku.networks.Eth2NetworkConfiguration;
import tech.pegasys.teku.spec.Spec;
import tech.pegasys.teku.spec.datastructures.util.ChainDataLoader;
import tech.pegasys.teku.spec.networks.Eth2Network;
import tech.pegasys.web3signer.core.service.http.handlers.commitboost.json.ProxyKeyMessage;
import tech.pegasys.web3signer.core.service.http.handlers.commitboost.json.ProxyKeySignatureScheme;

import java.io.IOException;
import java.util.Optional;
import java.util.HashMap;
import java.util.Map;

import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;

class SigningRootGeneratorTest {
static Spec spec;
static Bytes32 genesisValidatorsRoot;
static final Bytes32 COMMIT_BOOST_COMPUTED_DOMAIN =
Bytes32.fromHexString("0x6d6d6f43b5303f2ad2010d699a76c8e62350947421a3e4a979779642cfdb0f66");
private static final Bytes32 GVR = Bytes32.ZERO;
private static final Map<Eth2Network, Bytes32> DOMAIN_MAP = new HashMap<>();
private static final Map<Eth2Network, Bytes32> BLS_PROXY_ROOT_MAP = new HashMap<>();
private static final String BLS_PRIVATE_KEY_1 =
"3ee2224386c82ffea477e2adf28a2929f5c349165a4196158c7f3a2ecca40f35";
private static final String BLS_PRIVATE_KEY_2 =
"32ae313afff2daa2ef7005a7f834bdf291855608fe82c24d30be6ac2017093a8";

@BeforeAll
static void initSpecAndGVR() {
final Eth2NetworkConfiguration.Builder builder = Eth2NetworkConfiguration.builder();
builder.applyNetworkDefaults(Eth2Network.MAINNET);
Eth2NetworkConfiguration eth2NetworkConfiguration = builder.build();
spec = eth2NetworkConfiguration.getSpec();

genesisValidatorsRoot =
eth2NetworkConfiguration
.getNetworkBoostrapConfig()
.getGenesisState()
.flatMap(
state -> {
try {
return Optional.of(
ChainDataLoader.loadState(spec, state).getGenesisValidatorsRoot());
} catch (IOException e) {
return Optional.empty();
}
})
.orElseThrow(() -> new RuntimeException("Genesis state for MAINNET cannot be loaded"));
static void initExpectedSigningRoots() {
// precalculated Domain values from Commit Boost client implementation
DOMAIN_MAP.put(
Eth2Network.MAINNET,
Bytes32.fromHexString(
"0x6d6d6f43f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a9"));
DOMAIN_MAP.put(
Eth2Network.HOLESKY,
Bytes32.fromHexString(
"0x6d6d6f435b83a23759c560b2d0c64576e1dcfc34ea94c4988f3e0d9f77f05387"));
DOMAIN_MAP.put(
Eth2Network.SEPOLIA,
Bytes32.fromHexString(
"0x6d6d6f43d3010778cd08ee514b08fe67b6c503b510987a4ce43f42306d97c67c"));
// precalculated Proxy Message Signing Root values from Commit Boost client implementation
BLS_PROXY_ROOT_MAP.put(
Eth2Network.MAINNET,
Bytes32.fromHexString(
"0x36700803956402c24e232e5da8d7dda12796ba96e49177f37daab87dd852f0cd"));
BLS_PROXY_ROOT_MAP.put(
Eth2Network.HOLESKY,
Bytes32.fromHexString(
"0xdb1b20106a8955ddb47eb2c8c2fe602af8801e61f682f068fc968c65644e45b6"));
BLS_PROXY_ROOT_MAP.put(
Eth2Network.SEPOLIA,
Bytes32.fromHexString(
"0x99615a149344fc1beffc2085ae98b676bff384b92b45dd28bc1f62127c41505e"));
}

@Test
void validComputedDomainForMAINNET() {
final SigningRootGenerator signingRootGenerator =
new SigningRootGenerator(spec, genesisValidatorsRoot);
assertThat(signingRootGenerator.getDomain()).isEqualTo(COMMIT_BOOST_COMPUTED_DOMAIN);
@ParameterizedTest
@EnumSource(names = {"MAINNET", "HOLESKY", "SEPOLIA"})
void validComputedDomain(final Eth2Network network) {
final Spec spec = getSpec(network);
final SigningRootGenerator signingRootGenerator = new SigningRootGenerator(spec, GVR);
assertThat(signingRootGenerator.getDomain()).isEqualTo(DOMAIN_MAP.get(network));
}

@Test
void computeSigningRootForBLSProxyKey() {
final SigningRootGenerator signingRootGenerator =
new SigningRootGenerator(spec, genesisValidatorsRoot);
@ParameterizedTest
@EnumSource(names = {"MAINNET", "HOLESKY", "SEPOLIA"})
void computeSigningRootForBLSProxyKey(final Eth2Network network) {
final Spec spec = getSpec(network);
final SigningRootGenerator signingRootGenerator = new SigningRootGenerator(spec, GVR);
final BLSPublicKey delegator =
new BLSKeyPair(BLSSecretKey.fromBytes(Bytes32.fromHexString(BLS_PRIVATE_KEY_1)))
.getPublicKey();
Expand All @@ -86,14 +95,19 @@ void computeSigningRootForBLSProxyKey() {
new ProxyKeyMessage(delegator.toHexString(), proxy.toHexString());
final Bytes signingRoot =
signingRootGenerator.computeSigningRoot(proxyKeyMessage, ProxyKeySignatureScheme.BLS);
assertThat(signingRoot)
.isEqualTo(
Bytes.fromHexString(
"0x148a095bf06bf227190b95dcc5c269e7d054d17c11d2a30499e0a41d2e200a05"));
// the expected value is calculated using the Commit Boost client implementation
assertThat(signingRoot).isEqualTo(BLS_PROXY_ROOT_MAP.get(network));
}

@Test
void computeSigningRootforSECPProxyKey() {
// TODO: Implement this test
}

private static Spec getSpec(final Eth2Network network) {
final Eth2NetworkConfiguration.Builder builder = Eth2NetworkConfiguration.builder();
builder.applyNetworkDefaults(network);
Eth2NetworkConfiguration eth2NetworkConfiguration = builder.build();
return eth2NetworkConfiguration.getSpec();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,12 @@ public interface CommitBoostParameters {
Path getProxyKeystoresPasswordFile();

/**
* The Genesis Validators Root for the network used by the commit boost signing operations.
* The Genesis Validators Root for the network used by the commit boost signing operations. The
* Commit Boost Client implementation uses ZERO as the default value.
*
* @return Genesis Validators Root as Bytes32
*/
Bytes32 getGenesisValidatorsRoot();
default Bytes32 getGenesisValidatorsRoot() {
return Bytes32.ZERO;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
import java.util.Optional;
import java.util.stream.IntStream;

import org.apache.tuweni.bytes.Bytes32;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
Expand Down Expand Up @@ -274,10 +273,5 @@ public Path getProxyKeystoresPath() {
public Path getProxyKeystoresPasswordFile() {
return passwordFile;
}

@Override
public Bytes32 getGenesisValidatorsRoot() {
return Bytes32.ZERO;
}
}
}

0 comments on commit 6611ecd

Please sign in to comment.