Skip to content

Commit

Permalink
sign type BLOCK_v2 to support block signing for Altair and future for…
Browse files Browse the repository at this point in the history
…ks (#422)

* Introduce new sign type BLOCK_V2 which will allow Altair and future forks block signing requests. Keep BLOCK for phase 0 backward compatibility.
* Upgrade Teku libraries to support Altair fork on Prater network.
* Update OpenAPI spec. 
* Update Acceptance tests.
* Add network to AT DSL.
  • Loading branch information
usmansaleem authored Sep 2, 2021
1 parent 4d030f9 commit 15fc5c5
Show file tree
Hide file tree
Showing 28 changed files with 640 additions and 138 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Changelog

## 21.8.1

### Features Added
- Added sign type BLOCK_V2 to support block signing for Phase0, Altair and future forks (Eth2 mode). BLOCK is not removed for
backward compatibility with PHASE0 blocks.
- Upgraded Teku libraries to 21.8.2 which added support for Altair upgrade on Prater testnet at epoch 36660.

### Bugs fixed
- Unable to sign blocks on testnet Pyrmont after Altair fork. (Thanks to [Sephiroth](https://github.com/3eph1r0th) for reporting it.)

## 21.8.0

### Features Added
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import static tech.pegasys.web3signer.dsl.utils.WaitUtils.waitFor;
import static tech.pegasys.web3signer.tests.AcceptanceTestBase.JSON_RPC_PATH;

import tech.pegasys.web3signer.core.service.http.SigningJsonModule;
import tech.pegasys.web3signer.core.service.http.SigningObjectMapperFactory;
import tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.Eth2SigningRequestBody;
import tech.pegasys.web3signer.core.signing.KeyType;
import tech.pegasys.web3signer.dsl.lotus.FilecoinJsonRpcEndpoint;
Expand Down Expand Up @@ -59,9 +59,7 @@ public class Signer extends FilecoinJsonRpcEndpoint {
public static final String RELOAD_ENDPOINT = "/reload";

public static final ObjectMapper ETH_2_INTERFACE_OBJECT_MAPPER =
new ObjectMapper()
.registerModule(new SigningJsonModule())
.setSerializationInclusion(Include.NON_NULL);
SigningObjectMapperFactory.createObjectMapper().setSerializationInclusion(Include.NON_NULL);
private static final String METRICS_ENDPOINT = "/metrics";

private final Web3SignerRunner runner;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ public class SignerConfiguration {
private final long slashingPruningSlotsPerEpoch;
private final long slashingPruningInterval;
private final Optional<Long> altairForkEpoch;
private final Optional<String> network;

public SignerConfiguration(
final String hostname,
Expand Down Expand Up @@ -84,7 +85,8 @@ public SignerConfiguration(
final boolean swaggerUIEnabled,
final boolean useConfigFile,
final Optional<Path> slashingDbPoolConfigurationFile,
final Optional<Long> altairForkEpoch) {
final Optional<Long> altairForkEpoch,
final Optional<String> network) {
this.hostname = hostname;
this.logLevel = logLevel;
this.httpRpcPort = httpRpcPort;
Expand Down Expand Up @@ -113,6 +115,7 @@ public SignerConfiguration(
this.useConfigFile = useConfigFile;
this.slashingProtectionDbPoolConfigurationFile = slashingDbPoolConfigurationFile;
this.altairForkEpoch = altairForkEpoch;
this.network = network;
}

public String hostname() {
Expand Down Expand Up @@ -234,4 +237,8 @@ public Optional<Path> getSlashingProtectionDbPoolConfigurationFile() {
public Optional<Long> getAltairForkEpoch() {
return altairForkEpoch;
}

public Optional<String> getNetwork() {
return network;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ public class SignerConfigurationBuilder {
private long slashingPruningSlotsPerEpoch = 1;
private long slashingPruningInterval = 1;
private Long altairForkEpoch = null;
private String network = null;

public SignerConfigurationBuilder withLogLevel(final Level logLevel) {
this.logLevel = logLevel;
Expand Down Expand Up @@ -201,6 +202,11 @@ public SignerConfigurationBuilder withAltairForkEpoch(final long altairForkEpoch
return this;
}

public SignerConfigurationBuilder withNetwork(final String network) {
this.network = network;
return this;
}

public SignerConfiguration build() {
if (mode == null) {
throw new IllegalArgumentException("Mode cannot be null");
Expand Down Expand Up @@ -233,6 +239,7 @@ public SignerConfiguration build() {
swaggerUIEnabled,
useConfigFile,
Optional.ofNullable(slashingProtectionDbPoolConfigurationFile),
Optional.ofNullable(altairForkEpoch));
Optional.ofNullable(altairForkEpoch),
Optional.ofNullable(network));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,11 @@ private String createEth2SlashingProtectionArgs() {
signerConfig.getAltairForkEpoch().get()));
}

if (signerConfig.getNetwork().isPresent()) {
yamlConfig.append(
String.format(YAML_STRING_FMT, "eth2.network", signerConfig.getNetwork().get()));
}

return yamlConfig.toString();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,11 @@ private Collection<String> createEth2Args() {
params.add(Long.toString(signerConfig.getAltairForkEpoch().get()));
}

if (signerConfig.getNetwork().isPresent()) {
params.add("--network");
params.add(signerConfig.getNetwork().get());
}

return params;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/*
* Copyright 2021 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.dsl.utils;

import tech.pegasys.teku.api.schema.Fork;
import tech.pegasys.teku.api.schema.altair.BeaconBlockAltair;
import tech.pegasys.teku.api.schema.altair.BeaconBlockBodyAltair;
import tech.pegasys.teku.core.signatures.SigningRootUtil;
import tech.pegasys.teku.spec.Spec;
import tech.pegasys.teku.spec.SpecMilestone;
import tech.pegasys.teku.spec.TestSpecFactory;
import tech.pegasys.teku.spec.datastructures.blocks.BeaconBlock;
import tech.pegasys.teku.spec.datastructures.state.ForkInfo;
import tech.pegasys.teku.spec.util.DataStructureUtil;
import tech.pegasys.web3signer.core.service.http.ArtifactType;
import tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.BlockRequest;
import tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.Eth2SigningRequestBody;

import org.apache.tuweni.bytes.Bytes;

public class Eth2BlockSigningRequestUtil {
private final SpecMilestone specMilestone;
private final DataStructureUtil dataStructureUtil;
private final SigningRootUtil signingRootUtil;
private final ForkInfo tekuForkInfo;
private final Fork tekuFork;
private final tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.ForkInfo forkInfo;
private final BeaconBlock beaconBlock;
private final Bytes signingRoot;

public Eth2BlockSigningRequestUtil(final SpecMilestone specMilestone) {
final Spec spec;
switch (specMilestone) {
case ALTAIR:
spec = TestSpecFactory.createMinimalAltair();
break;
case PHASE0:
spec = TestSpecFactory.createMinimalPhase0();
break;
default:
throw new IllegalStateException("Spec Milestone not yet supported: " + specMilestone);
}
this.specMilestone = specMilestone;
dataStructureUtil = new DataStructureUtil(spec);
signingRootUtil = new SigningRootUtil(spec);
tekuForkInfo = dataStructureUtil.randomForkInfo();
tekuFork = new Fork(tekuForkInfo.getFork());
forkInfo =
new tech.pegasys.web3signer.core.service.http.handlers.signing.eth2.ForkInfo(
tekuFork, tekuForkInfo.getGenesisValidatorsRoot());
beaconBlock = dataStructureUtil.randomBeaconBlock(0);
signingRoot = signingRootUtil.signingRootForSignBlock(beaconBlock, tekuForkInfo);
}

public Eth2SigningRequestBody createBlockV2Request() {
final BlockRequest blockRequest = new BlockRequest(specMilestone, getBeaconBlock());

return new Eth2SigningRequestBody(
ArtifactType.BLOCK_V2,
signingRoot,
forkInfo,
null,
blockRequest,
null,
null,
null,
null,
null,
null,
null,
null,
null);
}

public Eth2SigningRequestBody createLegacyBlockRequest() {
if (specMilestone != SpecMilestone.PHASE0) {
throw new IllegalStateException(
"Only PHASE0 spec is supported to create legacy BLOCK type signing request");
}

return new Eth2SigningRequestBody(
ArtifactType.BLOCK,
signingRoot,
forkInfo,
getBeaconBlock(),
null,
null,
null,
null,
null,
null,
null,
null,
null,
null);
}

private tech.pegasys.teku.api.schema.BeaconBlock getBeaconBlock() {
if (specMilestone == SpecMilestone.ALTAIR) {
return new BeaconBlockAltair(
beaconBlock.getSlot(),
beaconBlock.getProposerIndex(),
beaconBlock.getParentRoot(),
beaconBlock.getStateRoot(),
getBeaconBlockBodyAltair(beaconBlock.getBody()));
} else if (specMilestone == SpecMilestone.PHASE0) {
return new tech.pegasys.teku.api.schema.BeaconBlock(beaconBlock);
}

throw new IllegalStateException("Spec milestone not yet supported: " + specMilestone);
}

private BeaconBlockBodyAltair getBeaconBlockBodyAltair(
final tech.pegasys.teku.spec.datastructures.blocks.blockbody.BeaconBlockBody body) {
return new BeaconBlockBodyAltair(
tech.pegasys.teku.spec.datastructures.blocks.blockbody.versions.altair.BeaconBlockBodyAltair
.required(body));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
import tech.pegasys.teku.spec.Spec;
import tech.pegasys.teku.spec.SpecFactory;
import tech.pegasys.teku.spec.SpecMilestone;
import tech.pegasys.teku.spec.constants.Domain;
import tech.pegasys.teku.spec.datastructures.operations.versions.altair.ContributionAndProof;
import tech.pegasys.teku.spec.datastructures.operations.versions.altair.SyncAggregatorSelectionData;
Expand Down Expand Up @@ -78,6 +79,9 @@ public class Eth2RequestUtils {
syncCommitteeUtil.createContributionAndProof(
UInt64.valueOf(11), contribution, aggregatorSignature);

private static final Eth2BlockSigningRequestUtil ALTAIR_BLOCK_UTIL =
new Eth2BlockSigningRequestUtil(SpecMilestone.ALTAIR);

public static Eth2SigningRequestBody createCannedRequest(final ArtifactType artifactType) {
switch (artifactType) {
case DEPOSIT:
Expand All @@ -88,6 +92,8 @@ public static Eth2SigningRequestBody createCannedRequest(final ArtifactType arti
return createRandaoReveal();
case BLOCK:
return createBlockRequest();
case BLOCK_V2:
return ALTAIR_BLOCK_UTIL.createBlockV2Request();
case ATTESTATION:
return createAttestationRequest();
case AGGREGATION_SLOT:
Expand Down Expand Up @@ -139,6 +145,7 @@ private static Eth2SigningRequestBody createAggregateAndProof() {
null,
null,
null,
null,
aggregateAndProof,
null,
null,
Expand All @@ -160,6 +167,7 @@ private static Eth2SigningRequestBody createAggregationSlot() {
forkInfo,
null,
null,
null,
aggregationSlot,
null,
null,
Expand Down Expand Up @@ -189,6 +197,7 @@ private static Eth2SigningRequestBody createRandaoReveal() {
null,
null,
null,
null,
randaoReveal,
null,
null,
Expand All @@ -210,6 +219,7 @@ private static Eth2SigningRequestBody createVoluntaryExit() {
null,
null,
null,
null,
voluntaryExit,
null,
null,
Expand Down Expand Up @@ -241,6 +251,7 @@ private static Eth2SigningRequestBody createDepositRequest() {
null,
null,
null,
null,
depositMessage,
null,
null,
Expand Down Expand Up @@ -269,6 +280,7 @@ public static Eth2SigningRequestBody createAttestationRequest(
signingRoot,
forkInfo,
null,
null,
attestationData,
null,
null,
Expand Down Expand Up @@ -327,6 +339,7 @@ public static Eth2SigningRequestBody createBlockRequest(
null,
null,
null,
null,
null);
}

Expand Down Expand Up @@ -371,6 +384,7 @@ private static Eth2SigningRequestBody createSyncCommitteeMessageRequest() {
null,
null,
null,
null,
syncCommitteeMessage,
null,
null);
Expand Down Expand Up @@ -407,6 +421,7 @@ private static Eth2SigningRequestBody createSyncCommitteeSelectionProofRequest()
null,
null,
null,
null,
getSyncAggregatorSelectionData(slot, subcommitteeIndex),
null);
}
Expand Down Expand Up @@ -446,6 +461,7 @@ private static Eth2SigningRequestBody createSyncCommitteeContributionAndProofReq
null,
null,
null,
null,
getContributionAndProof());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ void receiveASignatureWhenSubmitSigningRequestToFilecoinEndpoint() {
final String configFilename = publicKey.toString().substring(2);
final Path keyConfigFile = testDirectory.resolve(configFilename + ".yaml");
metadataFileHelpers.createUnencryptedYamlFileAt(keyConfigFile, PRIVATE_KEY, KeyType.BLS);
setupSigner("filecoin");
setupFilecoinSigner();

final ValueNode id = JsonNodeFactory.instance.numberNode(1);
final ObjectMapper mapper = new ObjectMapper();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ void receiveASignatureWhenSubmitSigningRequestToFilecoinEndpoint() throws URISyn
metadataFileHelpers.createKeyStoreYamlFileAt(
keyConfigFile, Path.of(keyPath), "pass", KeyType.SECP256K1);

setupSigner("filecoin");
setupFilecoinSigner();

final ValueNode id = JsonNodeFactory.instance.numberNode(1);
final ObjectMapper mapper = new ObjectMapper();
Expand Down
Loading

0 comments on commit 15fc5c5

Please sign in to comment.