diff --git a/.circleci/config.yml b/.circleci/config.yml index be872aac1..42e20b819 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -4,7 +4,7 @@ version: 2.1 executors: executor_med: # 2cpu, 4G ram docker: - - image: cimg/openjdk:17.0 + - image: cimg/openjdk:21.0 auth: &docker-auth # Don't panic, throw away account to avoid Docker rate limits when downloading. # Second reason we're doing this is so that forked PRs from external contributors works ie env vars aren't visible to forked PRs from within contexts @@ -18,7 +18,7 @@ executors: executor_large: # 4cpu, 8G ram docker: - - image: cimg/openjdk:17.0 + - image: cimg/openjdk:21.0 auth: <<: *docker-auth resource_class: large @@ -30,7 +30,7 @@ executors: executor_large_with_fc_devnet: # 4cpu, 8G ram docker: # Primary container - - image: cimg/openjdk:17.0 + - image: cimg/openjdk:21.0 auth: <<: *docker-auth # Secondary container running lotus as devnet on port 7777 @@ -82,17 +82,17 @@ commands: - restore_cache: name: Restore cached gradle dependencies keys: - - deps-{{ checksum "build.gradle" }}-{{ .Branch }}-{{ .Revision }} - - deps-{{ checksum "build.gradle" }} - - deps- - machine_java_17: - description: "Install Java 17 on machine executors" + - deps21-{{ checksum "build.gradle" }}-{{ .Branch }}-{{ .Revision }} + - deps21-{{ checksum "build.gradle" }} + - deps21- + machine_java: + description: "Install Java 21 on machine executors" steps: - run: - name: Java 17 + name: Java 21 command: | sudo apt update - sudo apt install -q --assume-yes openjdk-17-jre-headless openjdk-17-jdk-headless + sudo apt install -q --assume-yes openjdk-21-jre-headless openjdk-21-jdk-headless sudo update-java-alternatives -a capture_test_results: description: "Capture test results" @@ -193,7 +193,7 @@ jobs: - capture_test_reports - save_cache: name: Caching gradle dependencies - key: deps-{{ checksum "build.gradle" }}-{{ .Branch }}-{{ .Revision }} + key: deps21-{{ checksum "build.gradle" }}-{{ .Branch }}-{{ .Revision }} paths: - .gradle - ~/.gradle @@ -223,20 +223,6 @@ jobs: - capture_test_results - capture_test_reports - performanceTests: - executor: executor_large - steps: - - prepare - - attach_workspace: - at: ~/project - - run: - name: Performance Tests - no_output_timeout: 20m - command: | - ./gradlew --no-daemon clean installDist - ./gradlew --no-daemon gatlingRun - - capture_test_reports - publish: executor: executor_med steps: @@ -259,7 +245,7 @@ jobs: - prepare - attach_workspace: at: ~/project - - machine_java_17 + - machine_java - run: name: build and test Docker image command: | @@ -272,7 +258,7 @@ jobs: - prepare - attach_workspace: at: ~/project - - machine_java_17 + - machine_java - docker_trust_sign - docker_publish_images @@ -282,7 +268,7 @@ jobs: - prepare - attach_workspace: at: ~/project - - machine_java_17 + - machine_java - docker_trust_sign - docker_publish_images @@ -372,12 +358,6 @@ workflows: <<: *filters-release-tags context: - protocols-signers - - performanceTests: - requires: - - build - filters: - tags: - <<: *filters-release-tags - publishOpenApiSpec: filters: branches: diff --git a/CHANGELOG.md b/CHANGELOG.md index b2043ab7f..cc38c88af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ this release. The Web3Signer docker image will also use Java 21, however, binary require Java 21 to be available on the host machine. - This is the last Web3Signer release to use the "filecoin" mode. The "filecoin" mode will be removed in a future release. +### Breaking Changes +- Use Java 21 for build and runtime. Remove Java 17 variant of docker image. zip/tar.gz distributions will require Java 21 or above to run Web3Signer. +- The Web3Signer metrics are now compatible with OpenMetrics data model. This results in the names of counter metrics to append `_total` suffix. Users may need to update their dashboards to reflect these changes. + ### Features Added - Added endpoint `/api/v1/eth2/ext/sign/:identifier` which is enabled using cli option `--Xsigning-ext-enabled=true`. This endpoint allows signing of additional data not covered by the remoting API specs. [#982](https://github.com/Consensys/web3signer/pull/982) diff --git a/acceptance-tests/build.gradle b/acceptance-tests/build.gradle index ab8cdf840..8d2197006 100644 --- a/acceptance-tests/build.gradle +++ b/acceptance-tests/build.gradle @@ -13,9 +13,8 @@ import groovy.text.SimpleTemplateEngine */ plugins { - id "de.undercouch.download" version "4.1.0" + id "de.undercouch.download" version "5.6.0" id "com.google.osdetector" version "1.7.3" - id "io.gatling.gradle" version "3.9.3.1" } dependencies { @@ -64,6 +63,7 @@ dependencies { testImplementation 'com.github.arteam:simple-json-rpc-server' testImplementation 'com.github.arteam:simple-json-rpc-client' testImplementation 'org.flywaydb:flyway-core' + testImplementation 'org.flywaydb:flyway-database-postgresql' testImplementation 'io.rest-assured:rest-assured' testImplementation 'org.jdbi:jdbi3-core' testImplementation 'org.zeroturnaround:zt-exec' @@ -80,8 +80,6 @@ dependencies { testImplementation 'com.azure:azure-security-keyvault-keys' testImplementation 'com.azure:azure-security-keyvault-secrets' - gatlingImplementation configurations.getByName("testImplementation") - implementation 'software.amazon.awssdk:auth' implementation 'software.amazon.awssdk:secretsmanager' implementation 'software.amazon.awssdk:kms' @@ -90,7 +88,7 @@ dependencies { test.enabled = false task cleanBesuInstall(type: Delete) { - delete "$buildDir/besu" + delete layout.buildDirectory.dir("besu") } task downloadBesu(type: Download) { @@ -98,7 +96,7 @@ task downloadBesu(type: Download) { // see gradle.properties for Besu URL return new SimpleTemplateEngine().createTemplate(besuDistroUrl).make(["besuVersion":"$besuVersion"]).toString() } - dest new File(buildDir, "besu-${besuVersion}.tar.gz") + dest layout.buildDirectory.file("downloads/besu-${besuVersion}.tar.gz") onlyIfModified true retries 3 } @@ -114,15 +112,15 @@ task extractBesu(dependsOn: [ } includeEmptyDirs = false } - into "$buildDir/besu" + into layout.buildDirectory.dir("besu") } def vaultBinary () { switch (osdetector.os) { case "windows": - return new File(buildDir, "vault.exe").toString() + return layout.buildDirectory.file("vault-bin/vault.exe").get().toString() default: - return new File(buildDir, "vault").toString() + return layout.buildDirectory.file("vault-bin/vault").get().toString() } } @@ -154,13 +152,13 @@ task downloadVault(type: Download) { src { return vaultDownloadUrl() } - dest new File(buildDir, "hashicorp.zip") + dest layout.buildDirectory.file("downloads/hashicorp.zip") onlyIfModified true } task extractVault(dependsOn: downloadVault, type: Copy) { from zipTree(downloadVault.dest) - into buildDir + into layout.buildDirectory.dir("vault-bin") } task acceptanceTest(dependsOn: [ diff --git a/acceptance-tests/src/gatling/scala/Eth2SignSimulation.scala b/acceptance-tests/src/gatling/scala/Eth2SignSimulation.scala deleted file mode 100644 index 101233a6c..000000000 --- a/acceptance-tests/src/gatling/scala/Eth2SignSimulation.scala +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2020 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. - */ -import java.nio.file.{Files, Path} -import java.util.concurrent.atomic.AtomicInteger -import io.gatling.core.Predef._ -import io.gatling.http.Predef._ -import tech.pegasys.web3signer.dsl.signer.{Signer, SignerConfigurationBuilder} -import tech.pegasys.web3signer.dsl.utils.MetadataFileHelpers -import tech.pegasys.web3signer.signing.KeyType - -import scala.jdk.CollectionConverters.IterableHasAsScala -import scala.concurrent.duration.DurationInt -import scala.language.postfixOps - -class Eth2SignSimulation extends Simulation { - private val keyStoreDirectory: Path = Files.createTempDirectory("bls") - new MetadataFileHelpers().createRandomUnencryptedBlsKeys(keyStoreDirectory, 1000) - - System.setProperty("acctests.runWeb3SignerAsProcess", "true") - private val signer = new Signer(new SignerConfigurationBuilder() - .withKeyStoreDirectory(keyStoreDirectory) - .withMode("eth2") - .withSlashingEnabled(true) - .withSlashingProtectionDbUsername("postgres") - .withSlashingProtectionDbPassword("postgres") - .build(), null) - signer.start() - - after { - signer.shutdown() - } - - private val httpProtocol = http.baseUrl(signer.getUrl) - private val slot = new AtomicInteger(0) - private val slots: Iterator[Map[String, Int]] = Iterator.continually(Map("slot" -> slot.getAndIncrement())) - private val addresses = signer.listPublicKeys(KeyType.BLS).asScala.map(a => Map("address" -> a)).toArray.circular - - private val signing = scenario("Signing") - .feed(addresses) - .feed(slots) - .exec(http("signingRequest") - .post("/api/v1/eth2/sign/${address}") - .header("content-type", "application/json") - .body(StringBody( - """{ - | "type":"block", - | "fork_info":{ - | "fork":{ - | "previous_version":"0x00000001", - | "current_version":"0x00000001", - | "epoch":"0" - | }, - | "genesis_validators_root":"0x270d43e74ce340de4bca2b1936beca0f4f5408d9e78aec4850920baf659d5b69" - | }, - | "block":{ - | "slot":"${slot}", - | "proposer_index":"5", - | "parent_root":"0xb2eedb01adbd02c828d5eec09b4c70cbba12ffffba525ebf48aca33028e8ad89", - | "state_root":"0x2b530d6262576277f1cc0dbe341fd919f9f8c5c92fc9140dff6db4ef34edea0d", - | "body":{ - | "randao_reveal":"0xa686652aed2617da83adebb8a0eceea24bb0d2ccec9cd691a902087f90db16aa5c7b03172a35e874e07e3b60c5b2435c0586b72b08dfe5aee0ed6e5a2922b956aa88ad0235b36dfaa4d2255dfeb7bed60578d982061a72c7549becab19b3c12f", - | "eth1_data":{ - | "deposit_root":"0x6a0f9d6cb0868daa22c365563bb113b05f7568ef9ee65fdfeb49a319eaf708cf", - | "deposit_count":"8", - | "block_hash":"0x4242424242424242424242424242424242424242424242424242424242424242" - | }, - | "graffiti":"0x74656b752f76302e31322e31302d6465762d6338316361363235000000000000", - | "proposer_slashings":[], - | "attester_slashings":[], - | "attestations":[], - | "deposits":[], - | "voluntary_exits":[] - | } - | } - |} - |""".stripMargin) - ).check(status.is(200))) - - val constantTxRate = 100 - setUp(signing.inject( - constantUsersPerSec(constantTxRate) during (60 seconds), - ).protocols(httpProtocol)) -} diff --git a/acceptance-tests/src/gatling/scala/FcBlsSignSimulation.scala b/acceptance-tests/src/gatling/scala/FcBlsSignSimulation.scala deleted file mode 100644 index 316695971..000000000 --- a/acceptance-tests/src/gatling/scala/FcBlsSignSimulation.scala +++ /dev/null @@ -1,58 +0,0 @@ -import java.nio.file.{Files, Path} -import java.util - -import io.gatling.core.Predef.{rampUsersPerSec, _} -import io.gatling.http.Predef._ -import org.apache.tuweni.bytes.Bytes -import tech.pegasys.web3signer.dsl.signer.SignerConfigurationBuilder -import tech.pegasys.web3signer.dsl.signer.Signer -import tech.pegasys.web3signer.dsl.utils.MetadataFileHelpers - -import scala.jdk.CollectionConverters.IterableHasAsScala -import scala.concurrent.duration.DurationInt -import scala.language.postfixOps - -class FcBlsSignSimulation extends Simulation { - private val keyStoreDirectory: Path = Files.createTempDirectory("bls") - new MetadataFileHelpers().createRandomUnencryptedBlsKeys(keyStoreDirectory, 1000) - - System.setProperty("acctests.runWeb3SignerAsProcess", "true") - private val runner = new Signer(new SignerConfigurationBuilder() - .withKeyStoreDirectory(keyStoreDirectory).withMode("filecoin").build(), null) - runner.start() - - after { - runner.shutdown() - } - - private val httpProtocol = http.baseUrl(runner.getUrl()) - private val addresses: util.List[String] = runner.walletList() - private val feeder = addresses.asScala.map(a => Map("address" -> a, - "data" -> Bytes.random(64).toHexString)).toArray.random - - private val signing = scenario("Signing") - .feed(feeder) - .exec(http("signingRequest") - - .post("/rpc/v0/") - .body(StringBody( - """{ - | "jsonrpc": "2.0", - | "method": "Filecoin.WalletSign", - | "params":["${address}", "${data}"], - | "id": 1 - |}""".stripMargin) - ).asJson.check(jsonPath("$.result").not(""), jsonPath("$.result").notNull)) - - val constantTxRate = 10 - val burstTxRate = 100 - setUp(signing.inject( - nothingFor(10 seconds), - constantUsersPerSec(constantTxRate) during (60 seconds), - rampUsersPerSec(burstTxRate) to 0 during (5 seconds), - constantUsersPerSec(constantTxRate) during (60 seconds), - rampUsersPerSec(burstTxRate) to 0 during (5 seconds), - ).protocols(httpProtocol)) - .assertions(global.failedRequests.count.in(0)) - -} diff --git a/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/signer/Signer.java b/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/signer/Signer.java index 52924740d..2d9600248 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/signer/Signer.java +++ b/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/signer/Signer.java @@ -30,8 +30,9 @@ import tech.pegasys.web3signer.dsl.tls.ClientTlsConfig; import tech.pegasys.web3signer.signing.KeyType; -import java.util.Arrays; +import java.util.AbstractMap; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -39,8 +40,6 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.common.base.Splitter; -import com.google.common.collect.Iterables; import io.restassured.common.mapper.TypeRef; import io.restassured.http.ContentType; import io.restassured.response.Response; @@ -204,16 +203,28 @@ public static String signPath(final KeyType keyType) { return keyType == BLS ? ETH2_SIGN_ENDPOINT : ETH1_SIGN_ENDPOINT; } - public Set getMetricsMatching(final List metricsOfInterest) { + public Map getMetricsMatching(final Set metricsOfInterest) { final Response response = given().baseUri(getMetricsUrl()).contentType(ContentType.JSON).when().get(METRICS_ENDPOINT); - final List lines = - Arrays.asList(response.getBody().asString().split(String.format("%n")).clone()); + return response + .getBody() + .asString() + .lines() + .filter(line -> !line.startsWith("#")) // remove comments + .map(Signer::splitMetrics) + .filter(entry -> metricsOfInterest.contains(entry.getKey())) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + } - return lines.stream() - .filter(line -> metricsOfInterest.contains(Iterables.get(Splitter.on(' ').split(line), 0))) - .collect(Collectors.toSet()); + private static Map.Entry splitMetrics(final String input) { + if (input == null || input.isEmpty()) { + return new AbstractMap.SimpleEntry<>("", ""); + } + final String[] tokens = input.split("\\s+", 2); // Split into two parts: key and the rest + final String key = tokens.length > 0 ? tokens[0] : ""; + final String value = tokens.length > 1 ? tokens[1] : ""; + return new AbstractMap.SimpleEntry<>(key, value); } public String getSlashingDbUrl() { diff --git a/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/tls/TlsCertificateDefinition.java b/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/tls/TlsCertificateDefinition.java index 3823690a8..08db5ab19 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/tls/TlsCertificateDefinition.java +++ b/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/tls/TlsCertificateDefinition.java @@ -75,7 +75,9 @@ public List certificates() @SuppressWarnings("JdkObsolete") public List keys() - throws KeyStoreException, NoSuchAlgorithmException, CertificateException, + throws KeyStoreException, + NoSuchAlgorithmException, + CertificateException, UnrecoverableKeyException { final List results = Lists.newArrayList(); diff --git a/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2RequestUtils.java b/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2RequestUtils.java index 42f04ee7a..9a6a6fb5f 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2RequestUtils.java +++ b/acceptance-tests/src/test/java/tech/pegasys/web3signer/dsl/utils/Eth2RequestUtils.java @@ -121,19 +121,22 @@ public static Eth2SigningRequestBody createCannedRequest(final ArtifactType arti private static Eth2SigningRequestBody createAggregateAndProof() { final ForkInfo forkInfo = forkInfo(); final Bytes sszBytes = Bytes.of(0, 0, 1, 1); + final AttestationData attestationData = + new AttestationData( + UInt64.ZERO, + UInt64.ZERO, + Bytes32.fromHexString( + "0x100814c335d0ced5014cfa9d2e375e6d9b4e197381f8ce8af0473200fdc917fd"), + new Checkpoint(UInt64.ZERO, Bytes32.ZERO), + new Checkpoint( + UInt64.ZERO, + Bytes32.fromHexString( + "0x100814c335d0ced5014cfa9d2e375e6d9b4e197381f8ce8af0473200fdc917fd"))); final Attestation attestation = new Attestation( sszBytes, - new AttestationData( - UInt64.ZERO, - UInt64.ZERO, - Bytes32.fromHexString( - "0x100814c335d0ced5014cfa9d2e375e6d9b4e197381f8ce8af0473200fdc917fd"), - new Checkpoint(UInt64.ZERO, Bytes32.ZERO), - new Checkpoint( - UInt64.ZERO, - Bytes32.fromHexString( - "0x100814c335d0ced5014cfa9d2e375e6d9b4e197381f8ce8af0473200fdc917fd"))), + attestationData, + sszBytes, // committee_bits BLSSignature.fromHexString( "0xa627242e4a5853708f4ebf923960fb8192f93f2233cd347e05239d86dd9fb66b721ceec1baeae6647f498c9126074f1101a87854d674b6eebc220fd8c3d8405bdfd8e286b707975d9e00a56ec6cbbf762f23607d490f0bbb16c3e0e483d51875")); final BLSSignature selectionProof = diff --git a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/AcceptanceTestBase.java b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/AcceptanceTestBase.java index 32d108723..f55d68c64 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/AcceptanceTestBase.java +++ b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/AcceptanceTestBase.java @@ -18,6 +18,8 @@ import tech.pegasys.web3signer.dsl.signer.SignerConfiguration; import tech.pegasys.web3signer.signing.KeyType; +import java.util.Set; + import org.junit.jupiter.api.AfterEach; public class AcceptanceTestBase { @@ -27,6 +29,13 @@ public class AcceptanceTestBase { public static final Long FILECOIN_CHAIN_ID = 314L; public static final Long DEFAULT_CHAIN_ID = 1337L; + protected static final String ETH_2_SLASHINGPROTECTION_PERMITTED_SIGNINGS = + "eth2_slashingprotection_permitted_signings_total"; + protected static final String ETH_2_SLASHINGPROTECTION_PREVENTED_SIGNINGS = + "eth2_slashingprotection_prevented_signings_total"; + protected static final Set ETH2_SLASHINGPROTECTION_METRICS = + Set.of( + ETH_2_SLASHINGPROTECTION_PERMITTED_SIGNINGS, ETH_2_SLASHINGPROTECTION_PREVENTED_SIGNINGS); protected void startSigner(final SignerConfiguration config) { signer = new Signer(config, null); diff --git a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/HttpHostAllowListAcceptanceTest.java b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/HttpHostAllowListAcceptanceTest.java index d8b9d1c5d..817fbf91d 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/HttpHostAllowListAcceptanceTest.java +++ b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/HttpHostAllowListAcceptanceTest.java @@ -31,8 +31,6 @@ import io.restassured.http.ContentType; import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; public class HttpHostAllowListAcceptanceTest extends AcceptanceTestBase { private static final String UPCHECK_ENDPOINT = "/upcheck"; @@ -93,10 +91,8 @@ void httpEndpointForNonAllowedHostRespondsWithForbiddenResponse() { .statusCode(403); } - @ParameterizedTest - @ValueSource(strings = {"Host: \r\n", ""}) - void httpEndpointWithoutHostHeaderRespondsWithForbiddenResponse(final String rawHeader) - throws Exception { + @Test + void upcheckWithoutValueInHostHeaderRespondsWithForbiddenResponse() throws Exception { final SignerConfiguration signerConfiguration = new SignerConfigurationBuilder() .withHttpAllowHostList(Collections.singletonList("127.0.0.1")) @@ -116,7 +112,7 @@ void httpEndpointWithoutHostHeaderRespondsWithForbiddenResponse(final String raw + UPCHECK_ENDPOINT + " HTTP/1.1\r\n" + "Connection: close\r\n" // signals server to close the connection - + rawHeader + + "Host: \r\n" + "\r\n"; // end of headers section writer.write(req); writer.flush(); @@ -127,4 +123,36 @@ void httpEndpointWithoutHostHeaderRespondsWithForbiddenResponse(final String raw assertThat(response).contains("{\"message\":\"Host not authorized.\"}"); } } + + @Test + void upcheckWithoutHostHeaderRespondsWithBadRequest() throws Exception { + final SignerConfiguration signerConfiguration = + new SignerConfigurationBuilder() + .withHttpAllowHostList(Collections.singletonList("127.0.0.1")) + .withMode("eth2") + .build(); + startSigner(signerConfiguration); + + // raw request without Host header + final URI uri = URI.create(signer.getUrl()); + try (final Socket s = new Socket(InetAddress.getLoopbackAddress(), uri.getPort()); + final PrintWriter writer = + new PrintWriter(new OutputStreamWriter(s.getOutputStream(), UTF_8), true); + final BufferedReader reader = + new BufferedReader(new InputStreamReader(s.getInputStream(), UTF_8))) { + final String req = + "GET " + + UPCHECK_ENDPOINT + + " HTTP/1.1\r\n" + + "Connection: close\r\n" // signals server to close the connection + + "\r\n"; // end of headers section + writer.write(req); + writer.flush(); + + final String response = reader.lines().collect(Collectors.joining("\n")); + + assertThat(response).startsWith("HTTP/1.1 400 Bad Request"); + assertThat(response).contains("Bad Request"); + } + } } diff --git a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/MetricsAcceptanceTest.java b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/MetricsAcceptanceTest.java index b84a827dd..041125eb2 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/MetricsAcceptanceTest.java +++ b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/MetricsAcceptanceTest.java @@ -29,8 +29,8 @@ import java.security.InvalidAlgorithmParameterException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; -import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.Set; import com.fasterxml.jackson.core.JsonProcessingException; @@ -59,42 +59,48 @@ void filecoinApisAreCounted(final boolean useConfigFile) { .build(); startSigner(signerConfiguration); - final List metricsOfInterest = - List.of( - "filecoin_" + SECP256K1.name().toLowerCase(Locale.ROOT) + "_signing_request_count", - "filecoin_" + BLS.name().toLowerCase(Locale.ROOT) + "_signing_request_count", - "filecoin_total_request_count", - "filecoin_wallet_has_count", - "filecoin_wallet_list_count", - "filecoin_wallet_sign_message_count"); - - final Set initialMetrics = signer.getMetricsMatching(metricsOfInterest); + final Set metricsOfInterest = + Set.of( + "filecoin_" + + SECP256K1.name().toLowerCase(Locale.ROOT) + + "_signing_request_count_total", + "filecoin_" + BLS.name().toLowerCase(Locale.ROOT) + "_signing_request_count_total", + "filecoin_total_request_count_total", + "filecoin_wallet_has_count_total", + "filecoin_wallet_list_count_total", + "filecoin_wallet_sign_message_count_total"); + + final Map initialMetrics = signer.getMetricsMatching(metricsOfInterest); assertThat(initialMetrics).hasSize(metricsOfInterest.size()); - assertThat(initialMetrics).allMatch(s -> s.endsWith("0.0")); + assertThat(initialMetrics).values().allMatch(s -> s.endsWith("0.0")); signer.walletHas("t01234"); - final Set metricsAfterWalletHas = signer.getMetricsMatching(metricsOfInterest); - metricsAfterWalletHas.removeAll(initialMetrics); + final Map metricsAfterWalletHas = signer.getMetricsMatching(metricsOfInterest); assertThat(metricsAfterWalletHas) - .containsOnly("filecoin_total_request_count 1.0", "filecoin_wallet_has_count 1.0"); + .containsAllEntriesOf( + Map.of( + "filecoin_total_request_count_total", + "1.0", + "filecoin_wallet_has_count_total", + "1.0")); signer.walletList(); - final Set metricsAfterWalletList = signer.getMetricsMatching(metricsOfInterest); - metricsAfterWalletList.removeAll(initialMetrics); - metricsAfterWalletList.removeAll(metricsAfterWalletHas); + final Map metricsAfterWalletList = signer.getMetricsMatching(metricsOfInterest); assertThat(metricsAfterWalletList) - .containsOnly("filecoin_total_request_count 2.0", "filecoin_wallet_list_count 1.0"); + .containsAllEntriesOf( + Map.of( + "filecoin_total_request_count_total", + "2.0", + "filecoin_wallet_has_count_total", + "1.0")); try { signer.walletSign("t01234", Bytes.fromHexString("0x1234")); } catch (final Exception e) { // it is known that the signing will fail. } - final Set metricsAfterWalletSign = signer.getMetricsMatching(metricsOfInterest); - metricsAfterWalletSign.removeAll(initialMetrics); - metricsAfterWalletSign.removeAll(metricsAfterWalletList); - metricsAfterWalletSign.removeAll(metricsAfterWalletHas); - assertThat(metricsAfterWalletSign).containsOnly("filecoin_total_request_count 3.0"); + final Map metricsAfterWalletSign = signer.getMetricsMatching(metricsOfInterest); + assertThat(metricsAfterWalletSign).containsEntry("filecoin_total_request_count_total", "3.0"); } @Test @@ -108,17 +114,17 @@ void missingSignerMetricIncreasesWhenUnmatchedRequestReceived() throws JsonProce .build(); startSigner(signerConfiguration); - final List metricsOfInterest = List.of("signing_bls_missing_identifier_count"); + final Set metricsOfInterest = Set.of("signing_bls_missing_identifier_count_total"); - final Set initialMetrics = signer.getMetricsMatching(metricsOfInterest); + final Map initialMetrics = signer.getMetricsMatching(metricsOfInterest); assertThat(initialMetrics).hasSize(metricsOfInterest.size()); - assertThat(initialMetrics).allMatch(s -> s.endsWith("0.0")); + assertThat(initialMetrics).containsEntry("signing_bls_missing_identifier_count_total", "0.0"); signer.eth2Sign( "12345", Eth2RequestUtils.createBlockRequest(UInt64.valueOf(1), Bytes32.fromHexString("0x1111"))); - final Set metricsAfterSign = signer.getMetricsMatching(metricsOfInterest); - assertThat(metricsAfterSign).containsOnly("signing_bls_missing_identifier_count 1.0"); + final Map metricsAfterSign = signer.getMetricsMatching(metricsOfInterest); + assertThat(metricsAfterSign).containsEntry("signing_bls_missing_identifier_count_total", "1.0"); } @Test @@ -143,25 +149,30 @@ void signMetricIncrementsWhenSecpSignRequestReceived(@TempDir final Path testDir startSigner(signerConfiguration); - final List metricsOfInterest = - List.of( + final Set metricsOfInterest = + Set.of( "signing_" + SECP256K1.name().toLowerCase(Locale.ROOT) + "_signing_duration_count", - "signing_" + SECP256K1.name().toLowerCase(Locale.ROOT) + "_missing_identifier_count"); - final Set initialMetrics = signer.getMetricsMatching(metricsOfInterest); + "signing_" + + SECP256K1.name().toLowerCase(Locale.ROOT) + + "_missing_identifier_count_total"); + final Map initialMetrics = signer.getMetricsMatching(metricsOfInterest); assertThat(initialMetrics).hasSize(metricsOfInterest.size()); - assertThat(initialMetrics).allMatch(s -> s.endsWith("0.0")); + assertThat(initialMetrics).values().allMatch(s -> s.endsWith("0.0")); signer.eth1Sign( Numeric.toHexStringWithPrefixZeroPadded(keyPair.getPublicKey(), 128), Bytes.fromHexString("1122")); - final Set metricsAfterSign = signer.getMetricsMatching(metricsOfInterest); + final Map metricsAfterSign = signer.getMetricsMatching(metricsOfInterest); assertThat(metricsAfterSign) - .containsOnly( - "signing_" + SECP256K1.name().toLowerCase(Locale.ROOT) + "_signing_duration_count 1.0", - "signing_" - + SECP256K1.name().toLowerCase(Locale.ROOT) - + "_missing_identifier_count 0.0"); + .containsAllEntriesOf( + Map.of( + "signing_" + SECP256K1.name().toLowerCase(Locale.ROOT) + "_signing_duration_count", + "1.0", + "signing_" + + SECP256K1.name().toLowerCase(Locale.ROOT) + + "_missing_identifier_count_total", + "0.0")); } @Test @@ -185,22 +196,26 @@ void signMetricIncrementsWhenBlsSignRequestReceived(@TempDir final Path testDire startSigner(signerConfiguration); - final List metricsOfInterest = - List.of( + final Set metricsOfInterest = + Set.of( "signing_" + BLS.name().toLowerCase(Locale.ROOT) + "_signing_duration_count", - "signing_" + BLS.name().toLowerCase(Locale.ROOT) + "_missing_identifier_count"); - final Set initialMetrics = signer.getMetricsMatching(metricsOfInterest); + "signing_" + BLS.name().toLowerCase(Locale.ROOT) + "_missing_identifier_count_total"); + final Map initialMetrics = signer.getMetricsMatching(metricsOfInterest); assertThat(initialMetrics).hasSize(metricsOfInterest.size()); - assertThat(initialMetrics).allMatch(s -> s.endsWith("0.0")); + assertThat(initialMetrics).values().allMatch(s -> s.endsWith("0.0")); signer.eth2Sign( keyPair.getPublicKey().toBytesCompressed().toHexString(), Eth2RequestUtils.createBlockRequest(UInt64.valueOf(1), Bytes32.fromHexString("0x1111"))); - final Set metricsAfterSign = signer.getMetricsMatching(metricsOfInterest); + final Map metricsAfterSign = signer.getMetricsMatching(metricsOfInterest); assertThat(metricsAfterSign) - .containsOnly( - "signing_" + BLS.name().toLowerCase(Locale.ROOT) + "_signing_duration_count 1.0", - "signing_" + BLS.name().toLowerCase(Locale.ROOT) + "_missing_identifier_count 0.0"); + .containsAllEntriesOf( + Map.of( + "signing_" + BLS.name().toLowerCase(Locale.ROOT) + "_signing_duration_count", "1.0", + "signing_" + + BLS.name().toLowerCase(Locale.ROOT) + + "_missing_identifier_count_total", + "0.0")); } } diff --git a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/bulkloading/SecpV3KeystoresBulkLoadAcceptanceTest.java b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/bulkloading/SecpV3KeystoresBulkLoadAcceptanceTest.java index eb5b1f8b1..1ef6afba1 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/bulkloading/SecpV3KeystoresBulkLoadAcceptanceTest.java +++ b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/bulkloading/SecpV3KeystoresBulkLoadAcceptanceTest.java @@ -45,9 +45,9 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import org.web3j.crypto.CipherException; import org.web3j.crypto.ECKeyPair; import org.web3j.crypto.Keys; +import org.web3j.crypto.exception.CipherException; public class SecpV3KeystoresBulkLoadAcceptanceTest extends AcceptanceTestBase { @TempDir private static Path keystoresDir; diff --git a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsSigningAcceptanceTest.java b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsSigningAcceptanceTest.java index 0ff16ba0c..3c4b8681a 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsSigningAcceptanceTest.java +++ b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsSigningAcceptanceTest.java @@ -341,8 +341,11 @@ private void signAndVerifySignature( private void setupMinimalWeb3Signer(final ArtifactType artifactType) { switch (artifactType) { - case BLOCK_V2, SYNC_COMMITTEE_MESSAGE, SYNC_COMMITTEE_SELECTION_PROOF, SYNC_COMMITTEE_CONTRIBUTION_AND_PROOF -> setupEth2Signer( - Eth2Network.MINIMAL, SpecMilestone.ALTAIR); + case BLOCK_V2, + SYNC_COMMITTEE_MESSAGE, + SYNC_COMMITTEE_SELECTION_PROOF, + SYNC_COMMITTEE_CONTRIBUTION_AND_PROOF -> + setupEth2Signer(Eth2Network.MINIMAL, SpecMilestone.ALTAIR); default -> setupEth2Signer(Eth2Network.MINIMAL, SpecMilestone.PHASE0); } } diff --git a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsSigningRootPropertyAcceptanceTest.java b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsSigningRootPropertyAcceptanceTest.java index 6719f2cb1..1a8b133cf 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsSigningRootPropertyAcceptanceTest.java +++ b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/signing/BlsSigningRootPropertyAcceptanceTest.java @@ -89,8 +89,11 @@ private void signAndVerifySignature(final String signingRootProperty) private void setupMinimalWeb3Signer(final ArtifactType artifactType) { switch (artifactType) { - case BLOCK_V2, SYNC_COMMITTEE_MESSAGE, SYNC_COMMITTEE_SELECTION_PROOF, SYNC_COMMITTEE_CONTRIBUTION_AND_PROOF -> setupEth2Signer( - Eth2Network.MINIMAL, SpecMilestone.ALTAIR); + case BLOCK_V2, + SYNC_COMMITTEE_MESSAGE, + SYNC_COMMITTEE_SELECTION_PROOF, + SYNC_COMMITTEE_CONTRIBUTION_AND_PROOF -> + setupEth2Signer(Eth2Network.MINIMAL, SpecMilestone.ALTAIR); default -> setupEth2Signer(Eth2Network.MINIMAL, SpecMilestone.PHASE0); } } diff --git a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/slashing/SlashingExportAcceptanceTest.java b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/slashing/SlashingExportAcceptanceTest.java index a50443374..6fe08a18b 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/slashing/SlashingExportAcceptanceTest.java +++ b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/slashing/SlashingExportAcceptanceTest.java @@ -31,7 +31,7 @@ import java.io.IOException; import java.nio.file.Path; -import java.util.List; +import java.util.Map; import com.fasterxml.jackson.databind.ObjectMapper; import dsl.InterchangeV5Format; @@ -46,12 +46,8 @@ public class SlashingExportAcceptanceTest extends AcceptanceTestBase { private static final MetadataFileHelpers METADATA_FILE_HELPERS = new MetadataFileHelpers(); public static final String DB_USERNAME = "postgres"; public static final String DB_PASSWORD = "postgres"; - protected final BLSKeyPair keyPair = BLSTestUtil.randomKeyPair(0); - final List blockSlashingMetrics = - List.of( - "eth2_slashingprotection_permitted_signings", - "eth2_slashingprotection_prevented_signings"); + protected final BLSKeyPair keyPair = BLSTestUtil.randomKeyPair(0); void setupSigner(final Path testDirectory, final boolean enableSlashing) { final SignerConfigurationBuilder builder = @@ -78,8 +74,13 @@ void slashingDataIsExported(@TempDir final Path testDirectory) throws IOExceptio final Response initialResponse = signer.eth2Sign(keyPair.getPublicKey().toString(), request); assertThat(initialResponse.getStatusCode()).isEqualTo(200); - assertThat(signer.getMetricsMatching(blockSlashingMetrics)) - .containsOnly(blockSlashingMetrics.get(0) + " 1.0", blockSlashingMetrics.get(1) + " 0.0"); + assertThat(signer.getMetricsMatching(ETH2_SLASHINGPROTECTION_METRICS)) + .containsAllEntriesOf( + Map.of( + ETH_2_SLASHINGPROTECTION_PERMITTED_SIGNINGS, + "1.0", + ETH_2_SLASHINGPROTECTION_PREVENTED_SIGNINGS, + "0.0")); final Path exportFile = testDirectory.resolve("dbExport.json"); final SignerConfigurationBuilder builder = new SignerConfigurationBuilder(); diff --git a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/slashing/SlashingProtectionAcceptanceTest.java b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/slashing/SlashingProtectionAcceptanceTest.java index 3fc2756c8..e98a0115c 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/slashing/SlashingProtectionAcceptanceTest.java +++ b/acceptance-tests/src/test/java/tech/pegasys/web3signer/tests/slashing/SlashingProtectionAcceptanceTest.java @@ -26,7 +26,7 @@ import tech.pegasys.web3signer.tests.AcceptanceTestBase; import java.nio.file.Path; -import java.util.List; +import java.util.Map; import com.fasterxml.jackson.core.JsonProcessingException; import io.restassured.response.Response; @@ -44,16 +44,6 @@ public class SlashingProtectionAcceptanceTest extends AcceptanceTestBase { protected final BLSKeyPair keyPair = BLSTestUtil.randomKeyPair(0); static final int SLASHING_PROTECTION_ENFORCED = 412; - final List attestationSlashingMetrics = - List.of( - "eth2_slashingprotection_permitted_signings", - "eth2_slashingprotection_prevented_signings"); - - final List blockSlashingMetrics = - List.of( - "eth2_slashingprotection_permitted_signings", - "eth2_slashingprotection_prevented_signings"); - void setupSigner(final Path testDirectory) { setupSigner(testDirectory, true, true); } @@ -95,16 +85,24 @@ void canSignSameAttestationTwiceWhenSlashingIsEnabled( final Response initialResponse = signer.eth2Sign(keyPair.getPublicKey().toString(), request); assertThat(initialResponse.getStatusCode()).isEqualTo(200); - assertThat(signer.getMetricsMatching(attestationSlashingMetrics)) - .containsOnly( - attestationSlashingMetrics.get(0) + " 1.0", attestationSlashingMetrics.get(1) + " 0.0"); + assertThat(signer.getMetricsMatching(ETH2_SLASHINGPROTECTION_METRICS)) + .containsAllEntriesOf( + Map.of( + ETH_2_SLASHINGPROTECTION_PERMITTED_SIGNINGS, + "1.0", + ETH_2_SLASHINGPROTECTION_PREVENTED_SIGNINGS, + "0.0")); final Response secondResponse = signer.eth2Sign(keyPair.getPublicKey().toString(), request); assertThat(secondResponse.getStatusCode()).isEqualTo(200); - assertThat(signer.getMetricsMatching(attestationSlashingMetrics)) - .containsOnly( - attestationSlashingMetrics.get(0) + " 2.0", attestationSlashingMetrics.get(1) + " 0.0"); + assertThat(signer.getMetricsMatching(ETH2_SLASHINGPROTECTION_METRICS)) + .containsAllEntriesOf( + Map.of( + ETH_2_SLASHINGPROTECTION_PERMITTED_SIGNINGS, + "2.0", + ETH_2_SLASHINGPROTECTION_PREVENTED_SIGNINGS, + "0.0")); } @Test @@ -118,9 +116,13 @@ void cannotSignASecondAttestationForSameSlotWithDifferentSigningRoot( signer.eth2Sign(keyPair.getPublicKey().toString(), initialRequest); assertThat(initialResponse.getStatusCode()).isEqualTo(200); - assertThat(signer.getMetricsMatching(attestationSlashingMetrics)) - .containsOnly( - attestationSlashingMetrics.get(0) + " 1.0", attestationSlashingMetrics.get(1) + " 0.0"); + assertThat(signer.getMetricsMatching(ETH2_SLASHINGPROTECTION_METRICS)) + .containsAllEntriesOf( + Map.of( + ETH_2_SLASHINGPROTECTION_PERMITTED_SIGNINGS, + "1.0", + ETH_2_SLASHINGPROTECTION_PREVENTED_SIGNINGS, + "0.0")); final Eth2SigningRequestBody secondRequest = createAttestationRequest(5, 6, UInt64.ONE); @@ -128,9 +130,13 @@ void cannotSignASecondAttestationForSameSlotWithDifferentSigningRoot( signer.eth2Sign(keyPair.getPublicKey().toString(), secondRequest); assertThat(secondResponse.getStatusCode()).isEqualTo(SLASHING_PROTECTION_ENFORCED); - assertThat(signer.getMetricsMatching(attestationSlashingMetrics)) - .containsOnly( - attestationSlashingMetrics.get(0) + " 1.0", attestationSlashingMetrics.get(1) + " 1.0"); + assertThat(signer.getMetricsMatching(ETH2_SLASHINGPROTECTION_METRICS)) + .containsAllEntriesOf( + Map.of( + ETH_2_SLASHINGPROTECTION_PERMITTED_SIGNINGS, + "1.0", + ETH_2_SLASHINGPROTECTION_PREVENTED_SIGNINGS, + "1.0")); } @Test @@ -183,13 +189,23 @@ void canSignSameBlockTwiceWhenSlashingIsEnabled(@TempDir final Path testDirector final Response initialResponse = signer.eth2Sign(keyPair.getPublicKey().toString(), request); assertThat(initialResponse.getStatusCode()).isEqualTo(200); - assertThat(signer.getMetricsMatching(blockSlashingMetrics)) - .containsOnly(blockSlashingMetrics.get(0) + " 1.0", blockSlashingMetrics.get(1) + " 0.0"); + assertThat(signer.getMetricsMatching(ETH2_SLASHINGPROTECTION_METRICS)) + .containsAllEntriesOf( + Map.of( + ETH_2_SLASHINGPROTECTION_PERMITTED_SIGNINGS, + "1.0", + ETH_2_SLASHINGPROTECTION_PREVENTED_SIGNINGS, + "0.0")); final Response secondResponse = signer.eth2Sign(keyPair.getPublicKey().toString(), request); assertThat(secondResponse.getStatusCode()).isEqualTo(200); - assertThat(signer.getMetricsMatching(blockSlashingMetrics)) - .containsOnly(blockSlashingMetrics.get(0) + " 2.0", blockSlashingMetrics.get(1) + " 0.0"); + assertThat(signer.getMetricsMatching(ETH2_SLASHINGPROTECTION_METRICS)) + .containsAllEntriesOf( + Map.of( + ETH_2_SLASHINGPROTECTION_PERMITTED_SIGNINGS, + "2.0", + ETH_2_SLASHINGPROTECTION_PREVENTED_SIGNINGS, + "0.0")); } @Test @@ -206,8 +222,13 @@ void signingBlockWithDifferentSigningRootForPreviousSlotFailsWith412( final Response initialResponse = signer.eth2Sign(keyPair.getPublicKey().toString(), initialRequest); assertThat(initialResponse.getStatusCode()).isEqualTo(200); - assertThat(signer.getMetricsMatching(blockSlashingMetrics)) - .containsOnly(blockSlashingMetrics.get(0) + " 1.0", blockSlashingMetrics.get(1) + " 0.0"); + assertThat(signer.getMetricsMatching(ETH2_SLASHINGPROTECTION_METRICS)) + .containsAllEntriesOf( + Map.of( + ETH_2_SLASHINGPROTECTION_PERMITTED_SIGNINGS, + "1.0", + ETH_2_SLASHINGPROTECTION_PREVENTED_SIGNINGS, + "0.0")); final Eth2SigningRequestBody secondRequest = createBlockRequest( @@ -218,7 +239,12 @@ void signingBlockWithDifferentSigningRootForPreviousSlotFailsWith412( final Response secondResponse = signer.eth2Sign(keyPair.getPublicKey().toString(), secondRequest); assertThat(secondResponse.getStatusCode()).isEqualTo(SLASHING_PROTECTION_ENFORCED); - assertThat(signer.getMetricsMatching(blockSlashingMetrics)) - .containsOnly(blockSlashingMetrics.get(0) + " 1.0", blockSlashingMetrics.get(1) + " 1.0"); + assertThat(signer.getMetricsMatching(ETH2_SLASHINGPROTECTION_METRICS)) + .containsAllEntriesOf( + Map.of( + ETH_2_SLASHINGPROTECTION_PERMITTED_SIGNINGS, + "1.0", + ETH_2_SLASHINGPROTECTION_PREVENTED_SIGNINGS, + "1.0")); } } diff --git a/build.gradle b/build.gradle index 2cab8d8c7..103a725a4 100644 --- a/build.gradle +++ b/build.gradle @@ -21,28 +21,27 @@ import java.text.SimpleDateFormat buildscript { repositories { - mavenCentral() maven { url "https://artifacts.consensys.net/public/maven/maven/" } } dependencies { - classpath 'tech.pegasys.internal.license.reporter:license-reporter:1.0.1' - classpath 'org.owasp:dependency-check-gradle:10.0.2' + classpath 'tech.pegasys.internal.license.reporter:license-reporter:1.1.1' } } plugins { + id 'org.owasp.dependencycheck' version "10.0.3" id 'java-test-fixtures' - id 'com.diffplug.spotless' version '6.2.0' - id 'com.github.ben-manes.versions' version '0.27.0' - id 'com.github.jk1.dependency-license-report' version '2.0' - id 'io.spring.dependency-management' version '1.0.11.RELEASE' - id 'me.champeau.gradle.jmh' version '0.5.3' apply false - id 'net.ltgt.errorprone' version '2.0.2' - id 'org.ajoberstar.grgit' version '5.2.0' + id 'com.diffplug.spotless' version '7.0.0.BETA1' + id 'com.github.ben-manes.versions' version '0.51.0' //`./gradlew dependencyUpdates` to report outdated dependencies + id 'com.github.jk1.dependency-license-report' version '2.8' + id 'io.spring.dependency-management' version '1.1.6' + id 'me.champeau.jmh' version '0.7.2' apply false + id 'net.ltgt.errorprone' version '4.0.1' + id 'org.ajoberstar.grgit' version '5.2.2' } -if (!JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_17)) { - throw new GradleException("Java 17 or later is required to build Web3Signer.\n" + +if (!JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_21)) { + throw new GradleException("Java 21 or later is required to build Web3Signer.\n" + " Detected version ${JavaVersion.current()}") } @@ -97,20 +96,20 @@ allprojects { version = rootProject.version - jacoco { toolVersion = '0.8.7' } + jacoco { toolVersion = '0.8.11' } task sourcesJar(type: Jar, dependsOn: classes) { - classifier = 'sources' + archiveClassifier = 'sources' from sourceSets.main.allSource } task javadocJar(type: Jar, dependsOn: javadoc) { - classifier = 'javadoc' + archiveClassifier = 'javadoc' from javadoc.destinationDir } - sourceCompatibility = 17 - targetCompatibility = 17 + sourceCompatibility = 21 + targetCompatibility = 21 repositories { // mavenLocal() //for local testing only, uncomment while testing locally build signers. @@ -135,26 +134,15 @@ allprojects { include '**/*.java' exclude '**/.gradle/**' exclude '**/build/**' + exclude '.openapidoc/**' } - removeUnusedImports() // See gradle.properties for exports/opens flags required by JDK 16 and Google Java Format plugin - googleJavaFormat('1.10.0') + googleJavaFormat('1.22.0') importOrder 'tech.pegasys', 'java', '' trimTrailingWhitespace() endWithNewline() licenseHeaderFile "${rootDir}/gradle/spotless.java.license" } - groovyGradle { - target '*.gradle' - greclipse().configFile(rootProject.file('gradle/formatter.properties')) - endWithNewline() - } - - // Below this line are currently only license header tasks - format 'groovy', { - target '**/*.groovy' - licenseHeaderFile "${rootDir}/gradle/spotless.java.license", 'import' - } } dependencyCheck { @@ -264,7 +252,6 @@ allprojects { options.addStringOption('Xwerror', '-html5') options.encoding = 'UTF-8' } - } task deploy() {} @@ -474,7 +461,7 @@ tasks.register("dockerDistUntar") { } def dockerImage = "consensys/web3signer" -def dockerJdkVariants = ["jdk17",] +def dockerJdkVariants = ["jdk21",] def dockerBuildDir = "build/docker-web3signer/" task distDocker { @@ -607,8 +594,8 @@ task jacocoRootReport(type: org.gradle.testing.jacoco.tasks.JacocoReport) { classDirectories.from files(subprojects.sourceSets.main.output) executionData.from files(subprojects.jacocoTestReport.executionData) //how to exclude some package/classes com.test.** reports { - xml.enabled true - csv.enabled true + xml.required = true + csv.required = true html.destination file("build/reports/jacocoHtml") } onlyIf = { true } diff --git a/core/src/integrationTest/java/tech/pegasys/web3signer/core/jsonrpcproxy/IntegrationTestBase.java b/core/src/integrationTest/java/tech/pegasys/web3signer/core/jsonrpcproxy/IntegrationTestBase.java index a418d2e30..2bd1666dd 100644 --- a/core/src/integrationTest/java/tech/pegasys/web3signer/core/jsonrpcproxy/IntegrationTestBase.java +++ b/core/src/integrationTest/java/tech/pegasys/web3signer/core/jsonrpcproxy/IntegrationTestBase.java @@ -67,7 +67,6 @@ import io.restassured.response.Response; import io.restassured.specification.RequestSpecification; import io.vertx.core.Vertx; -import org.apache.http.params.CoreConnectionPNames; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.awaitility.Awaitility; @@ -264,8 +263,8 @@ void sendPostRequestAndVerifyResponse( RestAssured.config() .httpClient( HttpClientConfig.httpClientConfig() - .setParam(CoreConnectionPNames.CONNECTION_TIMEOUT, timeoutInMilliSec) - .setParam(CoreConnectionPNames.SO_TIMEOUT, timeoutInMilliSec)))); + .setParam("http.connection.timeout", timeoutInMilliSec) + .setParam("http.socket.timeout", timeoutInMilliSec)))); final Response response = requestSpec.post(path); diff --git a/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/LogErrorHandler.java b/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/LogErrorHandler.java index 128c54ea4..1130b7b9f 100644 --- a/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/LogErrorHandler.java +++ b/core/src/main/java/tech/pegasys/web3signer/core/service/http/handlers/LogErrorHandler.java @@ -12,6 +12,8 @@ */ package tech.pegasys.web3signer.core.service.http.handlers; +import java.util.Optional; + import io.vertx.core.Handler; import io.vertx.ext.web.RoutingContext; import org.apache.logging.log4j.LogManager; @@ -24,15 +26,23 @@ public class LogErrorHandler implements Handler { @Override public void handle(final RoutingContext failureContext) { - if (failureContext.failed()) { - LOG.error( - String.format("Failed request: %s", failureContext.request().absoluteURI()), - failureContext.failure()); + LOG.error("Failed request: {}", getRequestUri(failureContext), failureContext.failure()); + // Let the next matching route or error handler deal with the error, we only handle logging failureContext.next(); } else { LOG.warn("Error handler triggered without any propagated failure"); } } + + private static String getRequestUri(final RoutingContext failureContext) { + try { + return Optional.ofNullable(failureContext.request().absoluteURI()).orElse("[null uri]"); + } catch (final NullPointerException e) { + // absoluteURI() can throw NPE when header host is malformed. + LOG.warn("Vertx failed to calculate request URI due to malformed host header."); + return "[null uri]"; + } + } } diff --git a/core/src/main/java/tech/pegasys/web3signer/core/service/jsonrpc/RpcUtil.java b/core/src/main/java/tech/pegasys/web3signer/core/service/jsonrpc/RpcUtil.java index 2c2c9136c..32d5c524f 100644 --- a/core/src/main/java/tech/pegasys/web3signer/core/service/jsonrpc/RpcUtil.java +++ b/core/src/main/java/tech/pegasys/web3signer/core/service/jsonrpc/RpcUtil.java @@ -31,9 +31,7 @@ static T fromRpcRequestToJsonParam(final Class type, final JsonRpcRequest final Object object; final Object params = request.getParams(); - if (params instanceof List) { - @SuppressWarnings("unchecked") - final List paramList = (List) params; + if (params instanceof List paramList) { if (paramList.size() != 1) { throw new IllegalArgumentException( type.getSimpleName() diff --git a/core/src/main/java/tech/pegasys/web3signer/core/service/jsonrpc/handlers/internalresponse/EthSignTransactionResultProvider.java b/core/src/main/java/tech/pegasys/web3signer/core/service/jsonrpc/handlers/internalresponse/EthSignTransactionResultProvider.java index 180e1a8ae..2b4b0f700 100644 --- a/core/src/main/java/tech/pegasys/web3signer/core/service/jsonrpc/handlers/internalresponse/EthSignTransactionResultProvider.java +++ b/core/src/main/java/tech/pegasys/web3signer/core/service/jsonrpc/handlers/internalresponse/EthSignTransactionResultProvider.java @@ -90,9 +90,7 @@ public String createResponseResult(final JsonRpcRequest request) { public T fromRpcRequestToJsonParam(final Class type, final JsonRpcRequest request) { final Object object; final Object params = request.getParams(); - if (params instanceof List) { - @SuppressWarnings("unchecked") - final List paramList = (List) params; + if (params instanceof List paramList) { if (paramList.size() != 1) { throw new IllegalArgumentException( type.getSimpleName() diff --git a/core/src/main/java/tech/pegasys/web3signer/core/service/jsonrpc/handlers/sendtransaction/transaction/PrivateTransaction.java b/core/src/main/java/tech/pegasys/web3signer/core/service/jsonrpc/handlers/sendtransaction/transaction/PrivateTransaction.java index aefc8abc0..0bf05625b 100644 --- a/core/src/main/java/tech/pegasys/web3signer/core/service/jsonrpc/handlers/sendtransaction/transaction/PrivateTransaction.java +++ b/core/src/main/java/tech/pegasys/web3signer/core/service/jsonrpc/handlers/sendtransaction/transaction/PrivateTransaction.java @@ -23,7 +23,6 @@ import com.google.common.base.MoreObjects; import org.jetbrains.annotations.NotNull; import org.web3j.crypto.Sign.SignatureData; -import org.web3j.protocol.eea.crypto.PrivateTransactionEncoder; import org.web3j.protocol.eea.crypto.RawPrivateTransaction; import org.web3j.rlp.RlpEncoder; import org.web3j.rlp.RlpList; @@ -60,8 +59,7 @@ public void updateFieldsIfRequired() { @Override public byte[] rlpEncode(final SignatureData signatureData) { final RawPrivateTransaction rawTransaction = createTransaction(); - final List values = - PrivateTransactionEncoder.asRlpValues(rawTransaction, signatureData); + final List values = rawTransaction.getPrivateTransaction().asRlpValues(signatureData); final RlpList rlpList = new RlpList(values); return RlpEncoder.encode(rlpList); } diff --git a/core/src/main/java/tech/pegasys/web3signer/core/service/jsonrpc/handlers/sendtransaction/transaction/TransactionFactory.java b/core/src/main/java/tech/pegasys/web3signer/core/service/jsonrpc/handlers/sendtransaction/transaction/TransactionFactory.java index 7c8298d6d..603990d94 100644 --- a/core/src/main/java/tech/pegasys/web3signer/core/service/jsonrpc/handlers/sendtransaction/transaction/TransactionFactory.java +++ b/core/src/main/java/tech/pegasys/web3signer/core/service/jsonrpc/handlers/sendtransaction/transaction/TransactionFactory.java @@ -102,12 +102,9 @@ private Transaction createEeaTransaction( } public T fromRpcRequestToJsonParam(final Class type, final JsonRpcRequest request) { - final Object object; final Object params = request.getParams(); - if (params instanceof List) { - @SuppressWarnings("unchecked") - final List paramList = (List) params; + if (params instanceof List paramList) { if (paramList.size() != 1) { throw new IllegalArgumentException( type.getSimpleName() diff --git a/core/src/main/java/tech/pegasys/web3signer/core/util/OpenApiSpecsExtractor.java b/core/src/main/java/tech/pegasys/web3signer/core/util/OpenApiSpecsExtractor.java index 148fcf5cc..9828665fa 100644 --- a/core/src/main/java/tech/pegasys/web3signer/core/util/OpenApiSpecsExtractor.java +++ b/core/src/main/java/tech/pegasys/web3signer/core/util/OpenApiSpecsExtractor.java @@ -108,8 +108,7 @@ private void fixRelativePathInOpenApiMap(final Path yamlFile, final Map modifyRefValue(yamlFile, discriminatorMapEntry)); } - } else if (value instanceof List) { - List listItems = (List) value; + } else if (value instanceof List listItems) { for (Object listItem : listItems) { if (listItem instanceof Map) { fixRelativePathInOpenApiMap(yamlFile, (Map) listItem); diff --git a/docker/jdk17/Dockerfile b/docker/jdk21/Dockerfile similarity index 97% rename from docker/jdk17/Dockerfile rename to docker/jdk21/Dockerfile index 54d44551d..34185a7b0 100644 --- a/docker/jdk17/Dockerfile +++ b/docker/jdk21/Dockerfile @@ -1,4 +1,4 @@ -FROM eclipse-temurin:17 as jre-build +FROM eclipse-temurin:21 as jre-build # Create a custom Java runtime RUN JAVA_TOOL_OPTIONS="-Djdk.lang.Process.launchMechanism=vfork" $JAVA_HOME/bin/jlink \ diff --git a/gradle.properties b/gradle.properties index 1d51d7505..f386909e8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -besuVersion=24.5.2 +besuVersion=24.7.0 besuDistroUrl=https://github.com/hyperledger/besu/releases/download/${besuVersion}/besu-${besuVersion}.tar.gz hashicorpVaultVersion=1.9.2 diff --git a/gradle/license-report-config/allowed-licenses.json b/gradle/license-report-config/allowed-licenses.json index d8ed1a4d6..a9c8f292c 100644 --- a/gradle/license-report-config/allowed-licenses.json +++ b/gradle/license-report-config/allowed-licenses.json @@ -178,6 +178,14 @@ { "moduleName": "com.google.errorprone:error_prone_annotations", "moduleLicense": "Apache License, Version 2.0" + }, + { + "moduleName": "com.google.auth:google-auth-library-credentials", + "moduleLicense": "Apache License, Version 2.0" + }, + { + "moduleName": "com.google.auth:google-auth-library-oauth2-http", + "moduleLicense": "Apache License, Version 2.0" } ] } diff --git a/gradle/owasp-suppression.xml b/gradle/owasp-suppression.xml index 95ccbab8c..e77466cdc 100644 --- a/gradle/owasp-suppression.xml +++ b/gradle/owasp-suppression.xml @@ -1,19 +1,58 @@ - + - ^pkg:maven/com\.azure/azure\-identity@1\.12\.[1-9]$ - CVE-2023-36415 + ^pkg:maven/com\.azure/azure-identity@.*$ + CVE-2023-36415 - + - ^pkg:maven/com\.azure/azure*@*.*$ + ^pkg:maven/com\.azure/(azure-core@.*|azure-core-http-netty@.*|azure-json@.*|azure-identity@.*)$ CVE-2023-36052 + + + ^pkg:maven/(com\.microsoft\.azure|com\.azure)/(azure-identity@.*|msal4j@.*|msal4j-persistence-extension@.*)$ + CVE-2024-35255 + + + + ^pkg:maven/com\.google\.guava/guava@.*$ + CVE-2023-2976 + + + + ^pkg:maven/com\.google\.guava/guava@.*$ + CVE-2020-8908 + diff --git a/gradle/versions.gradle b/gradle/versions.gradle index f6d84f4de..0885106cd 100644 --- a/gradle/versions.gradle +++ b/gradle/versions.gradle @@ -13,10 +13,10 @@ dependencyManagement { dependencies { - dependency 'com.fasterxml.jackson.core:jackson-databind:2.16.0' - dependency 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.16.0' + dependency 'com.fasterxml.jackson.core:jackson-databind:2.17.2' + dependency 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.17.2' - dependencySet(group: 'com.google.errorprone', version: '2.21.1') { + dependencySet(group: 'com.google.errorprone', version: '2.29.2') { entry 'error_prone_annotation' entry 'error_prone_check_api' entry 'error_prone_core' @@ -25,16 +25,16 @@ dependencyManagement { dependency 'tech.pegasys.tools.epchecks:errorprone-checks:1.1.1' - dependency 'com.google.guava:guava:33.1.0-jre' + dependency 'com.google.guava:guava:33.2.1-jre' dependency 'commons-cli:commons-cli:1.5.0' - dependency 'commons-io:commons-io:2.11.0' - dependency 'org.apache.commons:commons-lang3:3.12.0' - dependency 'commons-logging:commons-logging:1.3.1' + dependency 'commons-io:commons-io:2.16.1' + dependency 'org.apache.commons:commons-lang3:3.15.0' + dependency 'commons-logging:commons-logging:1.3.3' - dependency 'info.picocli:picocli:4.6.2' + dependency 'info.picocli:picocli:4.7.6' - dependencySet(group: 'io.vertx', version: '4.5.7') { + dependencySet(group: 'io.vertx', version: '4.5.9') { entry 'vertx-codegen' entry ('vertx-core') { exclude group: 'io.netty', name: 'netty-handler' @@ -48,7 +48,7 @@ dependencyManagement { dependency 'javax.activation:activation:1.1.1' - dependencySet(group: 'org.apache.logging.log4j', version: '2.20.0') { + dependencySet(group: 'org.apache.logging.log4j', version: '2.23.1') { entry 'log4j-api' entry 'log4j' entry 'log4j-core' @@ -63,35 +63,36 @@ dependencyManagement { entry 'tuweni-io' } - dependency 'org.assertj:assertj-core:3.22.0' + dependency 'org.assertj:assertj-core:3.26.3' - dependency 'org.awaitility:awaitility:4.1.1' + dependency 'org.awaitility:awaitility:4.2.1' - dependencySet(group: 'org.bouncycastle', version: '1.78') { + dependencySet(group: 'org.bouncycastle', version: '1.78.1') { entry 'bcpkix-jdk18on' entry 'bcprov-jdk18on' } - dependencySet(group: 'org.junit.jupiter', version: '5.8.2') { + dependencySet(group: 'org.junit.jupiter', version: '5.10.3') { entry 'junit-jupiter-api' entry 'junit-jupiter-engine' entry 'junit-jupiter-params' } + dependency 'org.junit.vintage:junit-vintage-engine:5.10.3' dependency 'org.mock-server:mockserver-netty:5.15.0' - dependencySet(group: 'org.mockito', version: '4.2.0') { + dependencySet(group: 'org.mockito', version: '5.12.0') { entry 'mockito-core' entry 'mockito-inline' entry 'mockito-junit-jupiter' } - dependency 'org.hyperledger.besu:plugin-api:24.1.2' - dependency 'org.hyperledger.besu.internal:metrics-core:24.1.2' + dependency "org.hyperledger.besu:plugin-api:${besuVersion}" + dependency "org.hyperledger.besu.internal:metrics-core:${besuVersion}" dependency 'org.xipki.iaik:sunpkcs11-wrapper:1.4.10' - dependencySet(group: 'tech.pegasys.teku.internal', version: '24.4.0') { + dependencySet(group: 'tech.pegasys.teku.internal', version: '24.6.1') { entry ('bls') { exclude group: 'org.bouncycastle', name: 'bcprov-jdk15on' } @@ -109,11 +110,11 @@ dependencyManagement { entry 'jackson' } - dependency 'tech.pegasys:jblst:0.3.8' + dependency 'tech.pegasys:jblst:0.3.12' - dependency 'io.rest-assured:rest-assured:5.4.0' + dependency 'io.rest-assured:rest-assured:5.5.0' dependency 'org.zeroturnaround:zt-exec:1.12' - dependencySet(group: 'org.web3j', version: '4.10.2') { + dependencySet(group: 'org.web3j', version: '4.12.0') { entry 'besu' entry ('core') { exclude group: 'com.github.jnr', name: 'jnr-unixsocket' @@ -127,29 +128,30 @@ dependencyManagement { dependency 'com.github.arteam:simple-json-rpc-server:1.3' dependency 'com.github.arteam:simple-json-rpc-client:1.3' - dependency 'com.azure:azure-security-keyvault-secrets:4.8.3' - dependency 'com.azure:azure-security-keyvault-keys:4.8.4' - dependency 'com.azure:azure-identity:1.12.2' + dependency 'com.azure:azure-security-keyvault-secrets:4.8.4' + dependency 'com.azure:azure-security-keyvault-keys:4.8.5' + dependency 'com.azure:azure-identity:1.13.1' - dependency 'com.zaxxer:HikariCP:5.0.1' - dependency 'org.postgresql:postgresql:42.7.2' + dependency 'com.zaxxer:HikariCP:5.1.0' + dependency 'org.postgresql:postgresql:42.7.3' - dependencySet(group: 'org.jdbi', version: '3.36.0') { + dependencySet(group: 'org.jdbi', version: '3.45.2') { entry 'jdbi3-core' entry 'jdbi3-sqlobject' entry 'jdbi3-testing' } - dependency 'org.flywaydb:flyway-core:6.1.1' + dependency 'org.flywaydb:flyway-core:10.16.0' + dependency 'org.flywaydb:flyway-database-postgresql:10.16.0' - dependency 'com.google.cloud:google-cloud-secretmanager:2.45.0' - dependency 'io.zonky.test.postgres:embedded-postgres-binaries-bom:11.19.0' - dependency 'io.zonky.test:embedded-postgres:2.0.3' + dependency 'com.google.cloud:google-cloud-secretmanager:2.46.0' + dependency 'io.zonky.test.postgres:embedded-postgres-binaries-bom:11.22.1' + dependency 'io.zonky.test:embedded-postgres:2.0.7' dependency 'com.github.ipld:java-cid:1.3.3' dependency 'net.jodah:failsafe:2.4.4' - dependencySet(group: 'software.amazon.awssdk', version: '2.20.101') { + dependencySet(group: 'software.amazon.awssdk', version: '2.26.21') { entry 'bom' entry 'auth' entry 'secretsmanager' @@ -157,15 +159,15 @@ dependencyManagement { entry 'kms' } - dependency 'io.rest-assured:rest-assured:4.4.0' + dependency 'io.rest-assured:rest-assured:5.5.0' /* com.squareup.okhttp3:logging-interceptor:4.9.0 // CVE-2021-0341 \--- org.web3j:core:4.9.2 */ - dependency 'com.squareup.okhttp3:logging-interceptor:4.11.0' + dependency 'com.squareup.okhttp3:logging-interceptor:4.12.0' - dependencySet(group: 'com.squareup.okhttp3', version: '4.11.0') { + dependencySet(group: 'com.squareup.okhttp3', version: '4.12.0') { entry 'okhttp' entry 'mockwebserver' } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 943f0cbfa..e6441136f 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index c7d437bbb..09523c0e5 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 65dcd68d6..b740cf133 100755 --- a/gradlew +++ b/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -83,10 +83,8 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -133,10 +131,13 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. @@ -144,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -152,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -197,11 +198,15 @@ if "$cygwin" || "$msys" ; then done fi -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/gradlew.bat b/gradlew.bat index 6689b85be..7101f8e46 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -43,11 +43,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/keystorage/src/test/java/tech/pegasys/web3signer/keystorage/hashicorp/HashicorpConnectionTest.java b/keystorage/src/test/java/tech/pegasys/web3signer/keystorage/hashicorp/HashicorpConnectionTest.java index 18c68aea2..75e71a0fe 100644 --- a/keystorage/src/test/java/tech/pegasys/web3signer/keystorage/hashicorp/HashicorpConnectionTest.java +++ b/keystorage/src/test/java/tech/pegasys/web3signer/keystorage/hashicorp/HashicorpConnectionTest.java @@ -50,7 +50,7 @@ void missingJksTrustStoreFileThrowsHashicorpException() throws IOException { assertThatThrownBy(() -> connectionFactory.create(params)) .isInstanceOf(HashicorpException.class) .hasMessage("Unable to initialise connection to hashicorp vault.") - .getCause() + .cause() .isInstanceOf(EOFException.class); } @@ -74,7 +74,7 @@ void pkcs12FileWithIncorrectPasswordThrowsHashicorpException() { assertThatThrownBy(() -> connectionFactory.create(params)) .isInstanceOf(HashicorpException.class) .hasMessage("Unable to initialise connection to hashicorp vault.") - .getCause() + .cause() .isInstanceOf(IOException.class) .hasMessage("keystore password was incorrect"); } diff --git a/settings.gradle b/settings.gradle index 2673a5be9..5757ca867 100644 --- a/settings.gradle +++ b/settings.gradle @@ -21,3 +21,9 @@ include 'keystorage' include 'signing' include 'slashing-protection' include 'slashing-protection:referencetests' + +dependencyResolutionManagement { + repositories { + mavenCentral() + } +} diff --git a/signing/src/main/java/tech/pegasys/web3signer/signing/bulkloading/SecpV3KeystoresBulkLoader.java b/signing/src/main/java/tech/pegasys/web3signer/signing/bulkloading/SecpV3KeystoresBulkLoader.java index 0f3202fca..d9e998c55 100644 --- a/signing/src/main/java/tech/pegasys/web3signer/signing/bulkloading/SecpV3KeystoresBulkLoader.java +++ b/signing/src/main/java/tech/pegasys/web3signer/signing/bulkloading/SecpV3KeystoresBulkLoader.java @@ -27,9 +27,9 @@ import org.apache.commons.io.FilenameUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.web3j.crypto.CipherException; import org.web3j.crypto.Credentials; import org.web3j.crypto.WalletUtils; +import org.web3j.crypto.exception.CipherException; public class SecpV3KeystoresBulkLoader { private static final Logger LOG = LogManager.getLogger(); diff --git a/signing/src/main/java/tech/pegasys/web3signer/signing/config/metadata/Secp256k1ArtifactSignerFactory.java b/signing/src/main/java/tech/pegasys/web3signer/signing/config/metadata/Secp256k1ArtifactSignerFactory.java index a78394996..3de427e5f 100644 --- a/signing/src/main/java/tech/pegasys/web3signer/signing/config/metadata/Secp256k1ArtifactSignerFactory.java +++ b/signing/src/main/java/tech/pegasys/web3signer/signing/config/metadata/Secp256k1ArtifactSignerFactory.java @@ -30,9 +30,9 @@ import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; -import org.web3j.crypto.CipherException; import org.web3j.crypto.Credentials; import org.web3j.crypto.WalletUtils; +import org.web3j.crypto.exception.CipherException; public class Secp256k1ArtifactSignerFactory extends AbstractArtifactSignerFactory { diff --git a/signing/src/main/java/tech/pegasys/web3signer/signing/secp256k1/filebased/FileBasedSignerFactory.java b/signing/src/main/java/tech/pegasys/web3signer/signing/secp256k1/filebased/FileBasedSignerFactory.java index 9d3f88b5d..a02cff238 100644 --- a/signing/src/main/java/tech/pegasys/web3signer/signing/secp256k1/filebased/FileBasedSignerFactory.java +++ b/signing/src/main/java/tech/pegasys/web3signer/signing/secp256k1/filebased/FileBasedSignerFactory.java @@ -23,9 +23,9 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.web3j.crypto.CipherException; import org.web3j.crypto.Credentials; import org.web3j.crypto.WalletUtils; +import org.web3j.crypto.exception.CipherException; public class FileBasedSignerFactory { diff --git a/signing/src/testFixtures/java/tech/pegasys/web3signer/BLSTestUtil.java b/signing/src/testFixtures/java/tech/pegasys/web3signer/BLSTestUtil.java index dd4fdba32..7cf89a418 100644 --- a/signing/src/testFixtures/java/tech/pegasys/web3signer/BLSTestUtil.java +++ b/signing/src/testFixtures/java/tech/pegasys/web3signer/BLSTestUtil.java @@ -28,6 +28,7 @@ public class BLSTestUtil { Bytes32.fromHexString("0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001"); static final BigInteger CURVE_ORDER_BI = CURVE_ORDER_BYTES.toUnsignedBigInteger(ByteOrder.BIG_ENDIAN); + /** * BLS Key Pair based on seed value. * diff --git a/slashing-protection/build.gradle b/slashing-protection/build.gradle index 2c3a9cd1e..876774796 100644 --- a/slashing-protection/build.gradle +++ b/slashing-protection/build.gradle @@ -48,7 +48,9 @@ dependencies { testImplementation (testFixtures(project(":signing"))) testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine' - testRuntimeOnly 'org.junit.vintage:junit-vintage-engine:5.7.0' + testRuntimeOnly 'org.junit.vintage:junit-vintage-engine' + + testImplementation 'org.flywaydb:flyway-database-postgresql' testFixturesImplementation 'com.fasterxml.jackson.core:jackson-databind' testFixturesImplementation 'io.zonky.test:embedded-postgres' @@ -59,11 +61,13 @@ dependencies { testFixturesImplementation 'org.jdbi:jdbi3-core' testFixturesImplementation 'org.junit.jupiter:junit-jupiter-api' testFixturesImplementation enforcedPlatform('io.zonky.test.postgres:embedded-postgres-binaries-bom') + testFixturesImplementation 'org.flywaydb:flyway-database-postgresql' integrationTestImplementation 'io.zonky.test:embedded-postgres' integrationTestImplementation 'org.assertj:assertj-core' integrationTestImplementation 'org.awaitility:awaitility' integrationTestImplementation 'org.flywaydb:flyway-core' + integrationTestImplementation 'org.flywaydb:flyway-database-postgresql' integrationTestImplementation 'org.junit.jupiter:junit-jupiter-api' integrationTestImplementation 'org.junit.jupiter:junit-jupiter-params' integrationTestImplementation 'org.mockito:mockito-junit-jupiter' diff --git a/slashing-protection/src/main/java/tech/pegasys/web3signer/slashingprotection/DbLocker.java b/slashing-protection/src/main/java/tech/pegasys/web3signer/slashingprotection/DbLocker.java index 594289415..2d5c8f1ed 100644 --- a/slashing-protection/src/main/java/tech/pegasys/web3signer/slashingprotection/DbLocker.java +++ b/slashing-protection/src/main/java/tech/pegasys/web3signer/slashingprotection/DbLocker.java @@ -17,13 +17,23 @@ public class DbLocker { public enum LockType { - BLOCK, - ATTESTATION + BLOCK(0), + ATTESTATION(1); + + private final int lockOrdinal; + + LockType(final int lockOrdinal) { + this.lockOrdinal = lockOrdinal; + } + + public int lockOrdinal() { + return lockOrdinal; + } } public static void lockForValidator( final Handle handle, final LockType lockType, final int validatorId) { - handle.execute("SELECT pg_advisory_xact_lock(?, ?)", lockType.ordinal(), validatorId); + handle.execute("SELECT pg_advisory_xact_lock(?, ?)", lockType.lockOrdinal(), validatorId); } public static void lockAllForValidator(final Handle handle, final int validatorId) {