diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e709d8c1c..ccf22402e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -28,35 +28,35 @@ jobs: timeout-minutes: 30 runs-on: ubuntu-latest container: - image: tmio/tuweni-build:1.2 + image: consensys/tuweni-build:1.3 steps: - uses: actions/checkout@v4 with: submodules: true - name: Set up GPG key run: gpg --import gradle/tuweni-test.asc - - name: Set up JDK 17 - uses: actions/setup-java@v3 + - name: Set up JDK 21 + uses: actions/setup-java@v4 with: distribution: temurin - java-version: 17 + java-version: 21 cache: gradle - name: gradle assemble run: gradle assemble compileTestJava compileIntegrationTestJava -x test -Psignatory.keyId=90010D4396A46BAF -Psigning.gnupg.keyName=90010D4396A46BAF -Psigning.gnupg.executable=gpg env: ENABLE_SIGNING: true - name: Upload source distrib - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: distsrc path: dist/build/distributions/tuweni-src-*.zip - name: Upload binary distrib - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: snapshot.zip path: dist/build/distributions/tuweni-bin-*.zip - name: Cache classes - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: "**/*.class" key: ${{ runner.os }}-build-${{ github.sha }} @@ -65,19 +65,19 @@ jobs: runs-on: ubuntu-latest needs: assemble container: - image: tmio/tuweni-build:1.2 + image: consensys/tuweni-build:1.3 steps: - uses: actions/checkout@v4 with: submodules: true - - name: Set up JDK 17 - uses: actions/setup-java@v3 + - name: Set up JDK 21 + uses: actions/setup-java@v4 with: distribution: temurin - java-version: 17 + java-version: 21 cache: gradle - name: Cache classes - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: "**/*.class" key: ${{ runner.os }}-build-${{ github.sha }} @@ -85,7 +85,7 @@ jobs: run: gradle test - name: Archive Junit Report if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: junit-report path: '**/build/reports/tests/**' @@ -98,7 +98,7 @@ jobs: needs: assemble steps: - name: Download distsrc - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 id: download with: name: distsrc @@ -110,10 +110,10 @@ jobs: run: Expand-Archive -Force -Path tuweni-src-*.zip -DestinationPath distunzipped - name: Rename folder run: mv distunzipped/tuweni-src-* distunzipped/tuweni - - name: Set up JDK 17 - uses: actions/setup-java@v3 + - name: Set up JDK 21 + uses: actions/setup-java@v4 with: - java-version: 17 + java-version: 21 distribution: temurin cache: gradle - name: Build from source @@ -127,19 +127,19 @@ jobs: runs-on: ubuntu-latest needs: assemble container: - image: tmio/tuweni-build:1.2 + image: consensys/tuweni-build:1.3 steps: - uses: actions/checkout@v4 with: submodules: true - - name: Set up JDK 17 - uses: actions/setup-java@v3 + - name: Set up JDK 21 + uses: actions/setup-java@v4 with: distribution: temurin - java-version: 17 + java-version: 21 cache: gradle - name: Cache classes - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: "**/*.class" key: ${{ runner.os }}-build-${{ github.sha }} @@ -147,36 +147,8 @@ jobs: run: gradle compileJava compileKotlin compileIntegrationTestJava compileIntegrationTestKotlin devp2p:integrationTest dist:integrationTest - name: Archive Junit Report if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - name: junit-report - path: '**/build/reports/tests/**' - retention-days: 5 - referenceTests: - timeout-minutes: 30 - needs: assemble - runs-on: ubuntu-latest - container: - image: tmio/tuweni-build:1.2 - steps: - - uses: actions/checkout@v4 - with: - submodules: true - - name: Set up JDK 17 - uses: actions/setup-java@v3 - with: - distribution: temurin - java-version: 17 - cache: gradle - - name: Cache classes - uses: actions/cache@v3 - with: - path: "**/*.class" - key: ${{ runner.os }}-build-${{ github.sha }} - - name: Archive Junit Report - if: always() - uses: actions/upload-artifact@v3 - with: - name: junit-report + name: integration-junit-report path: '**/build/reports/tests/**' retention-days: 5 diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 4deba762e..64ab61ea1 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -28,14 +28,14 @@ jobs: timeout-minutes: 30 runs-on: ubuntu-latest container: - image: tmio/tuweni-build:1.2 + image: consensys/tuweni-build:1.3 steps: - uses: actions/checkout@v4 - - name: Set up JDK 17 - uses: actions/setup-java@v3 + - name: Set up JDK 21 + uses: actions/setup-java@v4 with: distribution: temurin - java-version: 17 + java-version: 21 cache: gradle - name: gradle spotlessCheck checkNotice - run: gradle spotlessCheck checkNotice \ No newline at end of file + run: gradle spotlessCheck checkNotice diff --git a/.github/workflows/close-stale.yml b/.github/workflows/close-stale.yml index e8bd53fb5..14ebfd444 100644 --- a/.github/workflows/close-stale.yml +++ b/.github/workflows/close-stale.yml @@ -24,7 +24,7 @@ jobs: stale: runs-on: ubuntu-latest steps: - - uses: actions/stale@v8 + - uses: actions/stale@v9 with: repo-token: ${{ secrets.GITHUB_TOKEN }} stale-pr-message: 'This PR was marked stale due to lack of activity. It will be closed in 14 days.' @@ -35,4 +35,4 @@ jobs: days-before-issue-stale: -1 # Stale label is applied by mark-issues-as-stale.yml days-before-pr-close: 14 days-before-issue-close: 60 - exempt-issue-labels: 'never stale' \ No newline at end of file + exempt-issue-labels: 'never stale' diff --git a/.github/workflows/docs.yml.disable b/.github/workflows/docs.yml.disable index f0763f3c5..d6ac3699a 100644 --- a/.github/workflows/docs.yml.disable +++ b/.github/workflows/docs.yml.disable @@ -30,19 +30,19 @@ jobs: timeout-minutes: 30 runs-on: ubuntu-latest container: - image: tmio/tuweni-build:1.2 + image: consensys/tuweni-build:1.3 steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v4 with: submodules: true - name: Cache Gradle packages - uses: actions/cache@v1 + uses: actions/cache@v4 with: path: ~/.gradle/caches key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} restore-keys: ${{ runner.os }}-gradle - name: Cache Maven Repository - uses: actions/cache@v1 + uses: actions/cache@v4 with: path: ~/.m2 key: ${{ runner.os }}-m2-${{ hashFiles('**/dependency-versions.gradle') }} @@ -50,7 +50,7 @@ jobs: - name: gradle docs run: gradle docs - name: Upload docs - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: Docs - path: "build/docs" \ No newline at end of file + path: "build/docs" diff --git a/.github/workflows/license-checks.yml b/.github/workflows/license-checks.yml index 6efbf0353..af415821d 100644 --- a/.github/workflows/license-checks.yml +++ b/.github/workflows/license-checks.yml @@ -26,10 +26,10 @@ jobs: timeout-minutes: 30 runs-on: ubuntu-latest container: - image: tmio/tuweni-build:1.2 + image: consensys/tuweni-build:1.3 steps: - uses: actions/checkout@v4 with: submodules: true - name: gradle checkLicense - run: gradle checkLicense \ No newline at end of file + run: gradle checkLicense diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 2bd90c09e..95fb19029 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -24,7 +24,7 @@ jobs: publish: runs-on: ubuntu-latest container: - image: tmio/tuweni-build:1.2 + image: consensys/tuweni-build:1.3 permissions: contents: read packages: write @@ -34,12 +34,12 @@ jobs: submodules: true - uses: actions/setup-java@v4 with: - java-version: '17' + java-version: '21' distribution: 'temurin' - name: Setup Gradle - uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 + uses: gradle/actions/setup-gradle@cc4fc85e6b35bafd578d5ffbc76a5518407e1af0 # v4.2.1 - name: Publish package run: ./gradlew publishAllPublicationsToGitHubPackagesRepository env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml index 39d2d41e6..0e2bbf9f2 100644 --- a/.github/workflows/test-windows.yml +++ b/.github/workflows/test-windows.yml @@ -33,18 +33,18 @@ jobs: - uses: actions/checkout@v4 with: submodules: true - - name: Set up JDK 17 - uses: actions/setup-java@v3 + - name: Set up JDK 21 + uses: actions/setup-java@v4 with: distribution: temurin - java-version: 17 + java-version: 21 cache: gradle - name: gradle test run: ./gradlew.bat test - name: Archive Junit Report if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: junit-report path: '**/build/reports/tests/**' - retention-days: 5 \ No newline at end of file + retention-days: 5 diff --git a/build.gradle b/build.gradle index f7c7bdaee..3acf5da5a 100644 --- a/build.gradle +++ b/build.gradle @@ -10,7 +10,10 @@ * 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 org.ajoberstar.grgit.Grgit +import net.ltgt.gradle.errorprone.CheckSeverity +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import groovy.xml.XmlParser import java.time.Instant import java.time.ZoneId import java.time.format.DateTimeFormatter @@ -19,20 +22,16 @@ buildscript { repositories { mavenCentral() } - - dependencies { - classpath "org.ajoberstar.grgit:grgit-core:5.2.1" - } } plugins { id 'com.diffplug.spotless' version '6.22.0' id 'net.ltgt.errorprone' version '3.1.0' - id 'org.springframework.boot' version '3.2.4' + id 'org.springframework.boot' version '3.4.0' id 'io.spring.dependency-management' version '1.1.3' id 'org.gradle.crypto.checksum' version '1.4.0' - id 'org.jetbrains.kotlin.jvm' version '1.9.23' - id 'org.jetbrains.kotlin.plugin.spring' version '1.9.23' + id 'org.jetbrains.kotlin.jvm' version '2.1.0' + id 'org.jetbrains.kotlin.plugin.spring' version '2.1.0' id 'org.jetbrains.dokka' version '1.9.20' id 'maven-publish' id 'se.patrikerdes.use-latest-versions' version '0.2.18' @@ -74,10 +73,10 @@ def expandedTaskList = [] gradle.startParameter.taskNames.each { expandedTaskList << (buildAliases[it] ? buildAliases[it] : it) } -gradle.startParameter.taskNames = expandedTaskList.flatten() +gradle.startParameter.taskNames = expandedTaskList.flatten() as Iterable ext { - gradleVersion = '7.6' + gradleVersion = '8.8' } apply from: "${rootDir}/gradle/wrapper.gradle" @@ -96,11 +95,10 @@ spotless { } } -task integrationTest(type: Test) { +tasks.register('integrationTest', Test) { } subprojects { - ////// // Source formatting @@ -142,14 +140,14 @@ subprojects { integrationTestRuntimeOnly 'ch.qos.logback:logback-classic' } - task integrationTest(type: Test) { + tasks.register('integrationTest', Test) { description = 'Runs integration tests.' group = 'verification' testClassesDirs = sourceSets.integrationTest.output.classesDirs classpath = sourceSets.integrationTest.runtimeClasspath - useJUnitPlatform() { includeEngines 'spek', 'junit-jupiter' } + useJUnitPlatform() { 'junit-jupiter' } timeout = Duration.ofMinutes(30) } @@ -159,24 +157,23 @@ subprojects { ////// // Parallel build execution - tasks.withType(Test) { + tasks.withType(Test).configureEach { // If GRADLE_MAX_TEST_FORKS is not set, use half the available processors maxParallelForks = (System.getenv('GRADLE_MAX_TEST_FORKS') ?: - (Runtime.runtime.availableProcessors().intdiv(2) ?: 1)).toInteger() + (Runtime.runtime.availableProcessors().intdiv(2) ?: 1)).toInteger() } - tasks.withType(JavaCompile) { + tasks.withType(JavaCompile).configureEach { options.fork = true options.incremental = true options.encoding = 'UTF-8' } - task allDependencies(type: DependencyReportTask) {} + tasks.register('allDependencies', DependencyReportTask) {} } ////// // Project defaults - allprojects { apply plugin: 'java-library' apply plugin: 'kotlin' @@ -200,51 +197,47 @@ allprojects { repositories { mavenCentral() - maven { - url = 'https://hyperledger.jfrog.io/artifactory/besu-maven/' - } } - ////// // Compiler arguments - sourceCompatibility = '1.17' - targetCompatibility = '1.17' + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 dependencies { errorprone 'com.google.errorprone:error_prone_core' } - tasks.withType(AbstractArchiveTask) { + tasks.withType(AbstractArchiveTask).configureEach { preserveFileTimestamps = false reproducibleFileOrder = true } - tasks.withType(JavaCompile) { + tasks.withType(JavaCompile).configureEach { options.compilerArgs += [ - '-Xlint:unchecked', - '-Xlint:cast', - '-Xlint:rawtypes', - '-Xlint:overloads', - '-Xlint:divzero', - '-Xlint:finally', - '-Xlint:static', - '-Werror' + '-Xlint:unchecked', + '-Xlint:cast', + '-Xlint:rawtypes', + '-Xlint:overloads', + '-Xlint:divzero', + '-Xlint:finally', + '-Xlint:static', + '-Werror' ] options.errorprone { excludedPaths = '.*/generated-src/.*' - check('FutureReturnValueIgnored', net.ltgt.gradle.errorprone.CheckSeverity.OFF) - check('UnnecessaryParentheses', net.ltgt.gradle.errorprone.CheckSeverity.OFF) + check('FutureReturnValueIgnored', CheckSeverity.OFF) + check('UnnecessaryParentheses', CheckSeverity.OFF) disableWarningsInGeneratedCode = true } } - tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all { - kotlinOptions { - jvmTarget = "17" + tasks.withType(KotlinCompile).configureEach { + compilerOptions { + jvmTarget = JvmTarget.JVM_21 allWarningsAsErrors = true freeCompilerArgs = [ '-Xjsr305=strict', @@ -258,16 +251,16 @@ allprojects { // Use JUnit5 for testing test { - useJUnitPlatform() { includeEngines 'spek', 'junit-jupiter' } + useJUnitPlatform() { 'junit-jupiter' } timeout = Duration.ofMinutes(30) } jacocoTestReport { reports { - xml.enabled true - html.enabled true + xml.required.set(true) + html.required.set(true) } - getExecutionData().setFrom(fileTree(buildDir).include("/jacoco/*.exec")) + getExecutionData().setFrom(fileTree(rootProject.layout.buildDirectory).include("/jacoco/*.exec")) } @@ -275,19 +268,20 @@ allprojects { // Artifact locations jar { - destinationDirectory = file("${rootProject.buildDir}/libs") + destinationDirectory = rootProject.layout.buildDirectory.dir("libs") } - task sourcesJar(type: Jar, dependsOn: classes) { - destinationDirectory = file("${rootProject.buildDir}/src") - classifier = 'sources' + tasks.register('sourcesJar', Jar) { + dependsOn classes + destinationDirectory = rootProject.layout.buildDirectory.dir("src") + archiveClassifier.set('sources') from sourceSets.main.allSource } ////// // Packaging and deployment - tasks.withType(Jar) { + tasks.withType(Jar).configureEach { def moduleName = rootProject.name if (rootProject == project) { archiveBaseName = project.name @@ -297,8 +291,8 @@ allprojects { } manifest { attributes('Implementation-Title': archiveBaseName, - 'Implementation-Version': project.version, - 'Automatic-Module-Name': moduleName.replaceAll("-","_")) + 'Implementation-Version': project.version, + 'Automatic-Module-Name': moduleName.replaceAll("-", "_")) } from(rootProject.projectDir) { include 'DISCLAIMER' @@ -310,17 +304,17 @@ allprojects { if (project.name != 'dist') { - artifacts { + artifacts { archives sourcesJar archives jar } - signing { + signing { useGpgCmd() sign configurations.archives } - publishing { + publishing { repositories { maven { name = "OSSRH" @@ -336,7 +330,7 @@ allprojects { project.logger.info('Reading .m2/settings.xml') def serverId = (project.properties['distMgmtServerId'] ?: isRelease ? 'apache.releases.https' : 'apache.snapshots.https') - def m2SettingCreds = new XmlSlurper().parse(settingsXml).servers.server.find { server -> serverId.equals(server.id.text()) } + def m2SettingCreds = new XmlParser().parse(settingsXml).servers.server.find { server -> serverId == server.id.text() } if (m2SettingCreds) { project.logger.info('Found matching credentials from .m2/settings.xml') credentials { @@ -366,24 +360,17 @@ allprojects { } } } + publications { - MavenDeployment(MavenPublication) { publication -> + create("MavenDeployment", MavenPublication) { if (project != rootProject) { from components.java - artifact sourcesJar { classifier 'sources' } - } - groupId 'io.consensys.protocols' - artifactId 'tuweni-' + project.name - version project.version - - versionMapping { - usage('java-runtime'){ - fromResolutionResult() - } - usage('java-api'){ - fromResolutionResult() - } + artifact sourcesJar { archiveClassifier.set('sources') } } + + groupId = 'io.consensys.protocols' + artifactId = project == rootProject ? project.name : "${rootProject.name}-${project.name}" + version = project.version pom { name = project.name @@ -412,81 +399,65 @@ allprojects { system = "github" url = "https://www.github.com/consensys/tuweni/issues" } - } - - pom.withXml { - // use inline versions rather than pom dependency management - asNode().remove(asNode().dependencyManagement[0]) - if (asNode().dependencies[0]) { - asNode().remove(asNode().dependencies[0]) - } - - def dependenciesNode = asNode().appendNode('dependencies') - def addDependencyNode = { dep, optional, scope -> - def dependencyNode = dependenciesNode.appendNode('dependency') - if (dep instanceof ProjectDependency) { - dependencyNode.appendNode('groupId', 'io.consensys') - dependencyNode.appendNode('artifactId', rootProject.name + '-' + dep.name) - dependencyNode.appendNode('version', dep.version) - } else { - dependencyNode.appendNode('groupId', dep.group) - dependencyNode.appendNode('artifactId', dep.name) - if (dep.version != null) { - dependencyNode.appendNode('version', dep.version) - } else { - def version = dependencyManagement.managedVersions["$dep.group:$dep.name"] - dependencyNode.appendNode('version', version) + + withXml { + def root = asNode() + + // Remove dependencyManagement section if it exists + root.dependencyManagement.each { it.parent().remove(it) } + + def dependencies = root.dependencies[0] ?: root.appendNode('dependencies') + dependencies.children().clear() + + // Add implementation dependencies with versions from dependency management + configurations.implementation.allDependencies.each { dep -> + if (dep.name != 'unspecified') { + def node = dependencies.appendNode('dependency') + node.appendNode('groupId', dep instanceof ProjectDependency ? "io.consensys.protocols" : dep.group) + node.appendNode('artifactId', dep instanceof ProjectDependency ? "${rootProject.name}-${dep.name}" : dep.name) + + // Get version from dependency management if available + def version = dep.version ?: project.dependencyManagement.managedVersions["${dep.group}:${dep.name}"] + node.appendNode('version', version) } } - if (optional) { - dependencyNode.appendNode('optional', 'true') - } - if (scope != null) { - dependencyNode.appendNode('scope', scope) + + // Add compileOnly dependencies as optional without trying to resolve them + configurations.compileOnly.allDependencies.each { dep -> + if (dep.name != 'unspecified') { + def node = dependencies.appendNode('dependency') + node.appendNode('groupId', dep instanceof ProjectDependency ? "io.consensys.protocols" : dep.group) + node.appendNode('artifactId', dep instanceof ProjectDependency ? "${rootProject.name}-${dep.name}" : dep.name) + // Get version from dependency management if available + def version = dep.version ?: project.dependencyManagement.managedVersions["${dep.group}:${dep.name}"] + node.appendNode('version', version) + node.appendNode('optional', 'true') + } } - def ers = dep.excludeRules - if (!ers.empty) { - def exclusionsNode = dependencyNode.appendNode('exclusions') - ers.each { er -> - def exclusionNode = exclusionsNode.appendNode('exclusion') - exclusionNode.appendNode('groupId', er.group) - exclusionNode.appendNode('artifactId', er.module) + if (System.getenv('ENABLE_SIGNING') == 'true') { + def pomFile = file("${project.buildDir}/generated-pom.xml") + writeTo(pomFile) + def pomAscFile = signing.sign(pomFile).signatureFiles[0] + artifact(pomAscFile) { + classifier = null + extension = 'pom.asc' } } } - configurations.implementation.allDependencies.each { dep -> - addDependencyNode(dep, false, null) - } - configurations.compileOnly.allDependencies.each { dep -> - addDependencyNode(dep, true, null) - } - configurations.runtimeOnly.allDependencies.each { dep -> - addDependencyNode(dep, false, 'runtime') - } if (System.getenv('ENABLE_SIGNING') == 'true') { - def pomFile = file("${project.buildDir}/generated-pom.xml") - writeTo(pomFile) - def pomAscFile = signing.sign(pomFile).signatureFiles[0] - artifact(pomAscFile) { - classifier = null - extension = 'pom.asc' - } - } - } - - if (System.getenv('ENABLE_SIGNING') == 'true') { - // create the signed artifacts - tasks.signArchives.signatureFiles.each { - artifact(it) { - def matcher = it.file =~ /-(sources|javadoc)\.jar\.asc$/ - if (matcher.find()) { - classifier = matcher.group(1) - } else { - classifier = null + // create the signed artifacts + tasks.signArchives.signatureFiles.each { + artifact(it) { + def matcher = it.file =~ /-(sources|javadoc)\.jar\.asc$/ + if (matcher.find()) { + classifier = matcher.group(1) + } else { + classifier = null + } + extension = 'jar.asc' } - extension = 'jar.asc' } } } @@ -494,26 +465,23 @@ allprojects { } } - tasks.withType(Sign) { + tasks.withType(Sign).configureEach { onlyIf { System.getenv('ENABLE_SIGNING') == 'true' } } - tasks.withType(GenerateModuleMetadata) { + tasks.withType(GenerateModuleMetadata).configureEach { enabled = false } - model { - tasks.generatePomFileForMavenDeploymentPublication { - destination = file("$buildDir/generated-pom.xml") - } - tasks.publishMavenDeploymentPublicationToMavenLocal { dependsOn project.tasks.signArchives } + // Ensure each project's publication task depends on its own POM generation + tasks.withType(PublishToMavenLocal).configureEach { publishTask -> + publishTask.dependsOn(tasks.withType(GenerateMavenPom)) } } } - ////// // Configure root project as a virtual package that depends on all components @@ -538,14 +506,14 @@ apply plugin: 'kotlin' apply plugin: 'org.jetbrains.dokka' tasks.dokkaHtmlMultiModule.configure { - outputDirectory.set(file("$rootProject.buildDir/docs")) + outputDirectory = rootProject.layout.buildDirectory.dir("docs") } tasks.register("docs") { dependsOn dokkaHtmlMultiModule } -dokkaHtml { +dokkaHtml.configure { moduleName = 'tuweni' dokkaSourceSets { @@ -573,7 +541,7 @@ dokkaHtml { } } -project.task("checkNotice") { +tasks.register('checkNotice') { def lines = file("NOTICE").readLines() def expected = "Copyright 2023-${LocalDate.now().getYear()} The Machine Consultancy LLC" for (line in lines) { diff --git a/bytes/build.gradle b/bytes/build.gradle index f3f093080..aa2d575c1 100644 --- a/bytes/build.gradle +++ b/bytes/build.gradle @@ -17,7 +17,7 @@ dependencies { implementation 'org.connid:framework-internal' compileOnly 'com.google.code.findbugs:jsr305' compileOnly 'com.google.errorprone:error_prone_annotations' - compileOnly 'io.vertx:vertx-core' + api 'io.vertx:vertx-core' testImplementation 'io.vertx:vertx-core' testImplementation 'org.junit.jupiter:junit-jupiter-api' diff --git a/dependency-versions.gradle b/dependency-versions.gradle index 94822d74a..0c9ae0475 100644 --- a/dependency-versions.gradle +++ b/dependency-versions.gradle @@ -15,135 +15,49 @@ dependencyManagement { dependency('ch.qos.logback:logback-classic:1.4.11') dependency('commons-codec:commons-codec:1.16.0') dependency('commons-net:commons-net:3.9.0') - dependency('com.fasterxml.jackson.core:jackson-databind:2.15.2') - dependency('com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.15.2') dependency('com.github.jnr:jnr-ffi:2.2.14') - dependency('com.github.codemonstur:embedded-redis:1.0.0') dependency('com.google.code.findbugs:jsr305:3.0.2') dependency('com.google.errorprone:error_prone_annotations:2.21.1') dependency('com.google.errorprone:error_prone_core:2.21.1') dependency('com.google.guava:guava:32.1.2-jre') - dependency('com.h2database:h2:2.2.220') - dependency('com.jolbox:bonecp:0.8.0.RELEASE') - dependency('com.netflix.concurrency-limits:concurrency-limits-core:0.4.0') - dependency('com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0') - dependency('com.opentable.components:otj-pg-embedded:1.0.1') dependency('com.squareup.okhttp3:okhttp:5.0.0-alpha.11') - dependency('com.winterbe:expekt:0.5.0') - dependency('com.zaxxer:HikariCP:5.0.1') - dependency('info.picocli:picocli:4.7.4') - dependency('io.grpc:grpc-netty-shaded:1.57.2') - dependency('net.java.dev.jna:jna:5.13.0') - dependency('org.hyperledger.besu:bls12-381:0.8.1') - dependency('org.hyperledger.besu:altbn128:0.8.1') - dependency('org.hyperledger.besu:secp256k1:0.4.3') - dependency('org.apache.httpcomponents.client5:httpclient5:5.3-alpha1') - dependency('org.springframework:spring-context:6.0.11') - dependency('org.springframework.boot:spring-boot:3.1.2') - dependency('org.springframework.boot:spring-boot-starter:3.1.2') - dependency('org.springframework.boot:spring-boot-starter-thymeleaf:3.1.2') - dependency('org.springframework.boot:spring-boot-starter-web:3.1.2') - dependency('org.springframework.boot:spring-boot-starter-webflux:3.1.2') - dependency('org.springframework.boot:spring-boot-starter-tomcat:3.1.2') - - dependency('io.opentelemetry:opentelemetry-api:1.29.0') - dependency('io.opentelemetry:opentelemetry-api-metrics:1.10.0-alpha-rc.1') - dependency('io.opentelemetry:opentelemetry-exporter-otlp-metrics:1.14.0') - dependency('io.opentelemetry:opentelemetry-exporter-otlp:1.29.0') - dependency('io.opentelemetry:opentelemetry-exporter-prometheus:1.29.0-alpha') - dependency('io.opentelemetry:opentelemetry-extension-trace-propagators:1.2.0') - dependency('io.opentelemetry:opentelemetry-proto:1.7.1-alpha') - dependency('io.opentelemetry:opentelemetry-sdk:1.29.0') - dependency('io.opentelemetry:opentelemetry-sdk-trace:1.29.0') - dependency('io.opentelemetry:opentelemetry-sdk-metrics:1.29.0') - dependency('io.opentelemetry:opentelemetry-sdk-testing:1.29.0') - - dependency('io.opentelemetry:opentelemetry-semconv:1.29.0-alpha') - dependency('io.prometheus:simpleclient:0.16.0') - dependency('io.prometheus:simpleclient_httpserver:0.16.0') - dependency('redis.clients:jedis:5.0.0-beta2') - dependency('io.swagger.core.v3:swagger-jaxrs2-jakarta:2.2.15') - dependency('org.webjars:swagger-ui:5.4.2') - - dependencySet(group: 'io.vertx', version: '4.4.4') { + dependencySet(group: 'io.vertx', version: '4.5.11') { entry 'vertx-core' - entry 'vertx-lang-kotlin' entry 'vertx-lang-kotlin-coroutines' - entry 'vertx-opentelemetry' - entry 'vertx-web' - entry 'vertx-web-client' } - dependency('jakarta.servlet:jakarta.servlet-api:6.0.0') - dependency('jakarta.annotation:jakarta.annotation-api:2.1.1') - dependency('javax.persistence:javax.persistence-api:2.2') dependencySet(group: 'org.antlr', version: '4.13.0') { entry 'antlr4' entry 'antlr4-runtime' } - dependency('javax.ws.rs:javax.ws.rs-api:2.1.1') dependency('org.apache.lucene:lucene-core:9.7.0') - dependency('org.apache.openjpa:openjpa:3.2.2') dependency('org.assertj:assertj-core:3.24.2') dependencySet(group: 'org.bouncycastle', version: '1.70') { entry 'bcpkix-jdk15on' entry 'bcprov-jdk15on' } - dependencySet(group: 'org.eclipse.jetty', version: '11.0.15') { - entry 'jetty-server' - entry 'jetty-servlet' - entry 'jetty-servlets' - entry 'jetty-util' - } - dependencySet(group: 'org.glassfish.jersey.core', version: '3.1.3') { - entry 'jersey-server' - entry 'jersey-client' - } - dependency('org.glassfish.jersey.containers:jersey-container-servlet:3.1.3') - dependency('org.glassfish.jersey.inject:jersey-hk2:3.1.3') - dependency('org.glassfish.jersey.media:jersey-media-json-jackson:3.0.5') - dependency('javax.xml.bind:jaxb-api:2.4.0-b180830.0359') - dependency('org.flywaydb:flyway-core:9.21.1') - dependency('org.openlabtesting.leveldbjni:leveldbjni-all:1.8') - dependencySet(group: 'org.junit.jupiter', version: '5.10.0') { + dependencySet(group: 'org.junit.jupiter', version: '5.11.3') { entry 'junit-jupiter-api' entry 'junit-jupiter-engine' entry 'junit-jupiter-params' entry 'junit-jupiter-migrationsupport' } - dependency('org.infinispan:infinispan-core:15.0.0.Dev02') - dependency('org.infinispan:infinispan-cachestore-rocksdb:15.0.0.Dev02') - - dependency('org.jetbrains:annotations:23.1.0') - dependencySet(group: 'org.jetbrains.kotlin', version: '1.9.0-Beta') { + dependency('org.jetbrains:annotations:26.0.1') + dependencySet(group: 'org.jetbrains.kotlin', version: '2.1.0') { entry 'kotlin-reflect' entry 'kotlin-stdlib' - entry 'kotlin-stdlib-jdk8' } - dependencySet(group: 'org.jetbrains.kotlinx', version: '1.7.3') { + dependencySet(group: 'org.jetbrains.kotlinx', version: '1.9.0') { entry 'kotlinx-coroutines-core' - entry 'kotlinx-coroutines-jdk8' - } - dependencySet(group: 'org.jetbrains.spek', version: '1.1.5') { - entry 'spek-api' - entry 'spek-junit-platform-engine' } - dependency('org.mapdb:mapdb:3.0.9') dependency('org.miracl.milagro.amcl:milagro-crypto-java:0.4.0') dependency('org.mockito:mockito-junit-jupiter:5.4.0') - dependency('org.postgresql:postgresql:42.6.0') - dependency('org.rocksdb:rocksdbjni:8.3.2') dependency('org.slf4j:slf4j-api:2.0.7') dependency('org.connid:framework:1.3.2') dependency('org.connid:framework-internal:1.3.2') - - dependency('org.webjars:bootstrap:5.3.1') - dependency('org.webjars:webjars-locator:0.47') - - dependency('org.xerial.snappy:snappy-java:1.1.10.3') } } diff --git a/devp2p/build.gradle b/devp2p/build.gradle index 9e9b4d2d4..49d9157ee 100644 --- a/devp2p/build.gradle +++ b/devp2p/build.gradle @@ -26,7 +26,6 @@ dependencies { implementation 'com.google.guava:guava' implementation 'io.vertx:vertx-core' implementation 'io.vertx:vertx-lang-kotlin-coroutines' - implementation 'io.vertx:vertx-lang-kotlin' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core' implementation 'org.slf4j:slf4j-api' implementation 'org.jetbrains.kotlin:kotlin-stdlib' @@ -48,7 +47,7 @@ application { applicationName = 'scraper' } -task v4ScraperApp(type: CreateStartScripts) { +tasks.register('v4ScraperApp', CreateStartScripts) { mainClass = "org.apache.tuweni.devp2p.ScraperApp" applicationName = "v4scraper" diff --git a/devp2p/src/integrationTest/java/org/apache/tuweni/devp2p/DiscoveryServiceJavaTest.java b/devp2p/src/integrationTest/java/org/apache/tuweni/devp2p/DiscoveryServiceJavaTest.java index b845dc1bd..c7edaf1fd 100644 --- a/devp2p/src/integrationTest/java/org/apache/tuweni/devp2p/DiscoveryServiceJavaTest.java +++ b/devp2p/src/integrationTest/java/org/apache/tuweni/devp2p/DiscoveryServiceJavaTest.java @@ -16,6 +16,7 @@ import java.net.URI; import java.util.Collections; import java.util.List; +import java.util.Objects; import io.vertx.core.Vertx; import org.junit.jupiter.api.Test; @@ -66,11 +67,11 @@ void managePeerRepository(@VertxInstance Vertx vertx) throws Exception { AsyncResult result = repository.getAsync( URI.create("enode://" + peerKeyPair.publicKey().toHexString() + "@127.0.0.1:10000")); - assertEquals(peerKeyPair.publicKey(), result.get().getNodeId()); + assertEquals(peerKeyPair.publicKey(), Objects.requireNonNull(result.get()).getNodeId()); AsyncResult byURIString = repository.getAsync( "enode://" + peerKeyPair.publicKey().toHexString() + "@127.0.0.1:10000"); - assertEquals(peerKeyPair.publicKey(), byURIString.get().getNodeId()); + assertEquals(peerKeyPair.publicKey(), Objects.requireNonNull(byURIString.get()).getNodeId()); service.shutdownAsync().join(); } } diff --git a/devp2p/src/integrationTest/kotlin/org/apache/tuweni/devp2p/v5/ConnectTwoServersTest.kt b/devp2p/src/integrationTest/kotlin/org/apache/tuweni/devp2p/v5/ConnectTwoServersTest.kt index 7a44654ab..5df4eb591 100644 --- a/devp2p/src/integrationTest/kotlin/org/apache/tuweni/devp2p/v5/ConnectTwoServersTest.kt +++ b/devp2p/src/integrationTest/kotlin/org/apache/tuweni/devp2p/v5/ConnectTwoServersTest.kt @@ -25,7 +25,9 @@ internal class SimpleTestENRStorage : ENRStorage { override fun find(nodeId: Bytes): EthereumNodeRecord? = storage[nodeId] - override fun put(nodeId: Bytes, enr: EthereumNodeRecord) { storage.put(nodeId, enr) } + override fun put(nodeId: Bytes, enr: EthereumNodeRecord) { + storage[nodeId] = enr + } } @ExtendWith(BouncyCastleExtension::class, VertxExtension::class) diff --git a/devp2p/src/integrationTest/kotlin/org/apache/tuweni/devp2p/v5/MedallaTest.kt b/devp2p/src/integrationTest/kotlin/org/apache/tuweni/devp2p/v5/MedallaTest.kt index 1c2f12f78..ff60fbb1d 100644 --- a/devp2p/src/integrationTest/kotlin/org/apache/tuweni/devp2p/v5/MedallaTest.kt +++ b/devp2p/src/integrationTest/kotlin/org/apache/tuweni/devp2p/v5/MedallaTest.kt @@ -38,7 +38,7 @@ class MedallaTest { ) service.start().join() - kotlinx.coroutines.delay(10000) + delay(10000) (1..8).forEach { service.requestNodes(it) } diff --git a/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/DiscoveryService.kt b/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/DiscoveryService.kt index 0d2441ba2..a11dccfd0 100644 --- a/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/DiscoveryService.kt +++ b/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/DiscoveryService.kt @@ -8,7 +8,7 @@ import io.vertx.core.Vertx import io.vertx.core.buffer.Buffer import io.vertx.core.datagram.DatagramPacket import io.vertx.core.net.SocketAddress -import io.vertx.kotlin.coroutines.await +import io.vertx.kotlin.coroutines.coAwait import io.vertx.kotlin.coroutines.dispatcher import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.CoroutineExceptionHandler @@ -271,7 +271,7 @@ interface DiscoveryService { val unexpectedENRResponses: Long } -internal class CoroutineDiscoveryService constructor( +internal class CoroutineDiscoveryService( vertx: Vertx, private val keyPair: SECP256K1.KeyPair, private val seq: Long = Instant.now().toEpochMilli(), @@ -334,8 +334,8 @@ internal class CoroutineDiscoveryService constructor( start() } - fun start() = launch { - server.handler { receiveDatagram(it) }.listen(bindAddress.port(), bindAddress.host()).await() + private fun start() = launch { + server.handler { receiveDatagram(it) }.listen(bindAddress.port(), bindAddress.host()).coAwait() val endpoint = Endpoint( advertiseAddress ?: (server.localAddress()).host(), advertiseUdpPort ?: server.localAddress().port(), @@ -428,7 +428,7 @@ internal class CoroutineDiscoveryService constructor( override suspend fun shutdown() { if (shutdown.compareAndSet(false, true)) { logger.info("{}: shutdown", serviceDescriptor) - server.close().await() + server.close().coAwait() for (pending in awaitingPongs.values) { pending.complete(null) } @@ -446,7 +446,7 @@ internal class CoroutineDiscoveryService constructor( override suspend fun lookup(target: SECP256K1.PublicKey): List { val targetId = target.bytesArray() val results = neighbors(target).toMutableList() - logger.debug("Initial neighbors query $results") + logger.debug("Initial neighbors query {}", results) // maybe add ourselves to the set val selfPeer = peerRepository.get(selfEndpoint!!.address, selfEndpoint!!.udpPort, nodeId) @@ -872,7 +872,7 @@ internal class CoroutineDiscoveryService constructor( private suspend fun send(request: FindNodeRequest) { try { val endpoint = peer.endpoint - var now = timeSupplier() + val now = timeSupplier() lastReceive = now val findNodePacket = FindNodePacket.create(keyPair, now, request.target) sendPacket(endpoint.udpSocketAddress, findNodePacket) @@ -881,7 +881,7 @@ internal class CoroutineDiscoveryService constructor( // issue a "get" on the state cache, to indicate that this state is still in use val state = findNodeStates.getIfPresent(peer.nodeId) if (state != this) { - logger.warn("{}: findNode state for {} has been replaced") + logger.warn("{}: findNode state for {} has been replaced", serviceDescriptor, state) close() } } catch (e: TimeoutCancellationException) { @@ -916,6 +916,6 @@ internal class CoroutineDiscoveryService constructor( } private suspend fun sendPacket(address: SocketAddress, packet: Packet) { - server.send(Buffer.buffer(packet.encode().toArrayUnsafe()), address.port(), address.host()).await() + server.send(Buffer.buffer(packet.encode().toArrayUnsafe()), address.port(), address.host()).coAwait() } } diff --git a/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/Endpoint.kt b/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/Endpoint.kt index 22681daaa..5db3d964d 100644 --- a/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/Endpoint.kt +++ b/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/Endpoint.kt @@ -7,16 +7,8 @@ import org.apache.tuweni.rlp.RLPException import org.apache.tuweni.rlp.RLPReader import org.apache.tuweni.rlp.RLPWriter import java.net.InetAddress -import java.net.InetSocketAddress import java.net.UnknownHostException -private fun parseInetAddress(address: String): InetAddress { - require(Character.digit(address[0], 16) != -1 || address[0] == ':') { - "address should be a literal IP address, got $address" - } - return InetAddress.getByName(address) -} - /** * An Ethereum node endpoint. * @@ -91,11 +83,6 @@ data class Endpoint( */ val udpSocketAddress: SocketAddress = SocketAddress.inetSocketAddress(udpPort, address) - /** - * TCP socket address of the endpoint, if set - */ - val tcpSocketAddress: InetSocketAddress? = if (tcpPort != null) InetSocketAddress(address, tcpPort) else null - /** * Write this endpoint to an RLP output. * diff --git a/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/EthereumNodeRecord.kt b/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/EthereumNodeRecord.kt index dd0c4e08a..5a1be77b8 100644 --- a/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/EthereumNodeRecord.kt +++ b/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/EthereumNodeRecord.kt @@ -264,9 +264,9 @@ class EthereumNodeRecord( * The ENR public key entry bytes * @return the ENR public key bytes */ - fun publicKeyBytes(): Bytes { + private fun publicKeyBytes(): Bytes { val keyBytes = data["secp256k1"] ?: throw InvalidNodeRecordException("Missing secp256k1 entry") - val ecPoint = SECP256K1.Parameters.CURVE.getCurve().decodePoint(keyBytes.toArrayUnsafe()) + val ecPoint = SECP256K1.Parameters.CURVE.curve.decodePoint(keyBytes.toArrayUnsafe()) return Bytes.wrap(ecPoint.getEncoded(false)).slice(1) } @@ -274,7 +274,7 @@ class EthereumNodeRecord( * Derives the public key of an ethereum node record into a unique 32 bytes hash. * @return the hash of the public key */ - fun nodeId() = EthereumNodeRecord.nodeId(publicKey()) + fun nodeId() = nodeId(publicKey()) /** * The ip associated with the ENR @@ -319,9 +319,7 @@ class EthereumNodeRecord( other as EthereumNodeRecord - if (rlp != other.rlp) return false - - return true + return rlp == other.rlp } override fun hashCode(): Int { diff --git a/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/Packet.kt b/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/Packet.kt index 63aa87c9c..40266dec5 100644 --- a/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/Packet.kt +++ b/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/Packet.kt @@ -134,11 +134,10 @@ internal class PingPacket private constructor( val from = reader.readList { r -> Endpoint.readFrom(r) } val to = reader.readList { r -> Endpoint.readFrom(r) } val expiration = reader.readLong() // seconds - val seq: Long? - if (!reader.isComplete) { - seq = reader.readLong() + val seq: Long? = if (!reader.isComplete) { + reader.readLong() } else { - seq = null + null } if (version < VERSION) { @@ -208,11 +207,10 @@ internal class PongPacket private constructor( val to = reader.readList { r -> Endpoint.readFrom(r) } val pingHash = Bytes32.wrap(reader.readValue()) val expiration = reader.readLong() // seconds - val seq: Long? - if (!reader.isComplete) { - seq = reader.readLong() + val seq: Long? = if (!reader.isComplete) { + reader.readLong() } else { - seq = null + null } PongPacket(publicKey, signature, hash, to, pingHash, secToMsec(expiration), seq) } @@ -403,7 +401,7 @@ internal class ENRRequestPacket private constructor( PacketType.ENRRESPONSE, keyPair, ) { writer -> - ENRRequestPacket.encodeTo(writer, expiration) + encodeTo(writer, expiration) } return ENRRequestPacket( keyPair.publicKey(), @@ -475,6 +473,6 @@ internal class ENRResponsePacket private constructor( } override fun encode() = encodeTo(PacketType.ENRRESPONSE) { writer -> - ENRResponsePacket.encodeTo(writer, requestHash, enr, expiration) + encodeTo(writer, requestHash, enr, expiration) } } diff --git a/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/PacketType.kt b/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/PacketType.kt index ff34ff764..cd1814c43 100644 --- a/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/PacketType.kt +++ b/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/PacketType.kt @@ -91,7 +91,7 @@ internal enum class PacketType( init { // populate an array by packet type id for index-based lookup in `forType(Byte)` - PacketType.values().forEach { type -> INDEX[type.typeId.toInt()] = type } + entries.forEach { type -> INDEX[type.typeId.toInt()] = type } } fun forType(typeId: Byte): PacketType? { @@ -100,7 +100,11 @@ internal enum class PacketType( } init { - require(typeId <= PacketType.MAX_VALUE) { "Packet typeId must be in range [0x00, 0x80)" } + checkTypeId() + } + + private fun checkTypeId() { + require(typeId <= PacketType.MAX_VALUE) { "Packet typeId must be in range [0x00, 0x80]" } } abstract fun decode( diff --git a/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/Peer.kt b/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/Peer.kt index e87d531a8..1c902f7cd 100644 --- a/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/Peer.kt +++ b/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/Peer.kt @@ -84,7 +84,7 @@ interface Peer { /** * Update the peer's ENR. * - * Will only update if the [seq] is larger than the one associated with the peer. + * Will only update if the `seq` is larger than the one associated with the peer. * * @param record the ENR record associated with the peer * @param time the time this endpoint information was determined, in milliseconds since the epoch diff --git a/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/Scraper.kt b/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/Scraper.kt index b5b85f7e2..aaa884f99 100644 --- a/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/Scraper.kt +++ b/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/Scraper.kt @@ -10,7 +10,6 @@ import kotlinx.coroutines.async import kotlinx.coroutines.delay import kotlinx.coroutines.runBlocking import org.apache.tuweni.concurrent.ExpiringSet -import org.apache.tuweni.concurrent.coroutines.await import org.apache.tuweni.crypto.SECP256K1 import org.bouncycastle.jce.provider.BouncyCastleProvider import java.net.URI @@ -30,7 +29,7 @@ object ScraperApp { run(args) } - fun run(args: Array) { + private fun run(args: Array) { val uris = args.map { URI.create(it) } val addr = SocketAddress.inetSocketAddress(11000, "0.0.0.0") val scraper = Scraper( @@ -66,7 +65,7 @@ class Scraper( val bindAddress: SocketAddress, val repository: PeerRepository, val listeners: List<(Peer) -> Unit>? = null, - val waitSecondsBetweenScrapes: Long = 30, + private val waitSecondsBetweenScrapes: Long = 30, ) : CoroutineScope { private var service: DiscoveryService? = null @@ -99,7 +98,7 @@ class Scraper( } } - fun discover() = async { + private fun discover() = async { for (node in nodes) { service?.lookupAsync(node.nodeId)?.thenAccept { for (newNode in it) { diff --git a/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/v5/DiscoveryV5Service.kt b/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/v5/DiscoveryV5Service.kt index ba48a1988..e21927208 100644 --- a/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/v5/DiscoveryV5Service.kt +++ b/devp2p/src/main/kotlin/org/apache/tuweni/devp2p/v5/DiscoveryV5Service.kt @@ -6,7 +6,7 @@ import io.vertx.core.Vertx import io.vertx.core.buffer.Buffer import io.vertx.core.datagram.DatagramPacket import io.vertx.core.net.SocketAddress -import io.vertx.kotlin.coroutines.await +import io.vertx.kotlin.coroutines.coAwait import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -151,7 +151,7 @@ interface DiscoveryV5Service : CoroutineScope { } internal class DefaultDiscoveryV5Service( - private val vertx: Vertx, + vertx: Vertx, private val bindAddress: InetSocketAddress, private val bootstrapENRList: List, private val enrStorage: ENRStorage, @@ -176,14 +176,14 @@ internal class DefaultDiscoveryV5Service( private lateinit var receiveJob: Job override suspend fun start(): AsyncCompletion { - server.handler(this::receiveDatagram).listen(bindAddress.port, bindAddress.hostString).await() + server.handler(this::receiveDatagram).listen(bindAddress.port, bindAddress.hostString).coAwait() return bootstrap() } override suspend fun terminate() { if (started.compareAndSet(true, false)) { receiveJob.cancel() - server.close().await() + server.close().coAwait() } } @@ -207,7 +207,7 @@ internal class DefaultDiscoveryV5Service( private fun send(addr: SocketAddress, message: Bytes) { launch { - server.send(Buffer.buffer(message.toArrayUnsafe()), addr.port(), addr.host()).await() + server.send(Buffer.buffer(message.toArrayUnsafe()), addr.port(), addr.host()).coAwait() } } @@ -224,10 +224,10 @@ internal class DefaultDiscoveryV5Service( ) private fun receiveDatagram(packet: DatagramPacket) { - var session = sessions.get(packet.sender()) - val size = Math.min(Packet.MAX_SIZE, packet.data().length()) + var session = sessions[packet.sender()] + val size = Packet.MAX_SIZE.coerceAtMost(packet.data().length()) val buffer = ByteBuffer.allocate(size) - packet.data().byteBuf.readBytes(buffer) + buffer.put(packet.data().bytes) buffer.flip() val message = Bytes.wrapByteBuffer(buffer) if (message.slice(0, 32) == whoAreYouHeader && session != null) { diff --git a/devp2p/src/test/kotlin/org/apache/tuweni/devp2p/DiscoveryServiceTest.kt b/devp2p/src/test/kotlin/org/apache/tuweni/devp2p/DiscoveryServiceTest.kt index 3ed757448..49bddcf93 100644 --- a/devp2p/src/test/kotlin/org/apache/tuweni/devp2p/DiscoveryServiceTest.kt +++ b/devp2p/src/test/kotlin/org/apache/tuweni/devp2p/DiscoveryServiceTest.kt @@ -5,7 +5,7 @@ package org.apache.tuweni.devp2p import io.vertx.core.Vertx import io.vertx.core.buffer.Buffer import io.vertx.core.net.SocketAddress -import io.vertx.kotlin.coroutines.await +import io.vertx.kotlin.coroutines.coAwait import kotlinx.coroutines.delay import kotlinx.coroutines.runBlocking import org.apache.tuweni.bytes.Bytes @@ -47,7 +47,7 @@ internal class DiscoveryServiceTest { } @Test - fun shouldRespondToPingAndRecordEndpoint(@VertxInstance vertx: Vertx) = runBlocking { + fun shouldRespondToPingAndRecordEndpoint(@VertxInstance vertx: Vertx): Unit = runBlocking { val peerRepository = EphemeralPeerRepository() val discoveryService = DiscoveryService.open( vertx, @@ -61,7 +61,7 @@ internal class DiscoveryServiceTest { val reference = AsyncResult.incomplete() val client = vertx.createDatagramSocket().handler { res -> reference.complete(res.data()) - }.listen(0, "localhost").await() + }.listen(0, "localhost").coAwait() val clientEndpoint = Endpoint("192.168.1.1", 5678, 7654) val ping = PingPacket.create( clientKeyPair, @@ -70,10 +70,10 @@ internal class DiscoveryServiceTest { Endpoint(address), null, ) - client.send(Buffer.buffer(ping.encode().toArrayUnsafe()), address.port(), address.host()).await() + client.send(Buffer.buffer(ping.encode().toArrayUnsafe()), address.port(), address.host()).coAwait() val datagram = reference.await() val buffer = ByteBuffer.allocate(datagram.length()) - datagram.byteBuf.readBytes(buffer) + buffer.put(datagram.bytes) val pong = Packet.decodeFrom(buffer) as PongPacket assertEquals(discoveryService.nodeId, pong.nodeId) assertEquals(ping.hash, pong.pingHash) @@ -86,13 +86,13 @@ internal class DiscoveryServiceTest { } @Test - fun shouldPingBootstrapNodeAndValidate(@VertxInstance vertx: Vertx) = runBlocking { + fun shouldPingBootstrapNodeAndValidate(@VertxInstance vertx: Vertx): Unit = runBlocking { val bootstrapKeyPair = SECP256K1.KeyPair.random() val reference = AtomicReference>() reference.set(AsyncResult.incomplete()) val bootstrapClient = vertx.createDatagramSocket().handler { res -> reference.get().complete(res.data()) - }.listen(0, "127.0.0.1").await() + }.listen(0, "127.0.0.1").coAwait() val serviceKeyPair = SECP256K1.KeyPair.random() val peerRepository = EphemeralPeerRepository() @@ -113,7 +113,7 @@ internal class DiscoveryServiceTest { val datagram = reference.get().await() val buffer = ByteBuffer.allocate(datagram.length()) - datagram.byteBuf.readBytes(buffer) + buffer.put(datagram.bytes) val ping = Packet.decodeFrom(buffer) as PingPacket assertEquals(discoveryService.nodeId, ping.nodeId) assertEquals( @@ -132,7 +132,7 @@ internal class DiscoveryServiceTest { ) reference.set(AsyncResult.incomplete()) val address = SocketAddress.inetSocketAddress(discoveryService.localPort, "127.0.0.1") - bootstrapClient.send(Buffer.buffer(pong.encode().toArrayUnsafe()), address.port(), address.host()).await() + bootstrapClient.send(Buffer.buffer(pong.encode().toArrayUnsafe()), address.port(), address.host()).coAwait() val findNodesDatagram = reference.get().await() @@ -158,13 +158,13 @@ internal class DiscoveryServiceTest { } @Test - fun shouldIgnoreBootstrapNodeRespondingWithDifferentNodeId(@VertxInstance vertx: Vertx) = runBlocking { + fun shouldIgnoreBootstrapNodeRespondingWithDifferentNodeId(@VertxInstance vertx: Vertx): Unit = runBlocking { println("foo") val bootstrapKeyPair = SECP256K1.KeyPair.random() val reference = AsyncResult.incomplete() val bootstrapClient = vertx.createDatagramSocket().handler { res -> reference.complete(res.data()) - }.listen(0, "localhost").await() + }.listen(0, "localhost").coAwait() val serviceKeyPair = SECP256K1.KeyPair.random() val peerRepository = EphemeralPeerRepository() @@ -184,7 +184,7 @@ internal class DiscoveryServiceTest { ) val datagram = reference.await() val buffer = ByteBuffer.allocate(datagram.length()) - datagram.byteBuf.readBytes(buffer) + buffer.put(datagram.bytes) val ping = Packet.decodeFrom(buffer) as PingPacket assertEquals(discoveryService.nodeId, ping.nodeId) assertEquals( @@ -202,7 +202,7 @@ internal class DiscoveryServiceTest { null, ) val address = SocketAddress.inetSocketAddress(discoveryService.localPort, "127.0.0.1") - bootstrapClient.send(Buffer.buffer(pong.encode().toArrayUnsafe()), address.port(), address.host()).await() + bootstrapClient.send(Buffer.buffer(pong.encode().toArrayUnsafe()), address.port(), address.host()).coAwait() delay(1000) val bootstrapPeer = @@ -220,12 +220,12 @@ internal class DiscoveryServiceTest { } @Test - fun shouldPingBootstrapNodeWithAdvertisedAddress(@VertxInstance vertx: Vertx) = runBlocking { + fun shouldPingBootstrapNodeWithAdvertisedAddress(@VertxInstance vertx: Vertx): Unit = runBlocking { val bootstrapKeyPair = SECP256K1.KeyPair.random() val reference = AsyncResult.incomplete() val bootstrapClient = vertx.createDatagramSocket().handler { res -> reference.complete(res.data()) - }.listen(0, "localhost").await() + }.listen(0, "localhost").coAwait() val discoveryService = DiscoveryService.open( vertx, @@ -244,7 +244,7 @@ internal class DiscoveryServiceTest { val datagram = reference.await() val buffer = ByteBuffer.allocate(datagram.length()) - datagram.byteBuf.readBytes(buffer) + buffer.put(datagram.bytes) val ping = Packet.decodeFrom(buffer) as PingPacket assertEquals(discoveryService.nodeId, ping.nodeId) assertEquals( @@ -258,13 +258,13 @@ internal class DiscoveryServiceTest { } @Test - fun shouldRetryPingsToBootstrapNodes(@VertxInstance vertx: Vertx) = runBlocking { + fun shouldRetryPingsToBootstrapNodes(@VertxInstance vertx: Vertx): Unit = runBlocking { val bootstrapKeyPair = SECP256K1.KeyPair.random() val reference = AtomicReference>() reference.set(AsyncResult.incomplete()) val bootstrapClient = vertx.createDatagramSocket().handler { res -> reference.get().complete(res.data()) - }.listen(0, "localhost").await() + }.listen(0, "localhost").coAwait() val discoveryService = DiscoveryService.open( vertx, @@ -280,7 +280,7 @@ internal class DiscoveryServiceTest { val datagram1 = reference.get().await() reference.set(AsyncResult.incomplete()) val buffer1 = ByteBuffer.allocate(datagram1.length()) - datagram1.byteBuf.readBytes(buffer1) + buffer1.put(datagram1.bytes) val ping1 = Packet.decodeFrom(buffer1) as PingPacket assertEquals(discoveryService.nodeId, ping1.nodeId) assertEquals( @@ -290,7 +290,7 @@ internal class DiscoveryServiceTest { val datagram2 = reference.get().await() reference.set(AsyncResult.incomplete()) val buffer2 = ByteBuffer.allocate(datagram2.length()) - datagram2.byteBuf.readBytes(buffer2) + buffer2.put(datagram2.bytes) val ping2 = Packet.decodeFrom(buffer2) as PingPacket assertEquals(discoveryService.nodeId, ping2.nodeId) assertEquals( @@ -300,7 +300,7 @@ internal class DiscoveryServiceTest { val datagram3 = reference.get().await() reference.set(AsyncResult.incomplete()) val buffer3 = ByteBuffer.allocate(datagram3.length()) - datagram3.byteBuf.readBytes(buffer3) + buffer3.put(datagram3.bytes) val ping3 = Packet.decodeFrom(buffer3) as PingPacket assertEquals(discoveryService.nodeId, ping3.nodeId) assertEquals( @@ -312,7 +312,7 @@ internal class DiscoveryServiceTest { } @Test - fun shouldRequirePingPongBeforeRespondingToFindNodesFromUnverifiedPeer(@VertxInstance vertx: Vertx) = runBlocking { + fun shouldRequirePingPongBeforeRespondingToFindNodesUnverifiedPeer(@VertxInstance vertx: Vertx): Unit = runBlocking { val peerRepository = EphemeralPeerRepository() val discoveryService = DiscoveryService.open( vertx, @@ -328,18 +328,18 @@ internal class DiscoveryServiceTest { reference.set(AsyncResult.incomplete()) val client = vertx.createDatagramSocket().handler { res -> reference.get().complete(res.data()) - }.listen(0, "localhost").await() + }.listen(0, "localhost").coAwait() val findNodes = FindNodePacket.create( clientKeyPair, System.currentTimeMillis(), SECP256K1.KeyPair.random().publicKey(), ) - client.send(Buffer.buffer(findNodes.encode().toArrayUnsafe()), address.port(), address.host()).await() + client.send(Buffer.buffer(findNodes.encode().toArrayUnsafe()), address.port(), address.host()).coAwait() val datagram = reference.get().await() val buffer = ByteBuffer.allocate(datagram.length()) - datagram.byteBuf.readBytes(buffer) + buffer.put(datagram.bytes) val ping = Packet.decodeFrom(buffer) as PingPacket assertEquals(discoveryService.nodeId, ping.nodeId) @@ -355,11 +355,11 @@ internal class DiscoveryServiceTest { ) reference.set(AsyncResult.incomplete()) - client.send(Buffer.buffer(pong.encode().toArrayUnsafe()), address.port(), address.host()).await() + client.send(Buffer.buffer(pong.encode().toArrayUnsafe()), address.port(), address.host()).coAwait() val datagram2 = reference.get().await() val buffer2 = ByteBuffer.allocate(datagram2.length()) - datagram2.byteBuf.readBytes(buffer2) + buffer2.put(datagram2.bytes) val neighbors = Packet.decodeFrom(buffer2) as NeighborsPacket assertEquals(discoveryService.nodeId, neighbors.nodeId) diff --git a/devp2p/src/test/kotlin/org/apache/tuweni/devp2p/EthereumNodeRecordTest.kt b/devp2p/src/test/kotlin/org/apache/tuweni/devp2p/EthereumNodeRecordTest.kt index 533ff86b6..1ab89a4dd 100644 --- a/devp2p/src/test/kotlin/org/apache/tuweni/devp2p/EthereumNodeRecordTest.kt +++ b/devp2p/src/test/kotlin/org/apache/tuweni/devp2p/EthereumNodeRecordTest.kt @@ -17,9 +17,9 @@ class EthereumNodeRecordTest { @Test fun tooLong() { val tooLong = Bytes.random(312) - val exception: IllegalArgumentException = assertThrows({ + val exception: IllegalArgumentException = assertThrows { EthereumNodeRecord.fromRLP(tooLong) - }) + } assertEquals("Record too long", exception.message) } diff --git a/devp2p/src/test/kotlin/org/apache/tuweni/devp2p/v5/DefaultDiscoveryV5ServiceTest.kt b/devp2p/src/test/kotlin/org/apache/tuweni/devp2p/v5/DefaultDiscoveryV5ServiceTest.kt index 28e17e8ed..59b1fe0a2 100644 --- a/devp2p/src/test/kotlin/org/apache/tuweni/devp2p/v5/DefaultDiscoveryV5ServiceTest.kt +++ b/devp2p/src/test/kotlin/org/apache/tuweni/devp2p/v5/DefaultDiscoveryV5ServiceTest.kt @@ -4,7 +4,7 @@ package org.apache.tuweni.devp2p.v5 import io.vertx.core.Vertx import io.vertx.core.buffer.Buffer -import io.vertx.kotlin.coroutines.await +import io.vertx.kotlin.coroutines.coAwait import kotlinx.coroutines.runBlocking import org.apache.tuweni.bytes.Bytes import org.apache.tuweni.concurrent.AsyncResult @@ -20,9 +20,7 @@ import org.junit.jupiter.api.Test import org.junit.jupiter.api.Timeout import org.junit.jupiter.api.extension.ExtendWith import java.net.InetAddress -import java.net.InetSocketAddress import java.nio.ByteBuffer -import java.time.Instant @Timeout(10) @ExtendWith(BouncyCastleExtension::class, VertxExtension::class) @@ -34,25 +32,14 @@ class DefaultDiscoveryV5ServiceTest { private val encodedEnr: String = "enr:${Base64URLSafe.encode(recipientEnr)}" private val keyPair: SECP256K1.KeyPair = SECP256K1.KeyPair.random() private val localPort: Int = 19000 - private val bindAddress: InetSocketAddress = InetSocketAddress("localhost", localPort) private val bootstrapENRList: List = listOf(encodedEnr) - private val enrSeq: Long = Instant.now().toEpochMilli() - private val selfENR: EthereumNodeRecord = EthereumNodeRecord.create( - keyPair, - enrSeq, - emptyMap(), - emptyMap(), - bindAddress.address, - null, - bindAddress.port, - ) @Test - fun startInitializesConnectorAndBootstraps(@VertxInstance vertx: Vertx) = runBlocking { + fun startInitializesConnectorAndBootstraps(@VertxInstance vertx: Vertx): Unit = runBlocking { val reference = AsyncResult.incomplete() val client = vertx.createDatagramSocket().handler { res -> reference.complete(res.data()) - }.listen(19001, "localhost").await() + }.listen(19001, "localhost").coAwait() val discoveryV5Service: DiscoveryV5Service = DiscoveryService.open( vertx, @@ -64,7 +51,7 @@ class DefaultDiscoveryV5ServiceTest { val datagram = reference.await() val buffer = ByteBuffer.allocate(datagram.length()) - datagram.byteBuf.readBytes(buffer) + buffer.put(datagram.bytes) buffer.flip() val receivedBytes = Bytes.wrapByteBuffer(buffer) val content = receivedBytes.slice(45) diff --git a/dist/build.gradle b/dist/build.gradle index 3674a8048..20017d037 100644 --- a/dist/build.gradle +++ b/dist/build.gradle @@ -109,7 +109,6 @@ distributions { } into('lib') { from rootProject.jar - from rootProject.signArchives.signatureFiles[0] } into('bin') { @@ -194,9 +193,17 @@ distTar { compression = Compression.GZIP } sourcesDistTar { compression = Compression.GZIP } +artifacts { + archives distZip + archives distTar + archives sourcesDistZip + archives sourcesDistTar +} + if (System.getenv('ENABLE_SIGNING') == 'true') { signing { useGpgCmd() + sign configurations.archives sign distZip sign distTar sign sourcesDistZip @@ -204,18 +211,18 @@ if (System.getenv('ENABLE_SIGNING') == 'true') { } } -task createChecksums(type: Checksum, dependsOn: [ - 'distZip', - 'distTar', - 'sourcesDistZip', - 'sourcesDistTar', -]) { +task createChecksums(type: Checksum) { + dependsOn tasks.withType(Sign), 'distZip', 'distTar', 'sourcesDistZip', 'sourcesDistTar' + files = distZip.outputs.files + distTar.outputs.files + sourcesDistZip.outputs.files + sourcesDistTar.outputs.files outputDir = new File(project.buildDir, "distributions") algorithm = Checksum.Algorithm.SHA512 } build.dependsOn('createChecksums') +if (System.getenv('ENABLE_SIGNING') == 'true') { + build.dependsOn tasks.withType(Sign) +} task buildBinImage(type: DockerBuildImage) { dependsOn distTar diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 2b22d057a..6f7a6eb33 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-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 798d4b390..340eb8243 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 @@ -118,7 +116,7 @@ esac # Loop in case we encounter an error. for attempt in 1 2 3; do if [ ! -e "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" ]; then - if ! curl -s -S --retry 3 -L -o "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" "https://raw.githubusercontent.com/gradle/gradle/v7.6.0/gradle/wrapper/gradle-wrapper.jar"; then + if ! curl -s -S --retry 3 -L -o "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" "https://raw.githubusercontent.com/gradle/gradle/v8.8.0/gradle/wrapper/gradle-wrapper.jar"; then rm -f "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" # Pause for a bit before looping in case the server throttled us. sleep 5 @@ -146,10 +144,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. @@ -157,7 +158,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 @@ -165,7 +166,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 @@ -210,11 +211,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 a556b295a..1d6ac2957 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 @@ -70,7 +70,7 @@ goto fail if not exist "%APP_HOME%/gradle/wrapper/gradle-wrapper.jar" ( - curl -q -o "%APP_HOME%/gradle/wrapper/gradle-wrapper.jar" "https://raw.githubusercontent.com/gradle/gradle/v7.6.0/gradle/wrapper/gradle-wrapper.jar" + curl -q -o "%APP_HOME%/gradle/wrapper/gradle-wrapper.jar" "https://raw.githubusercontent.com/gradle/gradle/v8.8.0/gradle/wrapper/gradle-wrapper.jar" ) set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar diff --git a/junit/build.gradle b/junit/build.gradle index e573e01ed..844ee1256 100644 --- a/junit/build.gradle +++ b/junit/build.gradle @@ -15,14 +15,11 @@ description = 'Utilities for better junit testing.' dependencies { implementation project(':crypto') implementation project(':io') - compileOnly 'com.github.codemonstur:embedded-redis' compileOnly 'io.vertx:vertx-core' compileOnly 'org.bouncycastle:bcprov-jdk15on' compileOnly 'org.junit.jupiter:junit-jupiter-api' compileOnly 'org.apache.lucene:lucene-core' - testImplementation 'com.github.codemonstur:embedded-redis' - testImplementation 'redis.clients:jedis' testImplementation 'io.vertx:vertx-core' testImplementation 'org.apache.lucene:lucene-core' testImplementation 'org.junit.jupiter:junit-jupiter-api'