diff --git a/applications/workers/release/combined-worker/src/main/kotlin/net/corda/applications/workers/combined/CombinedWorker.kt b/applications/workers/release/combined-worker/src/main/kotlin/net/corda/applications/workers/combined/CombinedWorker.kt index 59e1e1f235c..680ddb0d7ad 100644 --- a/applications/workers/release/combined-worker/src/main/kotlin/net/corda/applications/workers/combined/CombinedWorker.kt +++ b/applications/workers/release/combined-worker/src/main/kotlin/net/corda/applications/workers/combined/CombinedWorker.kt @@ -313,7 +313,7 @@ private class CombinedWorkerParams { @Option(names = ["--serviceEndpoint"], description = ["Internal REST endpoints for Corda workers"]) val workerEndpoints: Map = - listOf("crypto", "verification", "uniqueness", "persistence", "tokenSelection") + listOf("crypto", "verification", "uniqueness", "persistence", "tokenSelection", "p2pLinkManager") .associate { "endpoints.$it" to "localhost:7004" } .toMap() } diff --git a/applications/workers/release/crypto-worker/build.gradle b/applications/workers/release/crypto-worker/build.gradle index 550e154628d..cd9855df449 100644 --- a/applications/workers/release/crypto-worker/build.gradle +++ b/applications/workers/release/crypto-worker/build.gradle @@ -38,8 +38,6 @@ dependencies { testRuntimeOnly "org.apache.felix:org.apache.felix.framework:$felixVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" // This puts the jdbc driver into the docker image in the /opt/jdbc-driver folder // this folder can contain many jdbc drivers (and DataSourceFactory provider bundles). diff --git a/applications/workers/release/db-worker/build.gradle b/applications/workers/release/db-worker/build.gradle index 5b2477f22af..fb5a3266df8 100644 --- a/applications/workers/release/db-worker/build.gradle +++ b/applications/workers/release/db-worker/build.gradle @@ -44,8 +44,6 @@ dependencies { runtimeOnly project(':libs:tracing-impl') testImplementation 'org.osgi:osgi.core' - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation project(':libs:application:addon') testImplementation project(':libs:application:banner') testImplementation project(":libs:lifecycle:lifecycle") diff --git a/applications/workers/release/p2p-gateway-worker/src/main/kotlin/net.corda.applications.workers.p2p.gateway/GatewayWorker.kt b/applications/workers/release/p2p-gateway-worker/src/main/kotlin/net.corda.applications.workers.p2p.gateway/GatewayWorker.kt index 543cc89dd8b..bb60438053f 100644 --- a/applications/workers/release/p2p-gateway-worker/src/main/kotlin/net.corda.applications.workers.p2p.gateway/GatewayWorker.kt +++ b/applications/workers/release/p2p-gateway-worker/src/main/kotlin/net.corda.applications.workers.p2p.gateway/GatewayWorker.kt @@ -13,6 +13,7 @@ import net.corda.lifecycle.registry.LifecycleRegistry import net.corda.osgi.api.Application import net.corda.osgi.api.Shutdown import net.corda.processors.p2p.gateway.GatewayProcessor +import net.corda.schema.configuration.BootConfig.BOOT_WORKER_SERVICE import net.corda.tracing.configureTracing import net.corda.tracing.shutdownTracing import net.corda.web.api.WebServer @@ -21,6 +22,7 @@ import org.osgi.service.component.annotations.Component import org.osgi.service.component.annotations.Reference import org.slf4j.LoggerFactory import picocli.CommandLine +import picocli.CommandLine.Option @Component @Suppress("LongParameterList") @@ -63,7 +65,8 @@ class GatewayWorker @Activate constructor( val config = WorkerHelpers.getBootstrapConfig( secretsServiceFactoryResolver, params.defaultParams, - configurationValidatorFactory.createConfigValidator() + configurationValidatorFactory.createConfigValidator(), + listOf(WorkerHelpers.createConfigFromParams(BOOT_WORKER_SERVICE, params.workerEndpoints)), ) webServer.start(params.defaultParams.workerServerPort) gatewayProcessor.start(config) @@ -80,4 +83,11 @@ class GatewayWorker @Activate constructor( private class GatewayWorkerParams { @CommandLine.Mixin var defaultParams = DefaultWorkerParams() + + @Option( + names = ["--serviceEndpoint"], + description = ["Internal REST endpoints for Corda workers"], + required = true, + ) + val workerEndpoints: Map = emptyMap() } diff --git a/applications/workers/release/persistence-worker/build.gradle b/applications/workers/release/persistence-worker/build.gradle index bb468b352b9..14c9317f68f 100644 --- a/applications/workers/release/persistence-worker/build.gradle +++ b/applications/workers/release/persistence-worker/build.gradle @@ -43,8 +43,6 @@ dependencies { runtimeOnly project(':libs:web:web-impl') testImplementation 'org.osgi:osgi.core' - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation project(':libs:application:addon') testImplementation project(':libs:application:banner') diff --git a/applications/workers/release/token-selection-worker/build.gradle b/applications/workers/release/token-selection-worker/build.gradle index 46b60623fac..2ca5b84b86f 100644 --- a/applications/workers/release/token-selection-worker/build.gradle +++ b/applications/workers/release/token-selection-worker/build.gradle @@ -41,8 +41,6 @@ dependencies { runtimeOnly project(':libs:tracing-impl') testImplementation 'org.osgi:osgi.core' - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation project(':libs:application:addon') testImplementation project(':libs:application:banner') diff --git a/applications/workers/release/uniqueness-worker/build.gradle b/applications/workers/release/uniqueness-worker/build.gradle index 1ea5e705a46..4379b10a53a 100644 --- a/applications/workers/release/uniqueness-worker/build.gradle +++ b/applications/workers/release/uniqueness-worker/build.gradle @@ -42,8 +42,6 @@ dependencies { runtimeOnly project(':libs:tracing-impl') testImplementation 'org.osgi:osgi.core' - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation project(':libs:application:addon') testImplementation project(':libs:application:banner') diff --git a/applications/workers/worker-common/build.gradle b/applications/workers/worker-common/build.gradle index 3bc5a56d0fb..0f5510d1e12 100644 --- a/applications/workers/worker-common/build.gradle +++ b/applications/workers/worker-common/build.gradle @@ -53,8 +53,6 @@ dependencies { runtimeOnly project(':libs:web:web-impl') runtimeOnly "org.apache.commons:commons-lang3:$commonsLangVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation project(":libs:web:web-impl") testRuntimeOnly 'org.osgi:osgi.core' diff --git a/applications/workers/workers-smoketest/build.gradle b/applications/workers/workers-smoketest/build.gradle index 04f7843f3cb..aeb1968f468 100644 --- a/applications/workers/workers-smoketest/build.gradle +++ b/applications/workers/workers-smoketest/build.gradle @@ -53,8 +53,6 @@ kotlin { dependencies { // NO CORDA DEPENDENCIES!! - implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion" - smokeTestImplementation "net.corda:corda-avro-schema:$cordaApiVersion" // Avoid having the schema names and keys scattered across projects smokeTestImplementation "net.corda:corda-config-schema:$cordaApiVersion" @@ -82,7 +80,8 @@ dependencies { smokeTestImplementation project(":testing:packaging-test-utilities") smokeTestImplementation project(':testing:test-utilities') smokeTestImplementation project(":testing:uniqueness:uniqueness-utilities") - smokeTestRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junit5Version" + smokeTestImplementation libs.bundles.test + smokeTestRuntimeOnly libs.bundles.test.runtime smokeTestRuntimeOnly "org.apache.logging.log4j:log4j-slf4j-impl:$log4jVersion" } diff --git a/build.gradle b/build.gradle index e38b9b556a8..7514a1dfd70 100644 --- a/build.gradle +++ b/build.gradle @@ -14,9 +14,9 @@ buildscript { } plugins { - id 'org.jetbrains.kotlin.jvm' apply false - id 'org.jetbrains.kotlin.plugin.allopen' apply false - id 'org.jetbrains.kotlin.plugin.jpa' apply false + alias libs.plugins.kotlin.jvm apply false + alias libs.plugins.kotlin.allopen apply false + alias libs.plugins.kotlin.jpa apply false id 'io.gitlab.arturbosch.detekt' apply false id 'biz.aQute.bnd.builder' apply false id 'com.adarshr.test-logger' version '3.2.0' apply false @@ -278,14 +278,6 @@ allprojects { shouldRunAfter tasks.named('test', Test) } - - dependencies { - // Test utilities - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.junit.jupiter:junit-jupiter:$junit5Version" - testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junit5Version" - testRuntimeOnly 'org.junit.platform:junit-platform-launcher' - } } tasks.register('createSBOMZip', Zip) { @@ -326,11 +318,11 @@ if (project.hasProperty('generateSBOM')) { void configureKotlinForOSGi(Configuration configuration) { configuration.resolutionStrategy { dependencySubstitution { - substitute module('org.jetbrains.kotlin:kotlin-stdlib-jdk8') using module("org.jetbrains.kotlin:kotlin-osgi-bundle:$kotlinVersion") - substitute module('org.jetbrains.kotlin:kotlin-stdlib-jdk7') using module("org.jetbrains.kotlin:kotlin-osgi-bundle:$kotlinVersion") - substitute module('org.jetbrains.kotlin:kotlin-stdlib-common') using module("org.jetbrains.kotlin:kotlin-osgi-bundle:$kotlinVersion") - substitute module('org.jetbrains.kotlin:kotlin-stdlib') using module("org.jetbrains.kotlin:kotlin-osgi-bundle:$kotlinVersion") - substitute module('org.jetbrains.kotlin:kotlin-reflect') using module("org.jetbrains.kotlin:kotlin-osgi-bundle:$kotlinVersion") + substitute module('org.jetbrains.kotlin:kotlin-stdlib-jdk8') using module("org.jetbrains.kotlin:kotlin-osgi-bundle:${libs.versions.kotlinVersion.get()}") + substitute module('org.jetbrains.kotlin:kotlin-stdlib-jdk7') using module("org.jetbrains.kotlin:kotlin-osgi-bundle:${libs.versions.kotlinVersion.get()}") + substitute module('org.jetbrains.kotlin:kotlin-stdlib-common') using module("org.jetbrains.kotlin:kotlin-osgi-bundle:${libs.versions.kotlinVersion.get()}") + substitute module('org.jetbrains.kotlin:kotlin-stdlib') using module("org.jetbrains.kotlin:kotlin-osgi-bundle:${libs.versions.kotlinVersion.get()}") + substitute module('org.jetbrains.kotlin:kotlin-reflect') using module("org.jetbrains.kotlin:kotlin-osgi-bundle:${libs.versions.kotlinVersion.get()}") } } } diff --git a/buildSrc/settings.gradle b/buildSrc/settings.gradle new file mode 100644 index 00000000000..3ef0465d8ca --- /dev/null +++ b/buildSrc/settings.gradle @@ -0,0 +1,7 @@ +dependencyResolutionManagement { + versionCatalogs { + create('libs', { from(files("../gradle/libs.versions.toml")) }) + } +} + +rootProject.name = 'buildSrc' \ No newline at end of file diff --git a/buildSrc/src/main/groovy/corda.common-app.gradle b/buildSrc/src/main/groovy/corda.common-app.gradle index 7d5ac7245f1..5d99531e014 100644 --- a/buildSrc/src/main/groovy/corda.common-app.gradle +++ b/buildSrc/src/main/groovy/corda.common-app.gradle @@ -20,11 +20,11 @@ plugins { def applyDependencySubstitution = { Configuration conf -> conf.resolutionStrategy.dependencySubstitution { //Replace Kotlin stdlib - substitute module('org.jetbrains.kotlin:kotlin-stdlib-jdk8') using module("org.jetbrains.kotlin:kotlin-osgi-bundle:$kotlinVersion") - substitute module('org.jetbrains.kotlin:kotlin-stdlib-jdk7') using module("org.jetbrains.kotlin:kotlin-osgi-bundle:$kotlinVersion") - substitute module('org.jetbrains.kotlin:kotlin-stdlib-common') using module("org.jetbrains.kotlin:kotlin-osgi-bundle:$kotlinVersion") - substitute module('org.jetbrains.kotlin:kotlin-stdlib') using module("org.jetbrains.kotlin:kotlin-osgi-bundle:$kotlinVersion") - substitute module('org.jetbrains.kotlin:kotlin-reflect') using module("org.jetbrains.kotlin:kotlin-osgi-bundle:$kotlinVersion") + substitute module('org.jetbrains.kotlin:kotlin-stdlib-jdk8') using module("org.jetbrains.kotlin:kotlin-osgi-bundle:${libs.versions.kotlinVersion.get()}") + substitute module('org.jetbrains.kotlin:kotlin-stdlib-jdk7') using module("org.jetbrains.kotlin:kotlin-osgi-bundle:${libs.versions.kotlinVersion.get()}") + substitute module('org.jetbrains.kotlin:kotlin-stdlib-common') using module("org.jetbrains.kotlin:kotlin-osgi-bundle:${libs.versions.kotlinVersion.get()}") + substitute module('org.jetbrains.kotlin:kotlin-stdlib') using module("org.jetbrains.kotlin:kotlin-osgi-bundle:${libs.versions.kotlinVersion.get()}") + substitute module('org.jetbrains.kotlin:kotlin-reflect') using module("org.jetbrains.kotlin:kotlin-osgi-bundle:${libs.versions.kotlinVersion.get()}") } } diff --git a/buildSrc/src/main/groovy/corda.common-library.gradle b/buildSrc/src/main/groovy/corda.common-library.gradle index 63eee4015d7..8db251a1e1b 100644 --- a/buildSrc/src/main/groovy/corda.common-library.gradle +++ b/buildSrc/src/main/groovy/corda.common-library.gradle @@ -2,6 +2,7 @@ plugins { id 'java-library' + id 'org.jetbrains.kotlin.jvm' id 'biz.aQute.bnd.builder' } @@ -39,12 +40,10 @@ configurations { dependencies { compileOnly "org.jetbrains:annotations:$jetbrainsAnnotationsVersion" - testImplementation "org.junit.jupiter:junit-jupiter:$junit5Version" - testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junit5Version" - testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + testImplementation libs.bundles.test + testRuntimeOnly libs.bundles.test.runtime - integrationTestRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junit5Version" - integrationTestRuntimeOnly 'org.junit.platform:junit-platform-launcher' + integrationTestRuntimeOnly libs.bundles.test.runtime } tasks.named('jar', Jar) { diff --git a/buildSrc/src/main/groovy/corda.osgi-test-conventions.gradle b/buildSrc/src/main/groovy/corda.osgi-test-conventions.gradle index 5787930edc5..79f0be669cc 100644 --- a/buildSrc/src/main/groovy/corda.osgi-test-conventions.gradle +++ b/buildSrc/src/main/groovy/corda.osgi-test-conventions.gradle @@ -38,10 +38,9 @@ dependencies { } integrationTestRuntimeOnly files(configurations.quasarBundles) - integrationTestImplementation "org.junit.jupiter:junit-jupiter:$junit5Version" + integrationTestImplementation libs.bundles.test integrationTestImplementation "org.osgi:org.osgi.test.junit5:$osgiTestJunit5Version" - integrationTestRuntimeOnly 'org.junit.platform:junit-platform-launcher' - integrationTestRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junit5Version" + integrationTestRuntimeOnly libs.bundles.test.runtime integrationTestRuntimeOnly "org.apache.felix:org.apache.felix.framework:$felixVersion" integrationTestRuntimeOnly "org.apache.felix:org.apache.felix.scr:$felixScrVersion" integrationTestRuntimeOnly "org.osgi:org.osgi.service.component:$osgiServiceComponentVersion" diff --git a/charts/corda/templates/workers.yaml b/charts/corda/templates/workers.yaml index 85781457a3e..99291c37a76 100644 --- a/charts/corda/templates/workers.yaml +++ b/charts/corda/templates/workers.yaml @@ -13,8 +13,8 @@ {{- include "corda.worker" ( list $ .Values.workers.verification "verification" ) }} {{- include "corda.worker" ( list $ .Values.workers.membership "membership" ) }} {{- include "corda.worker" ( list $ .Values.workers.p2pGateway "p2pGateway" - ( dict "httpPort" 8080 ) -) }} + ( dict "httpPort" 8080 "servicesAccessed" ( list "p2pLinkManager" ) ) + ) }} {{- include "corda.worker" ( list $ .Values.workers.p2pLinkManager "p2pLinkManager" ) }} {{- include "corda.worker" ( list $ .Values.workers.persistence "persistence" ( dict "clusterDbAccess" true ) diff --git a/components/chunking/chunk-db-write-impl/build.gradle b/components/chunking/chunk-db-write-impl/build.gradle index 380be875d9c..7b2d00a22fb 100644 --- a/components/chunking/chunk-db-write-impl/build.gradle +++ b/components/chunking/chunk-db-write-impl/build.gradle @@ -67,8 +67,6 @@ dependencies { integrationTestImplementation project(':libs:platform-info') testImplementation "com.google.jimfs:jimfs:$jimfsVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testRuntimeOnly "org.hsqldb:hsqldb:$hsqldbVersion" testRuntimeOnly "org.postgresql:postgresql:$postgresDriverVersion" diff --git a/components/configuration/configuration-read-service-impl/build.gradle b/components/configuration/configuration-read-service-impl/build.gradle index 8e8626bf9f8..7fdb859c389 100644 --- a/components/configuration/configuration-read-service-impl/build.gradle +++ b/components/configuration/configuration-read-service-impl/build.gradle @@ -31,8 +31,6 @@ dependencies { testImplementation project(":libs:lifecycle:lifecycle-impl") testImplementation project(":libs:lifecycle:lifecycle-test-impl") - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" integrationTestImplementation project(":testing:db-message-bus-testkit") integrationTestImplementation project(":testing:test-utilities") integrationTestImplementation project(":libs:lifecycle:registry") diff --git a/components/configuration/configuration-rest-resource-service-impl/build.gradle b/components/configuration/configuration-rest-resource-service-impl/build.gradle index abb2ff533bb..44e86714b7a 100644 --- a/components/configuration/configuration-rest-resource-service-impl/build.gradle +++ b/components/configuration/configuration-rest-resource-service-impl/build.gradle @@ -27,7 +27,4 @@ dependencies { implementation 'net.corda:corda-topic-schema' implementation 'org.jetbrains.kotlin:kotlin-osgi-bundle' implementation "org.slf4j:slf4j-api:$slf4jVersion" - - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/components/configuration/configuration-write-service-impl/build.gradle b/components/configuration/configuration-write-service-impl/build.gradle index 2a8759eea34..10a999949a1 100644 --- a/components/configuration/configuration-write-service-impl/build.gradle +++ b/components/configuration/configuration-write-service-impl/build.gradle @@ -26,7 +26,4 @@ dependencies { implementation 'net.corda:corda-topic-schema' implementation 'org.jetbrains.kotlin:kotlin-osgi-bundle' implementation 'org.slf4j:slf4j-api' - - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/components/crypto/crypto-client-hsm-impl/build.gradle b/components/crypto/crypto-client-hsm-impl/build.gradle index 156a3e2c6ae..0fd20255ed7 100644 --- a/components/crypto/crypto-client-hsm-impl/build.gradle +++ b/components/crypto/crypto-client-hsm-impl/build.gradle @@ -23,8 +23,6 @@ dependencies { implementation project(":libs:messaging:messaging") implementation project(":libs:utilities") - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" - testImplementation project(":components:crypto:crypto-component-test-utils") testRuntimeOnly "org.slf4j:slf4j-simple:$slf4jVersion" diff --git a/components/crypto/crypto-client-impl/build.gradle b/components/crypto/crypto-client-impl/build.gradle index 718bf5e564d..419f53738bb 100644 --- a/components/crypto/crypto-client-impl/build.gradle +++ b/components/crypto/crypto-client-impl/build.gradle @@ -24,8 +24,6 @@ dependencies { implementation project(":libs:messaging:messaging") implementation project(":libs:utilities") - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" - testImplementation project(":components:crypto:crypto-component-test-utils") testRuntimeOnly "org.slf4j:slf4j-simple:$slf4jVersion" diff --git a/components/crypto/crypto-component-test-utils/build.gradle b/components/crypto/crypto-component-test-utils/build.gradle index 354bf90fbfb..c7255602080 100644 --- a/components/crypto/crypto-component-test-utils/build.gradle +++ b/components/crypto/crypto-component-test-utils/build.gradle @@ -23,7 +23,7 @@ dependencies { api project(":libs:lifecycle:registry") api project(":testing:test-utilities") - api "org.assertj:assertj-core:$assertjVersion" - api "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" + api libs.assertj.core + api libs.mockito.kotlin } diff --git a/components/crypto/crypto-hes-impl/build.gradle b/components/crypto/crypto-hes-impl/build.gradle index 11c2eb18455..15f723af2d9 100644 --- a/components/crypto/crypto-hes-impl/build.gradle +++ b/components/crypto/crypto-hes-impl/build.gradle @@ -20,11 +20,6 @@ dependencies { implementation project(":components:crypto:crypto-component-core-impl") implementation project(":libs:crypto:crypto-core") - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" - testImplementation project(":components:crypto:crypto-component-test-utils") testImplementation project(":libs:crypto:cipher-suite-impl") testImplementation project(":testing:test-utilities") diff --git a/components/crypto/crypto-persistence/build.gradle b/components/crypto/crypto-persistence/build.gradle index 7286ebc2c68..41fd81cbd21 100644 --- a/components/crypto/crypto-persistence/build.gradle +++ b/components/crypto/crypto-persistence/build.gradle @@ -31,12 +31,6 @@ dependencies { implementation project(":libs:metrics") implementation project(':libs:virtual-node:virtual-node-info') - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" - testImplementation "org.junit.jupiter:junit-jupiter:$junit5Version" - } diff --git a/components/crypto/crypto-rest/build.gradle b/components/crypto/crypto-rest/build.gradle index fefdf242394..07995e5f3b5 100644 --- a/components/crypto/crypto-rest/build.gradle +++ b/components/crypto/crypto-rest/build.gradle @@ -28,7 +28,5 @@ dependencies { implementation "net.corda:corda-topic-schema" implementation 'org.jetbrains.kotlin:kotlin-osgi-bundle' - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation project(':libs:lifecycle:lifecycle-test-impl') } diff --git a/components/crypto/crypto-service-impl/build.gradle b/components/crypto/crypto-service-impl/build.gradle index 3024f485604..f79319b71d3 100644 --- a/components/crypto/crypto-service-impl/build.gradle +++ b/components/crypto/crypto-service-impl/build.gradle @@ -47,7 +47,6 @@ dependencies { testImplementation project(":libs:cache:cache-caffeine") testImplementation 'net.corda:corda-application' - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" testImplementation project(":components:crypto:crypto-component-test-utils") testImplementation project(":components:crypto:crypto-persistence-model") diff --git a/components/crypto/crypto-softhsm-impl/build.gradle b/components/crypto/crypto-softhsm-impl/build.gradle index 66a87d330f3..4390555329a 100644 --- a/components/crypto/crypto-softhsm-impl/build.gradle +++ b/components/crypto/crypto-softhsm-impl/build.gradle @@ -39,7 +39,6 @@ dependencies { implementation platform("net.corda:corda-api:$cordaApiVersion") - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" testImplementation "com.github.ben-manes.caffeine:caffeine:$caffeineVersion" testImplementation project(":components:crypto:crypto-component-test-utils") testImplementation project(":components:crypto:crypto-hes-impl") diff --git a/components/db/db-connection-manager-impl/build.gradle b/components/db/db-connection-manager-impl/build.gradle index 037cb6adf34..9fb66814dc1 100644 --- a/components/db/db-connection-manager-impl/build.gradle +++ b/components/db/db-connection-manager-impl/build.gradle @@ -26,8 +26,6 @@ dependencies { implementation "com.typesafe:config:$typeSafeConfigVersion" implementation "org.slf4j:slf4j-api:$slf4jVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testRuntimeOnly "org.osgi:osgi.core" integrationTestImplementation project(':libs:db:db-admin') diff --git a/components/domino-logic/build.gradle b/components/domino-logic/build.gradle index 8277109cf43..f3026b1fc47 100644 --- a/components/domino-logic/build.gradle +++ b/components/domino-logic/build.gradle @@ -17,8 +17,6 @@ dependencies { implementation "com.typesafe:config:$typeSafeConfigVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation "org.apache.logging.log4j:log4j-core:$log4jVersion" testRuntimeOnly "org.apache.logging.log4j:log4j-slf4j-impl:$log4jVersion" } diff --git a/components/external-messaging-services/build.gradle b/components/external-messaging-services/build.gradle index 7f20874b325..1c1218d84bc 100644 --- a/components/external-messaging-services/build.gradle +++ b/components/external-messaging-services/build.gradle @@ -22,8 +22,4 @@ dependencies { implementation project(':libs:messaging:message-bus') implementation project(":libs:utilities") implementation project(":libs:virtual-node:virtual-node-info") - - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/components/flow/flow-mapper-impl/build.gradle b/components/flow/flow-mapper-impl/build.gradle index 7cc886d64a9..b89340bec45 100644 --- a/components/flow/flow-mapper-impl/build.gradle +++ b/components/flow/flow-mapper-impl/build.gradle @@ -26,9 +26,6 @@ dependencies { implementation "net.corda:corda-config-schema" implementation "net.corda:corda-topic-schema" - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation project(":testing:flow:flow-utilities") testImplementation project(":libs:flows:flow-utils") } diff --git a/components/flow/flow-mapper-service/build.gradle b/components/flow/flow-mapper-service/build.gradle index c8d6a4d8f8e..49153c6867a 100644 --- a/components/flow/flow-mapper-service/build.gradle +++ b/components/flow/flow-mapper-service/build.gradle @@ -31,10 +31,6 @@ dependencies { runtimeOnly project(":libs:web:web-impl") - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" - testImplementation project(":libs:lifecycle:lifecycle-test-impl") testImplementation project(":testing:test-utilities") testImplementation project(":testing:flow:flow-utilities") diff --git a/components/flow/flow-p2p-filter-service/build.gradle b/components/flow/flow-p2p-filter-service/build.gradle index 553f9a8e296..dfdd013005b 100644 --- a/components/flow/flow-p2p-filter-service/build.gradle +++ b/components/flow/flow-p2p-filter-service/build.gradle @@ -28,9 +28,6 @@ dependencies { runtimeOnly project(":libs:web:web-impl") - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation project(":libs:flows:flow-utils") integrationTestImplementation project(":testing:db-message-bus-testkit") diff --git a/components/flow/flow-rest-resource-service-impl/build.gradle b/components/flow/flow-rest-resource-service-impl/build.gradle index 4174528f488..22a1963d902 100644 --- a/components/flow/flow-rest-resource-service-impl/build.gradle +++ b/components/flow/flow-rest-resource-service-impl/build.gradle @@ -39,8 +39,6 @@ dependencies { implementation "com.google.guava:guava:$guavaVersion" implementation "org.apache.commons:commons-lang3:$commonsLangVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation project(":libs:lifecycle:lifecycle-test-impl") testImplementation project(':testing:test-utilities') } diff --git a/components/flow/flow-service/build.gradle b/components/flow/flow-service/build.gradle index 6ea2f66a3e7..cd63cc0bf8b 100644 --- a/components/flow/flow-service/build.gradle +++ b/components/flow/flow-service/build.gradle @@ -65,9 +65,6 @@ dependencies { implementation "com.esotericsoftware:kryo:$kryoVersion" implementation "com.fasterxml.jackson.module:jackson-module-kotlin:$jacksonVersion" - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation "org.apache.felix:org.apache.felix.framework:$felixVersion" testImplementation "com.fasterxml.jackson.module:jackson-module-kotlin:$jacksonVersion" diff --git a/components/gateway/build.gradle b/components/gateway/build.gradle index 027c89109c8..420871e0127 100644 --- a/components/gateway/build.gradle +++ b/components/gateway/build.gradle @@ -33,9 +33,8 @@ dependencies { implementation "com.github.ben-manes.caffeine:caffeine:$caffeineVersion" implementation project(':libs:schema-registry:schema-registry') implementation project(":libs:metrics") + implementation project(':libs:platform-info') - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation project(":testing:test-utilities") integrationTestRuntimeOnly "org.apache.logging.log4j:log4j-slf4j-impl:$log4jVersion" integrationTestImplementation "org.apache.logging.log4j:log4j-core:$log4jVersion" diff --git a/components/gateway/src/integrationTest/kotlin/net/corda/p2p/gateway/GatewayIntegrationTest.kt b/components/gateway/src/integrationTest/kotlin/net/corda/p2p/gateway/GatewayIntegrationTest.kt index 6513008b2f7..a73bd6cc263 100644 --- a/components/gateway/src/integrationTest/kotlin/net/corda/p2p/gateway/GatewayIntegrationTest.kt +++ b/components/gateway/src/integrationTest/kotlin/net/corda/p2p/gateway/GatewayIntegrationTest.kt @@ -25,6 +25,7 @@ import net.corda.data.p2p.gateway.GatewayMessage import net.corda.data.p2p.gateway.GatewayResponse import net.corda.data.p2p.mtls.gateway.ClientCertificateSubjects import net.corda.libs.configuration.SmartConfigImpl +import net.corda.libs.platform.PlatformInfoProvider import net.corda.lifecycle.LifecycleStatus import net.corda.lifecycle.impl.LifecycleCoordinatorFactoryImpl import net.corda.lifecycle.impl.LifecycleCoordinatorSchedulerFactoryImpl @@ -60,6 +61,7 @@ import net.corda.schema.Schemas.P2P.GATEWAY_TLS_TRUSTSTORES import net.corda.schema.Schemas.P2P.LINK_IN_TOPIC import net.corda.schema.Schemas.P2P.LINK_OUT_TOPIC import net.corda.schema.Schemas.P2P.SESSION_OUT_PARTITIONS +import net.corda.schema.configuration.BootConfig import net.corda.schema.configuration.BootConfig.INSTANCE_ID import net.corda.schema.configuration.BootConfig.TOPIC_PREFIX import net.corda.schema.configuration.MessagingConfig.MAX_ALLOWED_MSG_SIZE @@ -122,11 +124,24 @@ internal class GatewayIntegrationTest : TestBase() { private val sessionId = "session-1" private val instanceId = AtomicInteger(0) - private val messagingConfig = SmartConfigImpl.empty() + private val baseMessagingConfig = SmartConfigImpl.empty() .withValue(INSTANCE_ID, ConfigValueFactory.fromAnyRef(instanceId.getAndIncrement())) .withValue(MAX_ALLOWED_MSG_SIZE, ConfigValueFactory.fromAnyRef(10000000)) + private fun messagingConfig() = + baseMessagingConfig + .withValue(INSTANCE_ID, ConfigValueFactory.fromAnyRef(instanceId.incrementAndGet())) private val avroSchemaRegistry = AvroSchemaRegistryImpl() + private val platformInfoProvider = object : PlatformInfoProvider { + override val activePlatformVersion = 1 + override val localWorkerPlatformVersion = 1 + override val localWorkerSoftwareVersion = "5.2" + } + private val bootConfig = SmartConfigImpl.empty() + .withValue( + BootConfig.P2P_LINK_MANAGER_WORKER_REST_ENDPOINT, + ConfigValueFactory.fromAnyRef("localhost:${getOpenPort()}"), + ) private inner class Node(private val name: String) { private val topicService = TopicServiceImpl() @@ -136,7 +151,7 @@ internal class GatewayIntegrationTest : TestBase() { LifecycleCoordinatorFactoryImpl(LifecycleRegistryImpl(), LifecycleCoordinatorSchedulerFactoryImpl()) val subscriptionFactory = InMemSubscriptionFactory(topicService, rpcTopicService, lifecycleCoordinatorFactory) val publisherFactory = CordaPublisherFactory(topicService, rpcTopicService, lifecycleCoordinatorFactory) - val publisher = publisherFactory.createPublisher(PublisherConfig("$name.id", false), messagingConfig) + val publisher = publisherFactory.createPublisher(PublisherConfig("$name.id", false), baseMessagingConfig) val cryptoOpsClient = TestCryptoOpsClient(lifecycleCoordinatorFactory) fun stop() { @@ -165,8 +180,7 @@ internal class GatewayIntegrationTest : TestBase() { override val keyClass = Any::class.java override val valueClass = Any::class.java }, - messagingConfig = messagingConfig - .withValue(INSTANCE_ID, ConfigValueFactory.fromAnyRef(instanceId.incrementAndGet())) + messagingConfig = messagingConfig() .withValue(TOPIC_PREFIX, ConfigValueFactory.fromAnyRef("")), partitionAssignmentListener = null ).use { @@ -272,9 +286,11 @@ internal class GatewayIntegrationTest : TestBase() { alice.subscriptionFactory, alice.publisherFactory, alice.lifecycleCoordinatorFactory, - messagingConfig.withValue(INSTANCE_ID, ConfigValueFactory.fromAnyRef(instanceId.incrementAndGet())), alice.cryptoOpsClient, - avroSchemaRegistry + avroSchemaRegistry, + platformInfoProvider, + bootConfig, + messagingConfig(), ).usingLifecycle { alice.publishKeyStoreCertificatesAndKeys(aliceKeyStore, aliceHoldingIdentity) it.startAndWaitForStarted() @@ -318,9 +334,11 @@ internal class GatewayIntegrationTest : TestBase() { alice.subscriptionFactory, alice.publisherFactory, alice.lifecycleCoordinatorFactory, - messagingConfig.withValue(INSTANCE_ID, ConfigValueFactory.fromAnyRef(instanceId.incrementAndGet())), alice.cryptoOpsClient, - avroSchemaRegistry + avroSchemaRegistry, + platformInfoProvider, + bootConfig, + messagingConfig(), ).usingLifecycle { alice.publishKeyStoreCertificatesAndKeys(aliceKeyStore, aliceHoldingIdentity) it.startAndWaitForStarted() @@ -386,9 +404,11 @@ internal class GatewayIntegrationTest : TestBase() { alice.subscriptionFactory, alice.publisherFactory, alice.lifecycleCoordinatorFactory, - messagingConfig.withValue(INSTANCE_ID, ConfigValueFactory.fromAnyRef(instanceId.incrementAndGet())), alice.cryptoOpsClient, - avroSchemaRegistry + avroSchemaRegistry, + platformInfoProvider, + bootConfig, + messagingConfig(), ).usingLifecycle { alice.publishKeyStoreCertificatesAndKeys(aliceKeyStore, aliceHoldingIdentity) it.startAndWaitForStarted() @@ -461,9 +481,11 @@ internal class GatewayIntegrationTest : TestBase() { alice.subscriptionFactory, alice.publisherFactory, alice.lifecycleCoordinatorFactory, - messagingConfig.withValue(INSTANCE_ID, ConfigValueFactory.fromAnyRef(instanceId.incrementAndGet())), alice.cryptoOpsClient, - avroSchemaRegistry + avroSchemaRegistry, + platformInfoProvider, + bootConfig, + messagingConfig(), ).usingLifecycle { alice.publishKeyStoreCertificatesAndKeys(aliceKeyStore, aliceHoldingIdentity) it.startAndWaitForStarted() @@ -528,9 +550,11 @@ internal class GatewayIntegrationTest : TestBase() { alice.subscriptionFactory, alice.publisherFactory, alice.lifecycleCoordinatorFactory, - messagingConfig.withValue(INSTANCE_ID, ConfigValueFactory.fromAnyRef(instanceId.incrementAndGet())), alice.cryptoOpsClient, avroSchemaRegistry, + platformInfoProvider, + bootConfig, + messagingConfig(), ).usingLifecycle { alice.publishKeyStoreCertificatesAndKeys(aliceKeyStore, aliceHoldingIdentity) it.startAndWaitForStarted() @@ -633,9 +657,11 @@ internal class GatewayIntegrationTest : TestBase() { alice.subscriptionFactory, alice.publisherFactory, alice.lifecycleCoordinatorFactory, - messagingConfig.withValue(INSTANCE_ID, ConfigValueFactory.fromAnyRef(instanceId.incrementAndGet())), alice.cryptoOpsClient, - avroSchemaRegistry + avroSchemaRegistry, + platformInfoProvider, + bootConfig, + messagingConfig(), ).usingLifecycle { alice.publishKeyStoreCertificatesAndKeys(aliceKeyStore, aliceHoldingIdentity) it.startAndWaitForStarted() @@ -680,9 +706,11 @@ internal class GatewayIntegrationTest : TestBase() { alice.subscriptionFactory, alice.publisherFactory, alice.lifecycleCoordinatorFactory, - messagingConfig.withValue(INSTANCE_ID, ConfigValueFactory.fromAnyRef(instanceId.incrementAndGet())), alice.cryptoOpsClient, - avroSchemaRegistry + avroSchemaRegistry, + platformInfoProvider, + bootConfig, + messagingConfig(), ).usingLifecycle { alice.publishKeyStoreCertificatesAndKeys(ipKeyStore, aliceHoldingIdentity) it.startAndWaitForStarted() @@ -780,9 +808,11 @@ internal class GatewayIntegrationTest : TestBase() { alice.subscriptionFactory, alice.publisherFactory, alice.lifecycleCoordinatorFactory, - messagingConfig.withValue(INSTANCE_ID, ConfigValueFactory.fromAnyRef(instanceId.incrementAndGet())), alice.cryptoOpsClient, avroSchemaRegistry, + platformInfoProvider, + bootConfig, + messagingConfig(), ).usingLifecycle { gateway -> gateway.start() @@ -867,9 +897,11 @@ internal class GatewayIntegrationTest : TestBase() { alice.subscriptionFactory, alice.publisherFactory, alice.lifecycleCoordinatorFactory, - messagingConfig.withValue(INSTANCE_ID, ConfigValueFactory.fromAnyRef(instanceId.incrementAndGet())), alice.cryptoOpsClient, - avroSchemaRegistry + avroSchemaRegistry, + platformInfoProvider, + bootConfig, + messagingConfig(), ).usingLifecycle { it.startAndWaitForStarted() (1..clientNumber).map { index -> @@ -976,9 +1008,11 @@ internal class GatewayIntegrationTest : TestBase() { alice.subscriptionFactory, alice.publisherFactory, alice.lifecycleCoordinatorFactory, - messagingConfig.withValue(INSTANCE_ID, ConfigValueFactory.fromAnyRef(instanceId.incrementAndGet())), alice.cryptoOpsClient, - avroSchemaRegistry + avroSchemaRegistry, + platformInfoProvider, + bootConfig, + messagingConfig(), ).usingLifecycle { alice.publishKeyStoreCertificatesAndKeys(aliceKeyStore, aliceHoldingIdentity) startTime = Instant.now().toEpochMilli() @@ -1047,10 +1081,7 @@ internal class GatewayIntegrationTest : TestBase() { override val keyClass = Any::class.java override val valueClass = Any::class.java }, - messagingConfig = messagingConfig.withValue( - INSTANCE_ID, - ConfigValueFactory.fromAnyRef(instanceId.incrementAndGet()) - ), + messagingConfig = messagingConfig(), partitionAssignmentListener = null ) bobSubscription.start() @@ -1069,10 +1100,7 @@ internal class GatewayIntegrationTest : TestBase() { override val keyClass = Any::class.java override val valueClass = Any::class.java }, - messagingConfig = messagingConfig.withValue( - INSTANCE_ID, - ConfigValueFactory.fromAnyRef(instanceId.incrementAndGet()) - ), + messagingConfig = messagingConfig(), partitionAssignmentListener = null ) aliceSubscription.start() @@ -1098,9 +1126,11 @@ internal class GatewayIntegrationTest : TestBase() { alice.subscriptionFactory, alice.publisherFactory, alice.lifecycleCoordinatorFactory, - messagingConfig.withValue(INSTANCE_ID, ConfigValueFactory.fromAnyRef(instanceId.incrementAndGet())), alice.cryptoOpsClient, - avroSchemaRegistry + avroSchemaRegistry, + platformInfoProvider, + bootConfig, + messagingConfig(), ), Gateway( createConfigurationServiceFor( @@ -1121,9 +1151,11 @@ internal class GatewayIntegrationTest : TestBase() { bob.subscriptionFactory, bob.publisherFactory, bob.lifecycleCoordinatorFactory, - messagingConfig.withValue(INSTANCE_ID, ConfigValueFactory.fromAnyRef(instanceId.incrementAndGet())), bob.cryptoOpsClient, avroSchemaRegistry, + platformInfoProvider, + bootConfig, + messagingConfig(), ) ).onEach { it.startAndWaitForStarted() @@ -1194,9 +1226,11 @@ internal class GatewayIntegrationTest : TestBase() { alice.subscriptionFactory, alice.publisherFactory, alice.lifecycleCoordinatorFactory, - messagingConfig.withValue(INSTANCE_ID, ConfigValueFactory.fromAnyRef(instanceId.incrementAndGet())), alice.cryptoOpsClient, - avroSchemaRegistry + avroSchemaRegistry, + platformInfoProvider, + bootConfig, + messagingConfig(), ).usingLifecycle { gateway -> val port = getOpenPort() logger.info("Publishing good config") @@ -1349,9 +1383,11 @@ internal class GatewayIntegrationTest : TestBase() { server.subscriptionFactory, server.publisherFactory, server.lifecycleCoordinatorFactory, - messagingConfig.withValue(INSTANCE_ID, ConfigValueFactory.fromAnyRef(instanceId.incrementAndGet())), server.cryptoOpsClient, - avroSchemaRegistry + avroSchemaRegistry, + platformInfoProvider, + bootConfig, + messagingConfig(), ).usingLifecycle { gateway -> gateway.startAndWaitForStarted() val firstCertificatesAuthority = CertificateAuthorityFactory @@ -1526,10 +1562,7 @@ internal class GatewayIntegrationTest : TestBase() { override val keyClass = Any::class.java override val valueClass = Any::class.java }, - messagingConfig = messagingConfig.withValue( - INSTANCE_ID, - ConfigValueFactory.fromAnyRef(instanceId.incrementAndGet()) - ), + messagingConfig = messagingConfig(), partitionAssignmentListener = null ) bobSubscription.start() @@ -1548,10 +1581,7 @@ internal class GatewayIntegrationTest : TestBase() { override val keyClass = Any::class.java override val valueClass = Any::class.java }, - messagingConfig = messagingConfig.withValue( - INSTANCE_ID, - ConfigValueFactory.fromAnyRef(instanceId.incrementAndGet()) - ), + messagingConfig = messagingConfig(), partitionAssignmentListener = null ) aliceSubscription.start() @@ -1577,9 +1607,11 @@ internal class GatewayIntegrationTest : TestBase() { alice.subscriptionFactory, alice.publisherFactory, alice.lifecycleCoordinatorFactory, - messagingConfig.withValue(INSTANCE_ID, ConfigValueFactory.fromAnyRef(instanceId.incrementAndGet())), alice.cryptoOpsClient, - avroSchemaRegistry + avroSchemaRegistry, + platformInfoProvider, + bootConfig, + messagingConfig(), ), Gateway( createConfigurationServiceFor( @@ -1599,9 +1631,11 @@ internal class GatewayIntegrationTest : TestBase() { bob.subscriptionFactory, bob.publisherFactory, bob.lifecycleCoordinatorFactory, - messagingConfig.withValue(INSTANCE_ID, ConfigValueFactory.fromAnyRef(instanceId.incrementAndGet())), bob.cryptoOpsClient, avroSchemaRegistry, + platformInfoProvider, + bootConfig, + messagingConfig(), ) ).onEach { it.startAndWaitForStarted() diff --git a/components/gateway/src/main/kotlin/net/corda/p2p/gateway/Gateway.kt b/components/gateway/src/main/kotlin/net/corda/p2p/gateway/Gateway.kt index 9613d9d50c1..74a811c6539 100644 --- a/components/gateway/src/main/kotlin/net/corda/p2p/gateway/Gateway.kt +++ b/components/gateway/src/main/kotlin/net/corda/p2p/gateway/Gateway.kt @@ -3,6 +3,7 @@ package net.corda.p2p.gateway import net.corda.configuration.read.ConfigurationReadService import net.corda.crypto.client.CryptoOpsClient import net.corda.libs.configuration.SmartConfig +import net.corda.libs.platform.PlatformInfoProvider import net.corda.lifecycle.LifecycleCoordinatorFactory import net.corda.lifecycle.domino.logic.ComplexDominoTile import net.corda.lifecycle.domino.logic.DominoTile @@ -33,9 +34,11 @@ class Gateway( subscriptionFactory: SubscriptionFactory, publisherFactory: PublisherFactory, lifecycleCoordinatorFactory: LifecycleCoordinatorFactory, - messagingConfiguration: SmartConfig, cryptoOpsClient: CryptoOpsClient, - avroSchemaRegistry: AvroSchemaRegistry + avroSchemaRegistry: AvroSchemaRegistry, + platformInfoProvider: PlatformInfoProvider, + bootConfig: SmartConfig, + messagingConfiguration: SmartConfig, ) : LifecycleWithDominoTile { private val commonComponents = CommonComponents( @@ -52,6 +55,8 @@ class Gateway( messagingConfiguration, commonComponents, avroSchemaRegistry, + platformInfoProvider, + bootConfig, ) private val outboundMessageProcessor = OutboundMessageHandler( lifecycleCoordinatorFactory, diff --git a/components/gateway/src/main/kotlin/net/corda/p2p/gateway/messaging/internal/InboundMessageHandler.kt b/components/gateway/src/main/kotlin/net/corda/p2p/gateway/messaging/internal/InboundMessageHandler.kt index bccb0a4c295..cf1400f5f60 100644 --- a/components/gateway/src/main/kotlin/net/corda/p2p/gateway/messaging/internal/InboundMessageHandler.kt +++ b/components/gateway/src/main/kotlin/net/corda/p2p/gateway/messaging/internal/InboundMessageHandler.kt @@ -14,6 +14,7 @@ import net.corda.data.p2p.crypto.ResponderHelloMessage import net.corda.data.p2p.gateway.GatewayMessage import net.corda.data.p2p.gateway.GatewayResponse import net.corda.libs.configuration.SmartConfig +import net.corda.libs.platform.PlatformInfoProvider import net.corda.lifecycle.LifecycleCoordinatorFactory import net.corda.lifecycle.domino.logic.ComplexDominoTile import net.corda.lifecycle.domino.logic.LifecycleWithDominoTile @@ -51,7 +52,9 @@ internal class InboundMessageHandler( subscriptionFactory: SubscriptionFactory, messagingConfiguration: SmartConfig, commonComponents: CommonComponents, - private val avroSchemaRegistry: AvroSchemaRegistry + private val avroSchemaRegistry: AvroSchemaRegistry, + platformInfoProvider: PlatformInfoProvider, + bootConfig: SmartConfig, ) : RequestListener, LifecycleWithDominoTile { init { @@ -89,6 +92,12 @@ internal class InboundMessageHandler( subscriptionFactory, messagingConfiguration ) + private val linkManagerClient = + LinkManagerRpcClient( + publisherFactory, + platformInfoProvider, + bootConfig, + ) private val server = ReconfigurableHttpServer( lifecycleCoordinatorFactory, diff --git a/components/gateway/src/main/kotlin/net/corda/p2p/gateway/messaging/internal/LinkManagerRpcClient.kt b/components/gateway/src/main/kotlin/net/corda/p2p/gateway/messaging/internal/LinkManagerRpcClient.kt new file mode 100644 index 00000000000..7dbab949854 --- /dev/null +++ b/components/gateway/src/main/kotlin/net/corda/p2p/gateway/messaging/internal/LinkManagerRpcClient.kt @@ -0,0 +1,33 @@ +package net.corda.p2p.gateway.messaging.internal + +import net.corda.data.p2p.LinkInMessage +import net.corda.data.p2p.crypto.AuthenticatedDataMessage +import net.corda.libs.configuration.SmartConfig +import net.corda.libs.platform.PlatformInfoProvider +import net.corda.messaging.api.constants.WorkerRPCPaths.P2P_LINK_MANAGER_PATH +import net.corda.messaging.api.publisher.factory.PublisherFactory +import net.corda.messaging.api.publisher.send +import net.corda.schema.configuration.BootConfig.P2P_LINK_MANAGER_WORKER_REST_ENDPOINT +import java.net.URI + +internal class LinkManagerRpcClient( + publisherFactory: PublisherFactory, + platformInfoProvider: PlatformInfoProvider, + bootConfig: SmartConfig, +) { + private val client by lazy { + publisherFactory.createHttpRpcClient() + } + + private val endpoint= + bootConfig.getString(P2P_LINK_MANAGER_WORKER_REST_ENDPOINT) + + private val url by lazy { + val platformVersion = platformInfoProvider.localWorkerSoftwareShortVersion + URI.create("http://$endpoint/api/$platformVersion$P2P_LINK_MANAGER_PATH") + } + + fun send(message: LinkInMessage): AuthenticatedDataMessage? { + return client.send(url, message) + } +} \ No newline at end of file diff --git a/components/gateway/src/test/kotlin/net/corda/p2p/gateway/messaging/internal/InboundMessageHandlerTest.kt b/components/gateway/src/test/kotlin/net/corda/p2p/gateway/messaging/internal/InboundMessageHandlerTest.kt index afb90b9be9c..1ce9e3ca01b 100644 --- a/components/gateway/src/test/kotlin/net/corda/p2p/gateway/messaging/internal/InboundMessageHandlerTest.kt +++ b/components/gateway/src/test/kotlin/net/corda/p2p/gateway/messaging/internal/InboundMessageHandlerTest.kt @@ -105,7 +105,9 @@ class InboundMessageHandlerTest { subscriptionFactory, SmartConfigImpl.empty(), mock(), - avroSchemaRegistry + avroSchemaRegistry, + mock(), + mock(), ) @AfterEach diff --git a/components/gateway/src/test/kotlin/net/corda/p2p/gateway/messaging/internal/LinkManagerRpcClientTest.kt b/components/gateway/src/test/kotlin/net/corda/p2p/gateway/messaging/internal/LinkManagerRpcClientTest.kt new file mode 100644 index 00000000000..d47a0cc561c --- /dev/null +++ b/components/gateway/src/test/kotlin/net/corda/p2p/gateway/messaging/internal/LinkManagerRpcClientTest.kt @@ -0,0 +1,86 @@ +package net.corda.p2p.gateway.messaging.internal + +import net.corda.data.p2p.LinkInMessage +import net.corda.data.p2p.crypto.AuthenticatedDataMessage +import net.corda.libs.configuration.SmartConfig +import net.corda.libs.platform.PlatformInfoProvider +import net.corda.messaging.api.constants.WorkerRPCPaths.P2P_LINK_MANAGER_PATH +import net.corda.messaging.api.publisher.HttpRpcClient +import net.corda.messaging.api.publisher.factory.PublisherFactory +import net.corda.schema.configuration.BootConfig.P2P_LINK_MANAGER_WORKER_REST_ENDPOINT +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.mockito.kotlin.any +import org.mockito.kotlin.argumentCaptor +import org.mockito.kotlin.doReturn +import org.mockito.kotlin.eq +import org.mockito.kotlin.mock +import org.mockito.kotlin.whenever +import java.net.URI + +class LinkManagerRpcClientTest { + private val mockClient = mock< HttpRpcClient>() + private val publisherFactory = mock { + on { createHttpRpcClient() } doReturn mockClient + } + private val platformInfoProvider = mock { + on { localWorkerSoftwareShortVersion } doReturn "5.x" + } + private val bootConfig = mock { + on { getString(P2P_LINK_MANAGER_WORKER_REST_ENDPOINT) } doReturn "link-manager:2001" + } + private val client = LinkManagerRpcClient( + publisherFactory, + platformInfoProvider, + bootConfig, + ) + + @Test + fun `send sends the message to the correct URL`() { + val uri = argumentCaptor() + whenever( + mockClient.send( + uri.capture(), + any(), + eq(AuthenticatedDataMessage::class.java), + ) + ).doReturn(null) + + client.send(mock()) + + assertThat(uri.firstValue.toString()) + .isEqualTo("http://link-manager:2001/api/5.x$P2P_LINK_MANAGER_PATH") + } + + @Test + fun `send sends the correct object`() { + val sent = argumentCaptor() + whenever( + mockClient.send( + any(), + sent.capture(), + eq(AuthenticatedDataMessage::class.java), + ) + ).doReturn(null) + val message = LinkInMessage() + + client.send(message) + + assertThat(sent.firstValue) + .isSameAs(message) + } + + @Test + fun `send return the correct response the correct object`() { + val message = AuthenticatedDataMessage() + whenever( + mockClient.send( + any(), + any(), + eq(AuthenticatedDataMessage::class.java), + ) + ).doReturn(message) + + assertThat(client.send(mock())).isSameAs(message) + } +} diff --git a/components/ledger/ledger-common-flow-api/src/main/kotlin/net/corda/ledger/common/flow/transaction/filtered/factory/ComponentGroupFilterParameters.kt b/components/ledger/ledger-common-flow-api/src/main/kotlin/net/corda/ledger/common/flow/transaction/filtered/factory/ComponentGroupFilterParameters.kt index 3bc7958ef89..28d5c787193 100644 --- a/components/ledger/ledger-common-flow-api/src/main/kotlin/net/corda/ledger/common/flow/transaction/filtered/factory/ComponentGroupFilterParameters.kt +++ b/components/ledger/ledger-common-flow-api/src/main/kotlin/net/corda/ledger/common/flow/transaction/filtered/factory/ComponentGroupFilterParameters.kt @@ -34,9 +34,33 @@ sealed interface ComponentGroupFilterParameters { data class AuditProof( override val componentGroupIndex: Int, val deserializedClass: Class, - val predicate: Predicate + val predicate: AuditProofPredicate ) : ComponentGroupFilterParameters { override val merkleProofType = MerkleProofType.AUDIT + + sealed interface AuditProofPredicate { + /** + * [Content] include components in a [FilteredTransaction] where the components meet predicate. + * + * @property predicate Filtering function that is applied to each deserialized component with the group + */ + class Content(private val predicate: Predicate) : AuditProofPredicate, Predicate { + override fun test(t: T): Boolean { + return predicate.test(t) + } + } + + /** + * [Index] indexes of components to include in a [FilteredTransaction] + * + * @property indexes component indexes to include. + */ + class Index(private val indexes: List) : AuditProofPredicate, Predicate { + override fun test(t: Int): Boolean { + return t in indexes + } + } + } } /** diff --git a/components/ledger/ledger-common-flow/build.gradle b/components/ledger/ledger-common-flow/build.gradle index c37b01e8741..c5f2c5169f3 100644 --- a/components/ledger/ledger-common-flow/build.gradle +++ b/components/ledger/ledger-common-flow/build.gradle @@ -42,8 +42,6 @@ dependencies { testImplementation project(':testing:layered-property-map-testkit') testImplementation project(':testing:ledger:ledger-common-base-test') testImplementation project(':testing:test-serialization') - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" integrationTestImplementation project(':testing:ledger:ledger-common-base-integration-test') integrationTestImplementation project(':testing:group-policy-test-common') diff --git a/components/ledger/ledger-common-flow/src/main/kotlin/net/corda/ledger/common/flow/impl/transaction/filtered/factory/FilteredTransactionFactoryImpl.kt b/components/ledger/ledger-common-flow/src/main/kotlin/net/corda/ledger/common/flow/impl/transaction/filtered/factory/FilteredTransactionFactoryImpl.kt index 59079479e0a..01063345e80 100644 --- a/components/ledger/ledger-common-flow/src/main/kotlin/net/corda/ledger/common/flow/impl/transaction/filtered/factory/FilteredTransactionFactoryImpl.kt +++ b/components/ledger/ledger-common-flow/src/main/kotlin/net/corda/ledger/common/flow/impl/transaction/filtered/factory/FilteredTransactionFactoryImpl.kt @@ -6,6 +6,7 @@ import net.corda.ledger.common.flow.impl.transaction.filtered.FilteredTransactio import net.corda.ledger.common.flow.transaction.filtered.FilteredComponentGroup import net.corda.ledger.common.flow.transaction.filtered.FilteredTransaction import net.corda.ledger.common.flow.transaction.filtered.factory.ComponentGroupFilterParameters +import net.corda.ledger.common.flow.transaction.filtered.factory.ComponentGroupFilterParameters.AuditProof import net.corda.ledger.common.flow.transaction.filtered.factory.FilteredTransactionFactory import net.corda.sandbox.type.SandboxConstants.CORDA_SYSTEM_SERVICE import net.corda.sandbox.type.UsedByFlow @@ -19,7 +20,6 @@ import org.osgi.service.component.annotations.Component import org.osgi.service.component.annotations.Reference import org.osgi.service.component.annotations.ReferenceScope.PROTOTYPE_REQUIRED import org.osgi.service.component.annotations.ServiceScope.PROTOTYPE -import java.util.function.Predicate @Component( service = [ FilteredTransactionFactory::class, SingletonSerializeAsToken::class, UsedByFlow::class ], @@ -83,20 +83,30 @@ class FilteredTransactionFactoryImpl @Activate constructor( } val merkleProof = when (parameters) { - is ComponentGroupFilterParameters.AuditProof<*> -> { + is AuditProof<*> -> { val skipFiltering = componentGroupIndex == 0 val filteredComponents = componentGroup .mapIndexed { index, component -> index to component } - .filter { (_, component) -> - skipFiltering || (parameters.predicate as Predicate).test( - serializationService.deserialize( - component, - parameters.deserializedClass - ) - ) + .filter { (index, component) -> + if (skipFiltering) { + true + } else { + when (val predicate = parameters.predicate) { + is AuditProof.AuditProofPredicate.Content -> { + (predicate as AuditProof.AuditProofPredicate.Content).test( + serializationService.deserialize( + component, + parameters.deserializedClass + ) + ) + } + is AuditProof.AuditProofPredicate.Index -> { + predicate.test(index) + } + } + } } - wireTransaction.componentMerkleTrees[componentGroupIndex]!!.let { merkleTree -> if (filteredComponents.isEmpty()) { if (componentGroup.isEmpty()) { diff --git a/components/ledger/ledger-common-flow/src/test/kotlin/net/corda/ledger/common/flow/impl/transaction/filtered/FilteredTransactionImplIntegrationTest.kt b/components/ledger/ledger-common-flow/src/test/kotlin/net/corda/ledger/common/flow/impl/transaction/filtered/FilteredTransactionImplIntegrationTest.kt index ead3672a037..daf5f546149 100644 --- a/components/ledger/ledger-common-flow/src/test/kotlin/net/corda/ledger/common/flow/impl/transaction/filtered/FilteredTransactionImplIntegrationTest.kt +++ b/components/ledger/ledger-common-flow/src/test/kotlin/net/corda/ledger/common/flow/impl/transaction/filtered/FilteredTransactionImplIntegrationTest.kt @@ -11,6 +11,7 @@ import net.corda.ledger.common.data.transaction.WireTransaction import net.corda.ledger.common.flow.impl.transaction.filtered.factory.FilteredTransactionFactoryImpl import net.corda.ledger.common.flow.transaction.filtered.FilteredTransaction import net.corda.ledger.common.flow.transaction.filtered.factory.ComponentGroupFilterParameters +import net.corda.ledger.common.flow.transaction.filtered.factory.ComponentGroupFilterParameters.AuditProof.AuditProofPredicate import net.corda.ledger.common.testkit.getWireTransactionExample import net.corda.v5.application.serialization.SerializationService import net.corda.v5.base.annotations.CordaSerializable @@ -91,13 +92,33 @@ class FilteredTransactionImplIntegrationTest { filteredTransaction = filteredTransactionFactory.create( wireTransaction, componentGroupFilterParameters = listOf( - ComponentGroupFilterParameters.AuditProof(0, TransactionMetadataImpl::class.java) { true }, + ComponentGroupFilterParameters.AuditProof( + 0, + TransactionMetadataImpl::class.java, + AuditProofPredicate.Content { true } + ), ComponentGroupFilterParameters.SizeProof(1), - ComponentGroupFilterParameters.AuditProof(2, Any::class.java) { it is MyClassC }, - ComponentGroupFilterParameters.AuditProof(3, Any::class.java) { it is MyClassC }, + ComponentGroupFilterParameters.AuditProof( + 2, + Any::class.java, + AuditProofPredicate.Content { it is MyClassC } + ), + ComponentGroupFilterParameters.AuditProof( + 3, + Any::class.java, + AuditProofPredicate.Content { it is MyClassC } + ), ComponentGroupFilterParameters.SizeProof(4), - ComponentGroupFilterParameters.AuditProof(5, Any::class.java) { it is MyClassC }, - ComponentGroupFilterParameters.AuditProof(6, Any::class.java) { it is MyClassC }, + ComponentGroupFilterParameters.AuditProof( + 5, + Any::class.java, + AuditProofPredicate.Content { it is MyClassC } + ), + ComponentGroupFilterParameters.AuditProof( + 6, + Any::class.java, + AuditProofPredicate.Content { it is MyClassC } + ), ComponentGroupFilterParameters.SizeProof(9), ) ) @@ -124,9 +145,14 @@ class FilteredTransactionImplIntegrationTest { filteredTransaction = filteredTransactionFactory.create( wireTransaction, componentGroupFilterParameters = listOf( - ComponentGroupFilterParameters.AuditProof(0, TransactionMetadataImpl::class.java) { true }, - ComponentGroupFilterParameters.AuditProof(1, Any::class.java) { true }, - ComponentGroupFilterParameters.AuditProof(2, Any::class.java) { true }, + ComponentGroupFilterParameters.AuditProof( + 0, + TransactionMetadataImpl::class.java, + AuditProofPredicate.Content { true } + + ), + ComponentGroupFilterParameters.AuditProof(1, Any::class.java, AuditProofPredicate.Content { true }), + ComponentGroupFilterParameters.AuditProof(2, Any::class.java, AuditProofPredicate.Content { true }), ) ) @@ -163,9 +189,9 @@ class FilteredTransactionImplIntegrationTest { filteredTransaction = filteredTransactionFactory.create( wireTransaction, componentGroupFilterParameters = listOf( - ComponentGroupFilterParameters.AuditProof(0, TransactionMetadataImpl::class.java) { true }, - ComponentGroupFilterParameters.AuditProof(1, Any::class.java) { it is MyClassA || it is MyClassC }, - ComponentGroupFilterParameters.AuditProof(2, Any::class.java) { it is MyClassA || it is MyClassC }, + ComponentGroupFilterParameters.AuditProof(0, TransactionMetadataImpl::class.java, AuditProofPredicate.Content { true }), + ComponentGroupFilterParameters.AuditProof(1, Any::class.java, AuditProofPredicate.Content { it is MyClassA || it is MyClassC }), + ComponentGroupFilterParameters.AuditProof(2, Any::class.java, AuditProofPredicate.Content { it is MyClassA || it is MyClassC }), ) ) @@ -202,8 +228,8 @@ class FilteredTransactionImplIntegrationTest { filteredTransaction = filteredTransactionFactory.create( wireTransaction, componentGroupFilterParameters = listOf( - ComponentGroupFilterParameters.AuditProof(0, TransactionMetadataImpl::class.java) { true }, - ComponentGroupFilterParameters.AuditProof(1, Any::class.java) { it is MyClassA || it is MyClassC }, + ComponentGroupFilterParameters.AuditProof(0, TransactionMetadataImpl::class.java, AuditProofPredicate.Content { true }), + ComponentGroupFilterParameters.AuditProof(1, Any::class.java, AuditProofPredicate.Content { it is MyClassA || it is MyClassC }), ) ) @@ -234,7 +260,7 @@ class FilteredTransactionImplIntegrationTest { filteredTransaction = filteredTransactionFactory.create( wireTransaction, componentGroupFilterParameters = listOf( - ComponentGroupFilterParameters.AuditProof(0, TransactionMetadataImpl::class.java) { true }, + ComponentGroupFilterParameters.AuditProof(0, TransactionMetadataImpl::class.java, AuditProofPredicate.Content { true }), ComponentGroupFilterParameters.SizeProof(1), ComponentGroupFilterParameters.SizeProof(2), ) diff --git a/components/ledger/ledger-common-flow/src/test/kotlin/net/corda/ledger/common/flow/impl/transaction/filtered/factory/FilteredTransactionFactoryImplTest.kt b/components/ledger/ledger-common-flow/src/test/kotlin/net/corda/ledger/common/flow/impl/transaction/filtered/factory/FilteredTransactionFactoryImplTest.kt index e587a585eae..d6167c8518c 100644 --- a/components/ledger/ledger-common-flow/src/test/kotlin/net/corda/ledger/common/flow/impl/transaction/filtered/factory/FilteredTransactionFactoryImplTest.kt +++ b/components/ledger/ledger-common-flow/src/test/kotlin/net/corda/ledger/common/flow/impl/transaction/filtered/factory/FilteredTransactionFactoryImplTest.kt @@ -10,6 +10,7 @@ import net.corda.ledger.common.data.transaction.TransactionMetadataImpl import net.corda.ledger.common.data.transaction.WireTransaction import net.corda.ledger.common.flow.transaction.filtered.FilteredTransaction import net.corda.ledger.common.flow.transaction.filtered.factory.ComponentGroupFilterParameters +import net.corda.ledger.common.flow.transaction.filtered.factory.ComponentGroupFilterParameters.AuditProof.AuditProofPredicate import net.corda.ledger.common.testkit.getWireTransactionExample import net.corda.v5.application.serialization.SerializationService import net.corda.v5.base.annotations.CordaSerializable @@ -66,9 +67,9 @@ class FilteredTransactionFactoryImplTest { filteredTransaction = filteredTransactionFactory.create( wireTransaction, componentGroupFilterParameters = listOf( - ComponentGroupFilterParameters.AuditProof(0, TransactionMetadata::class.java) { true }, - ComponentGroupFilterParameters.AuditProof(1, Any::class.java) { true }, - ComponentGroupFilterParameters.AuditProof(1, Any::class.java) { true }, + ComponentGroupFilterParameters.AuditProof(0, TransactionMetadata::class.java, AuditProofPredicate.Content { true }), + ComponentGroupFilterParameters.AuditProof(1, Any::class.java, AuditProofPredicate.Content { true }), + ComponentGroupFilterParameters.AuditProof(1, Any::class.java, AuditProofPredicate.Content { true }), ) ) }.hasMessageContaining("Unique component group indexes are required when filtering a transaction") @@ -85,8 +86,8 @@ class FilteredTransactionFactoryImplTest { filteredTransaction = filteredTransactionFactory.create( wireTransaction, componentGroupFilterParameters = listOf( - ComponentGroupFilterParameters.AuditProof(0, TransactionMetadata::class.java) { false }, - ComponentGroupFilterParameters.AuditProof(1, Any::class.java) { false }, + ComponentGroupFilterParameters.AuditProof(0, TransactionMetadata::class.java, AuditProofPredicate.Content { false }), + ComponentGroupFilterParameters.AuditProof(1, Any::class.java, AuditProofPredicate.Content { false }), ) ) @@ -108,8 +109,8 @@ class FilteredTransactionFactoryImplTest { filteredTransaction = filteredTransactionFactory.create( wireTransaction, componentGroupFilterParameters = listOf( - ComponentGroupFilterParameters.AuditProof(0, TransactionMetadata::class.java) { true }, - ComponentGroupFilterParameters.AuditProof(1, Any::class.java) { true }, + ComponentGroupFilterParameters.AuditProof(0, TransactionMetadata::class.java, AuditProofPredicate.Content { true }), + ComponentGroupFilterParameters.AuditProof(1, Any::class.java, AuditProofPredicate.Content { true }), ) ) @@ -133,8 +134,16 @@ class FilteredTransactionFactoryImplTest { filteredTransaction = filteredTransactionFactory.create( wireTransaction, componentGroupFilterParameters = listOf( - ComponentGroupFilterParameters.AuditProof(0, TransactionMetadata::class.java) { true }, - ComponentGroupFilterParameters.AuditProof(1, Any::class.java) { it is MyClassA || it is MyClassB }, + ComponentGroupFilterParameters.AuditProof( + 0, + TransactionMetadata::class.java, + AuditProofPredicate.Content { true } + ), + ComponentGroupFilterParameters.AuditProof( + 1, + Any::class.java, + AuditProofPredicate.Content { it is MyClassA || it is MyClassB } + ), ) ) @@ -167,8 +176,8 @@ class FilteredTransactionFactoryImplTest { filteredTransaction = filteredTransactionFactory.create( wireTransaction, componentGroupFilterParameters = listOf( - ComponentGroupFilterParameters.AuditProof(0, TransactionMetadata::class.java) { true }, - ComponentGroupFilterParameters.AuditProof(1, Any::class.java) { false }, + ComponentGroupFilterParameters.AuditProof(0, TransactionMetadata::class.java, AuditProofPredicate.Content { true }), + ComponentGroupFilterParameters.AuditProof(1, Any::class.java, AuditProofPredicate.Content { false }), ) ) @@ -199,7 +208,7 @@ class FilteredTransactionFactoryImplTest { filteredTransaction = filteredTransactionFactory.create( wireTransaction, componentGroupFilterParameters = listOf( - ComponentGroupFilterParameters.AuditProof(0, TransactionMetadata::class.java) { true }, + ComponentGroupFilterParameters.AuditProof(0, TransactionMetadata::class.java, AuditProofPredicate.Content { true }), ComponentGroupFilterParameters.SizeProof(1), ) ) @@ -229,7 +238,7 @@ class FilteredTransactionFactoryImplTest { filteredTransaction = filteredTransactionFactory.create( wireTransaction, componentGroupFilterParameters = listOf( - ComponentGroupFilterParameters.AuditProof(0, TransactionMetadata::class.java) { true }, + ComponentGroupFilterParameters.AuditProof(0, TransactionMetadata::class.java, AuditProofPredicate.Content { true }), ComponentGroupFilterParameters.SizeProof(1), ) ) diff --git a/components/ledger/ledger-consensual-flow/build.gradle b/components/ledger/ledger-consensual-flow/build.gradle index 477a6ab6e42..ec4a6789b6b 100644 --- a/components/ledger/ledger-consensual-flow/build.gradle +++ b/components/ledger/ledger-consensual-flow/build.gradle @@ -36,9 +36,6 @@ dependencies { implementation project(':libs:utilities') implementation project(':libs:virtual-node:sandbox-group-context') - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" testImplementation project(':testing:ledger:ledger-consensual-base-test') testImplementation project(':testing:kryo-serialization-testkit') testImplementation project(':libs:serialization:serialization-amqp') diff --git a/components/ledger/ledger-persistence/build.gradle b/components/ledger/ledger-persistence/build.gradle index 136ab89968a..60753ac1e2a 100644 --- a/components/ledger/ledger-persistence/build.gradle +++ b/components/ledger/ledger-persistence/build.gradle @@ -61,7 +61,6 @@ dependencies { testImplementation project(':testing:db-testkit') testImplementation project(':testing:persistence-testkit') - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation project(":libs:lifecycle:lifecycle-test-impl") testImplementation project(":libs:lifecycle:lifecycle-impl") testImplementation project(":libs:lifecycle:registry") @@ -84,7 +83,7 @@ dependencies { // IMPORTANT: do NOT attempt to use mockito-kotlin in the integration tests. // It's not an OSGi bundle, so you will get errors (despite Intellij appearing to allow you to use it). - integrationTestImplementation("org.mockito:mockito-core:$mockitoVersion") + integrationTestImplementation libs.mockito.core integrationTestImplementation("com.fasterxml.jackson.module:jackson-module-kotlin:$jacksonVersion") integrationTestImplementation project(':libs:db:db-admin-impl') diff --git a/components/ledger/ledger-utxo-flow/build.gradle b/components/ledger/ledger-utxo-flow/build.gradle index 73741dc6328..a1ec25d5503 100644 --- a/components/ledger/ledger-utxo-flow/build.gradle +++ b/components/ledger/ledger-utxo-flow/build.gradle @@ -51,10 +51,6 @@ dependencies { implementation project(':notary-plugins:notary-plugin-common') implementation project(':libs:configuration:configuration-core') - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" - testImplementation project(':testing:test-serialization') testImplementation project(':testing:kryo-serialization-testkit') testImplementation project(':libs:serialization:serialization-internal') diff --git a/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/UtxoLedgerServiceImpl.kt b/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/UtxoLedgerServiceImpl.kt index 0ddc3e11c81..cec3d829a52 100644 --- a/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/UtxoLedgerServiceImpl.kt +++ b/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/UtxoLedgerServiceImpl.kt @@ -80,6 +80,11 @@ class UtxoLedgerServiceImpl @Activate constructor( override fun createTransactionBuilder() = UtxoTransactionBuilderImpl(utxoSignedTransactionFactory, notaryLookup) + @Suspendable + override fun verify(ledgerTransaction: UtxoLedgerTransaction) { + transactionVerificationService.verify(ledgerTransaction) + } + @Suppress("UNCHECKED_CAST") @Suspendable override fun resolve(stateRefs: Iterable): List> { diff --git a/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/UtxoSignedTransactionImpl.kt b/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/UtxoSignedTransactionImpl.kt index 1b90f18e80e..672232b9180 100644 --- a/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/UtxoSignedTransactionImpl.kt +++ b/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/UtxoSignedTransactionImpl.kt @@ -6,11 +6,11 @@ import net.corda.ledger.common.flow.transaction.TransactionSignatureServiceInter import net.corda.ledger.utxo.data.transaction.WrappedUtxoWireTransaction import net.corda.ledger.utxo.data.transaction.verifier.verifyMetadata import net.corda.ledger.utxo.flow.impl.transaction.factory.UtxoLedgerTransactionFactory +import net.corda.ledger.utxo.flow.impl.transaction.verifier.NotarySignatureVerificationServiceInternal import net.corda.v5.application.crypto.DigitalSignatureAndMetadata import net.corda.v5.application.serialization.SerializationService import net.corda.v5.base.annotations.Suspendable import net.corda.v5.base.types.MemberX500Name -import net.corda.v5.crypto.CompositeKey import net.corda.v5.crypto.KeyUtils import net.corda.v5.crypto.SecureHash import net.corda.v5.ledger.common.transaction.TransactionMetadata @@ -28,6 +28,7 @@ import java.util.Objects data class UtxoSignedTransactionImpl( private val serializationService: SerializationService, private val transactionSignatureServiceInternal: TransactionSignatureServiceInternal, + private val notarySignatureVerificationService: NotarySignatureVerificationServiceInternal, private val utxoLedgerTransactionFactory: UtxoLedgerTransactionFactory, override val wireTransaction: WireTransaction, private val signatures: List @@ -91,6 +92,7 @@ data class UtxoSignedTransactionImpl( UtxoSignedTransactionImpl( serializationService, transactionSignatureServiceInternal, + notarySignatureVerificationService, utxoLedgerTransactionFactory, wireTransaction, signatures + signature @@ -107,6 +109,7 @@ data class UtxoSignedTransactionImpl( UtxoSignedTransactionImpl( serializationService, transactionSignatureServiceInternal, + notarySignatureVerificationService, utxoLedgerTransactionFactory, wireTransaction, signatures + newSignatures @@ -119,7 +122,7 @@ data class UtxoSignedTransactionImpl( val keyIdToPublicKey = keyIdToSignatories.getOrPut(keyId.algorithm) { // Prepare keyIds for all public keys related to signatories for the relevant algorithm signatories.flatMap { signatory -> - getKeyOrLeafKeys(signatory).map { + notarySignatureVerificationService.getKeyOrLeafKeys(signatory).map { transactionSignatureServiceInternal.getIdOfPublicKey( it, keyId.algorithm ) to it @@ -179,51 +182,12 @@ data class UtxoSignedTransactionImpl( .toMap() } - private fun getNotaryPublicKeyByKeyId(keyId: SecureHash): PublicKey? { - val keyIdToPublicKey = keyIdToNotaryKeys.getOrPut(keyId.algorithm) { - // Prepare keyIds for all public keys related to the notary for the relevant algorithm - getKeyOrLeafKeys(notaryKey).associateBy { - transactionSignatureServiceInternal.getIdOfPublicKey( - it, - keyId.algorithm - ) - } - } - return keyIdToPublicKey[keyId] - } - override fun verifyAttachedNotarySignature() { - val notaryPublicKeysWithValidSignatures = signatures.mapNotNull { - val publicKey = getNotaryPublicKeyByKeyId(it.by) - if (publicKey != null) { - try { - transactionSignatureServiceInternal.verifySignature(this, it, publicKey) - publicKey - } catch (e: Exception) { - throw TransactionSignatureException( - id, - "Failed to verify signature of ${it.signature} for transaction $id. Message: ${e.message}", - e - ) - } - } else { - null - } - }.toSet() - // If the notary service key (composite key) is provided we need to make sure it contains the key the - // transaction was signed with. This means it was signed with one of the notary VNodes (worker). - if (!KeyUtils.isKeyFulfilledBy(notaryKey, notaryPublicKeysWithValidSignatures)) { - throw TransactionSignatureException( - id, - "Notary signing keys $notaryPublicKeysWithValidSignatures did not fulfil " + - "requirements of notary service key $notaryKey", - null - ) - } + notarySignatureVerificationService.verifyNotarySignatures(wireTransaction, notaryKey, signatures, keyIdToNotaryKeys) } override fun verifyNotarySignature(signature: DigitalSignatureAndMetadata) { - val publicKey = getNotaryPublicKeyByKeyId(signature.by) + val publicKey = notarySignatureVerificationService.getNotaryPublicKeyByKeyId(signature.by, notaryKey, keyIdToNotaryKeys) ?: throw TransactionSignatureException( id, "Notary signature has not been created by the notary for this transaction. " + @@ -263,6 +227,18 @@ data class UtxoSignedTransactionImpl( return utxoLedgerTransactionFactory.create(wireTransaction) } + @Suspendable + override fun toLedgerTransaction( + inputStateAndRefs: List>, + referenceStateAndRefs: List> + ): UtxoLedgerTransaction { + return utxoLedgerTransactionFactory.createWithStateAndRefs( + wireTransaction, + inputStateAndRefs, + referenceStateAndRefs + ) + } + override fun equals(other: Any?): Boolean { if (this === other) return true if (other !is UtxoSignedTransactionImpl) return false @@ -279,11 +255,4 @@ data class UtxoSignedTransactionImpl( override fun toString(): String { return "UtxoSignedTransactionImpl(id=$id, signatures=$signatures, wireTransaction=$wireTransaction)" } - - private fun getKeyOrLeafKeys(publicKey: PublicKey): List { - return when (publicKey) { - is CompositeKey -> publicKey.leafKeys.toList() - else -> listOf(publicKey) - } - } } diff --git a/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/factory/UtxoLedgerTransactionFactory.kt b/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/factory/UtxoLedgerTransactionFactory.kt index d49fb001faa..4582cdab3a3 100644 --- a/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/factory/UtxoLedgerTransactionFactory.kt +++ b/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/factory/UtxoLedgerTransactionFactory.kt @@ -4,6 +4,7 @@ import net.corda.ledger.common.data.transaction.WireTransaction import net.corda.ledger.utxo.data.transaction.UtxoLedgerTransactionInternal import net.corda.ledger.utxo.data.transaction.UtxoVisibleTransactionOutputDto import net.corda.v5.base.annotations.Suspendable +import net.corda.v5.ledger.utxo.StateAndRef import net.corda.v5.ledger.utxo.transaction.UtxoLedgerTransaction /** @@ -27,4 +28,10 @@ interface UtxoLedgerTransactionFactory { inputStateAndRefs: List, referenceStateAndRefs: List ): UtxoLedgerTransactionInternal + + fun createWithStateAndRefs( + wireTransaction: WireTransaction, + inputStateAndRefs: List>, + referenceStateAndRefs: List> + ): UtxoLedgerTransactionInternal } diff --git a/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/factory/impl/UtxoLedgerTransactionFactoryImpl.kt b/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/factory/impl/UtxoLedgerTransactionFactoryImpl.kt index 46c3d15b7a8..677f7ff874e 100644 --- a/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/factory/impl/UtxoLedgerTransactionFactoryImpl.kt +++ b/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/factory/impl/UtxoLedgerTransactionFactoryImpl.kt @@ -16,6 +16,7 @@ import net.corda.v5.application.serialization.SerializationService import net.corda.v5.base.annotations.Suspendable import net.corda.v5.base.exceptions.CordaRuntimeException import net.corda.v5.ledger.utxo.ContractState +import net.corda.v5.ledger.utxo.StateAndRef import net.corda.v5.membership.GroupParameters import net.corda.v5.serialization.SingletonSerializeAsToken import org.osgi.service.component.annotations.Activate @@ -79,6 +80,19 @@ class UtxoLedgerTransactionFactoryImpl @Activate constructor( ) } + override fun createWithStateAndRefs( + wireTransaction: WireTransaction, + inputStateAndRefs: List>, + referenceStateAndRefs: List> + ): UtxoLedgerTransactionInternal { + return UtxoLedgerTransactionImpl( + WrappedUtxoWireTransaction(wireTransaction, serializationService), + inputStateAndRefs, + referenceStateAndRefs, + getGroupParameters(wireTransaction) + ) + } + private fun getGroupParameters(wireTransaction: WireTransaction): GroupParameters { val membershipGroupParametersHashString = requireNotNull((wireTransaction.metadata as TransactionMetadataInternal).getMembershipGroupParametersHash()) { diff --git a/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/factory/impl/UtxoSignedTransactionFactoryImpl.kt b/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/factory/impl/UtxoSignedTransactionFactoryImpl.kt index 89d2a25d949..70c5d36d895 100644 --- a/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/factory/impl/UtxoSignedTransactionFactoryImpl.kt +++ b/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/factory/impl/UtxoSignedTransactionFactoryImpl.kt @@ -20,6 +20,7 @@ import net.corda.ledger.utxo.flow.impl.transaction.UtxoSignedTransactionInternal import net.corda.ledger.utxo.flow.impl.transaction.UtxoTransactionBuilderInternal import net.corda.ledger.utxo.flow.impl.transaction.factory.UtxoLedgerTransactionFactory import net.corda.ledger.utxo.flow.impl.transaction.factory.UtxoSignedTransactionFactory +import net.corda.ledger.utxo.flow.impl.transaction.verifier.NotarySignatureVerificationServiceInternal import net.corda.ledger.utxo.flow.impl.transaction.verifier.UtxoLedgerTransactionVerificationService import net.corda.membership.lib.SignedGroupParameters import net.corda.sandbox.type.UsedByFlow @@ -65,7 +66,9 @@ class UtxoSignedTransactionFactoryImpl @Activate constructor( @Reference(service = GroupParametersLookupInternal::class) private val groupParametersLookup: GroupParametersLookupInternal, @Reference(service = SignedGroupParametersVerifier::class) - private val signedGroupParametersVerifier: SignedGroupParametersVerifier + private val signedGroupParametersVerifier: SignedGroupParametersVerifier, + @Reference(service = NotarySignatureVerificationServiceInternal::class) + private val notarySignatureVerificationService: NotarySignatureVerificationServiceInternal ) : UtxoSignedTransactionFactory, UsedByFlow, SingletonSerializeAsToken { @Suspendable @@ -92,6 +95,7 @@ class UtxoSignedTransactionFactoryImpl @Activate constructor( return UtxoSignedTransactionImpl( serializationService, transactionSignatureService, + notarySignatureVerificationService, utxoLedgerTransactionFactory, wireTransaction, signaturesWithMetadata @@ -104,6 +108,7 @@ class UtxoSignedTransactionFactoryImpl @Activate constructor( ): UtxoSignedTransactionInternal = UtxoSignedTransactionImpl( serializationService, transactionSignatureService, + notarySignatureVerificationService, utxoLedgerTransactionFactory, wireTransaction, signaturesWithMetaData diff --git a/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/filtered/UtxoFilteredTransactionBuilderImpl.kt b/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/filtered/UtxoFilteredTransactionBuilderImpl.kt index b320068fdda..5e6ea6b8a1a 100644 --- a/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/filtered/UtxoFilteredTransactionBuilderImpl.kt +++ b/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/filtered/UtxoFilteredTransactionBuilderImpl.kt @@ -1,6 +1,7 @@ package net.corda.ledger.utxo.flow.impl.transaction.filtered import net.corda.ledger.common.flow.transaction.filtered.factory.ComponentGroupFilterParameters +import net.corda.ledger.common.flow.transaction.filtered.factory.ComponentGroupFilterParameters.AuditProof.AuditProofPredicate import net.corda.ledger.utxo.data.transaction.UtxoComponentGroup import net.corda.ledger.utxo.flow.impl.transaction.UtxoSignedTransactionInternal import net.corda.ledger.utxo.flow.impl.transaction.filtered.factory.UtxoFilteredTransactionFactory @@ -52,7 +53,7 @@ data class UtxoFilteredTransactionBuilderImpl( signatories = ComponentGroupFilterParameters.AuditProof( UtxoComponentGroup.SIGNATORIES.ordinal, PublicKey::class.java, - predicate + AuditProofPredicate.Content(predicate) ) ) } @@ -73,7 +74,7 @@ data class UtxoFilteredTransactionBuilderImpl( inputStates = ComponentGroupFilterParameters.AuditProof( UtxoComponentGroup.INPUTS.ordinal, StateRef::class.java, - predicate + AuditProofPredicate.Content(predicate) ) ) } @@ -94,7 +95,7 @@ data class UtxoFilteredTransactionBuilderImpl( referenceStates = ComponentGroupFilterParameters.AuditProof( UtxoComponentGroup.REFERENCES.ordinal, StateRef::class.java, - predicate + AuditProofPredicate.Content(predicate) ) ) } @@ -115,7 +116,18 @@ data class UtxoFilteredTransactionBuilderImpl( outputStates = ComponentGroupFilterParameters.AuditProof( UtxoComponentGroup.OUTPUTS.ordinal, ContractState::class.java, - predicate + AuditProofPredicate.Content(predicate) + ) + ) + } + + @Suspendable + override fun withOutputStates(indexes: List): UtxoFilteredTransactionBuilderInternal { + return copy( + outputStates = ComponentGroupFilterParameters.AuditProof( + UtxoComponentGroup.OUTPUTS.ordinal, + ContractState::class.java, + AuditProofPredicate.Index(indexes) ) ) } @@ -136,7 +148,7 @@ data class UtxoFilteredTransactionBuilderImpl( commands = ComponentGroupFilterParameters.AuditProof( UtxoComponentGroup.COMMANDS.ordinal, Command::class.java, - predicate + AuditProofPredicate.Content(predicate) ) ) } diff --git a/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/filtered/factory/UtxoFilteredTransactionFactoryImpl.kt b/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/filtered/factory/UtxoFilteredTransactionFactoryImpl.kt index 35d237b8b53..69a29ad0a0d 100644 --- a/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/filtered/factory/UtxoFilteredTransactionFactoryImpl.kt +++ b/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/filtered/factory/UtxoFilteredTransactionFactoryImpl.kt @@ -1,6 +1,7 @@ package net.corda.ledger.utxo.flow.impl.transaction.filtered.factory import net.corda.ledger.common.flow.transaction.filtered.factory.ComponentGroupFilterParameters +import net.corda.ledger.common.flow.transaction.filtered.factory.ComponentGroupFilterParameters.AuditProof.AuditProofPredicate import net.corda.ledger.common.flow.transaction.filtered.factory.FilteredTransactionFactory import net.corda.ledger.utxo.data.transaction.UtxoComponentGroup import net.corda.ledger.utxo.data.transaction.UtxoComponentGroup.METADATA @@ -41,10 +42,14 @@ class UtxoFilteredTransactionFactoryImpl @Activate constructor( filteredTransactionBuilder: UtxoFilteredTransactionBuilderInternal ): UtxoFilteredTransaction { val notaryAndTimeWindow = if (filteredTransactionBuilder.notary || filteredTransactionBuilder.timeWindow) { - ComponentGroupFilterParameters.AuditProof(NOTARY.ordinal, Any::class.java) { - filteredTransactionBuilder.notary && (it is MemberX500Name || it is PublicKey) || // notary components - filteredTransactionBuilder.timeWindow && it is TimeWindow // time window - } + ComponentGroupFilterParameters.AuditProof( + NOTARY.ordinal, + Any::class.java, + AuditProofPredicate.Content { + filteredTransactionBuilder.notary && (it is MemberX500Name || it is PublicKey) || // notary components + filteredTransactionBuilder.timeWindow && it is TimeWindow // time window + } + ) } else { null } @@ -53,7 +58,11 @@ class UtxoFilteredTransactionFactoryImpl @Activate constructor( filteredTransactionFactory.create( signedTransaction.wireTransaction, listOfNotNull( - ComponentGroupFilterParameters.AuditProof(METADATA.ordinal, TransactionMetadata::class.java) { true }, + ComponentGroupFilterParameters.AuditProof( + METADATA.ordinal, + TransactionMetadata::class.java, + AuditProofPredicate.Content { true } + ), notaryAndTimeWindow, filteredTransactionBuilder.signatories, filteredTransactionBuilder.inputStates, @@ -61,15 +70,17 @@ class UtxoFilteredTransactionFactoryImpl @Activate constructor( (filteredTransactionBuilder.outputStates as? ComponentGroupFilterParameters.AuditProof<*>)?.let { _ -> ComponentGroupFilterParameters.AuditProof( UtxoComponentGroup.OUTPUTS_INFO.ordinal, - UtxoOutputInfoComponent::class.java - ) { true } + UtxoOutputInfoComponent::class.java, + AuditProofPredicate.Content { true } + ) }, filteredTransactionBuilder.outputStates, (filteredTransactionBuilder.commands as? ComponentGroupFilterParameters.AuditProof<*>)?.let { _ -> ComponentGroupFilterParameters.AuditProof( UtxoComponentGroup.COMMANDS_INFO.ordinal, - List::class.java - ) { true } + List::class.java, + AuditProofPredicate.Content { true } + ) }, filteredTransactionBuilder.commands ) diff --git a/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/serializer/amqp/UtxoSignedTransactionSerializer.kt b/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/serializer/amqp/UtxoSignedTransactionSerializer.kt index 546b693a1ec..c6a52645a80 100644 --- a/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/serializer/amqp/UtxoSignedTransactionSerializer.kt +++ b/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/serializer/amqp/UtxoSignedTransactionSerializer.kt @@ -5,6 +5,7 @@ import net.corda.ledger.common.flow.transaction.TransactionSignatureServiceInter import net.corda.ledger.utxo.flow.impl.transaction.UtxoSignedTransactionImpl import net.corda.ledger.utxo.flow.impl.transaction.UtxoSignedTransactionInternal import net.corda.ledger.utxo.flow.impl.transaction.factory.UtxoLedgerTransactionFactory +import net.corda.ledger.utxo.flow.impl.transaction.verifier.NotarySignatureVerificationServiceInternal import net.corda.sandbox.type.SandboxConstants.CORDA_UNINJECTABLE_SERVICE import net.corda.sandbox.type.UsedByFlow import net.corda.serialization.BaseProxySerializer @@ -28,7 +29,9 @@ class UtxoSignedTransactionSerializer @Activate constructor( @Reference(service = TransactionSignatureServiceInternal::class) private val transactionSignatureService: TransactionSignatureServiceInternal, @Reference(service = UtxoLedgerTransactionFactory::class) - private val utxoLedgerTransactionFactory: UtxoLedgerTransactionFactory + private val utxoLedgerTransactionFactory: UtxoLedgerTransactionFactory, + @Reference(service = NotarySignatureVerificationServiceInternal::class) + private val notarySignatureVerificationService: NotarySignatureVerificationServiceInternal ) : BaseProxySerializer(), UsedByFlow { private companion object { private const val VERSION_1 = 1 @@ -58,6 +61,7 @@ class UtxoSignedTransactionSerializer @Activate constructor( UtxoSignedTransactionImpl( serializationService, transactionSignatureService, + notarySignatureVerificationService, utxoLedgerTransactionFactory, proxy.wireTransaction, proxy.signatures diff --git a/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/serializer/kryo/UtxoSignedTransactionKryoSerializer.kt b/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/serializer/kryo/UtxoSignedTransactionKryoSerializer.kt index 6f597229a4d..8c6bc5aaa18 100644 --- a/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/serializer/kryo/UtxoSignedTransactionKryoSerializer.kt +++ b/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/serializer/kryo/UtxoSignedTransactionKryoSerializer.kt @@ -5,6 +5,7 @@ import net.corda.ledger.common.flow.transaction.TransactionSignatureServiceInter import net.corda.ledger.utxo.flow.impl.transaction.UtxoSignedTransactionImpl import net.corda.ledger.utxo.flow.impl.transaction.UtxoSignedTransactionInternal import net.corda.ledger.utxo.flow.impl.transaction.factory.UtxoLedgerTransactionFactory +import net.corda.ledger.utxo.flow.impl.transaction.verifier.NotarySignatureVerificationServiceInternal import net.corda.sandbox.type.SandboxConstants.CORDA_UNINJECTABLE_SERVICE import net.corda.sandbox.type.UsedByFlow import net.corda.serialization.checkpoint.CheckpointInput @@ -28,7 +29,9 @@ class UtxoSignedTransactionKryoSerializer @Activate constructor( @Reference(service = TransactionSignatureServiceInternal::class) private val transactionSignatureService: TransactionSignatureServiceInternal, @Reference(service = UtxoLedgerTransactionFactory::class) - private val utxoLedgerTransactionFactory: UtxoLedgerTransactionFactory + private val utxoLedgerTransactionFactory: UtxoLedgerTransactionFactory, + @Reference(service = NotarySignatureVerificationServiceInternal::class) + private val notarySignatureVerificationService: NotarySignatureVerificationServiceInternal ) : CheckpointInternalCustomSerializer, UsedByFlow { override val type: Class get() = UtxoSignedTransactionInternal::class.java @@ -45,6 +48,7 @@ class UtxoSignedTransactionKryoSerializer @Activate constructor( return UtxoSignedTransactionImpl( serialisationService, transactionSignatureService, + notarySignatureVerificationService, utxoLedgerTransactionFactory, wireTransaction, signatures diff --git a/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/verifier/NotarySignatureVerificationServiceImpl.kt b/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/verifier/NotarySignatureVerificationServiceImpl.kt new file mode 100644 index 00000000000..fa40fb94d0b --- /dev/null +++ b/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/verifier/NotarySignatureVerificationServiceImpl.kt @@ -0,0 +1,87 @@ +package net.corda.ledger.utxo.flow.impl.transaction.verifier + +import net.corda.ledger.common.flow.transaction.TransactionSignatureServiceInternal +import net.corda.sandbox.type.UsedByFlow +import net.corda.v5.application.crypto.DigitalSignatureAndMetadata +import net.corda.v5.crypto.CompositeKey +import net.corda.v5.crypto.KeyUtils +import net.corda.v5.crypto.SecureHash +import net.corda.v5.ledger.common.transaction.TransactionSignatureException +import net.corda.v5.ledger.common.transaction.TransactionSignatureService +import net.corda.v5.ledger.common.transaction.TransactionWithMetadata +import net.corda.v5.ledger.utxo.NotarySignatureVerificationService +import net.corda.v5.serialization.SingletonSerializeAsToken +import org.osgi.service.component.annotations.Activate +import org.osgi.service.component.annotations.Component +import org.osgi.service.component.annotations.Reference +import org.osgi.service.component.annotations.ServiceScope.PROTOTYPE +import java.security.PublicKey + +@Component( + service = [NotarySignatureVerificationService::class, NotarySignatureVerificationServiceInternal::class, UsedByFlow::class], + scope = PROTOTYPE +) +class NotarySignatureVerificationServiceImpl @Activate constructor( + @Reference(service = TransactionSignatureService::class) + private val transactionSignatureService: TransactionSignatureService +) : NotarySignatureVerificationService, NotarySignatureVerificationServiceInternal, UsedByFlow, SingletonSerializeAsToken { + override fun verifyNotarySignatures( + transaction: TransactionWithMetadata, + notaryKey: PublicKey, + signatures: List, + keyIdToNotaryKeys: MutableMap> + ) { + val notaryPublicKeysWithValidSignatures = signatures.mapNotNull { + val publicKey = + getNotaryPublicKeyByKeyId(it.by, notaryKey, keyIdToNotaryKeys) + if (publicKey != null) { + try { + (transactionSignatureService as TransactionSignatureServiceInternal).verifySignature(transaction, it, publicKey) + publicKey + } catch (e: Exception) { + throw TransactionSignatureException( + transaction.id, + "Failed to verify signature of ${it.signature} for transaction $transaction. Message: ${e.message}", + e + ) + } + } else { + null + } + }.toSet() + // If the notary service key (composite key) is provided we need to make sure it contains the key the + // transaction was signed with. This means it was signed with one of the notary VNodes (worker). + if (!KeyUtils.isKeyFulfilledBy(notaryKey, notaryPublicKeysWithValidSignatures)) { + throw TransactionSignatureException( + transaction.id, + "Notary signing keys $notaryPublicKeysWithValidSignatures did not fulfil " + + "requirements of notary service key $notaryKey", + null + ) + } + } + + override fun getNotaryPublicKeyByKeyId( + keyId: SecureHash, + notaryKey: PublicKey, + keyIdToNotaryKeys: MutableMap> + ): PublicKey? { + val keyIdToPublicKey = keyIdToNotaryKeys.getOrPut(keyId.algorithm) { + // Prepare keyIds for all public keys related to the notary for the relevant algorithm + getKeyOrLeafKeys(notaryKey).associateBy { + (transactionSignatureService as TransactionSignatureServiceInternal).getIdOfPublicKey( + it, + keyId.algorithm + ) + } + } + return keyIdToPublicKey[keyId] + } + + override fun getKeyOrLeafKeys(publicKey: PublicKey): List { + return when (publicKey) { + is CompositeKey -> publicKey.leafKeys.toList() + else -> listOf(publicKey) + } + } +} diff --git a/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/verifier/NotarySignatureVerificationServiceInternal.kt b/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/verifier/NotarySignatureVerificationServiceInternal.kt new file mode 100644 index 00000000000..df7d8d5ae94 --- /dev/null +++ b/components/ledger/ledger-utxo-flow/src/main/kotlin/net/corda/ledger/utxo/flow/impl/transaction/verifier/NotarySignatureVerificationServiceInternal.kt @@ -0,0 +1,15 @@ +package net.corda.ledger.utxo.flow.impl.transaction.verifier + +import net.corda.v5.crypto.SecureHash +import net.corda.v5.ledger.utxo.NotarySignatureVerificationService +import java.security.PublicKey + +interface NotarySignatureVerificationServiceInternal : NotarySignatureVerificationService { + fun getNotaryPublicKeyByKeyId( + keyId: SecureHash, + notaryKey: PublicKey, + keyIdToNotaryKeys: MutableMap> + ): PublicKey? + + fun getKeyOrLeafKeys(publicKey: PublicKey): List +} diff --git a/components/ledger/ledger-utxo-flow/src/test/kotlin/net/corda/ledger/utxo/flow/impl/persistence/UtxoLedgerPersistenceServiceImplTest.kt b/components/ledger/ledger-utxo-flow/src/test/kotlin/net/corda/ledger/utxo/flow/impl/persistence/UtxoLedgerPersistenceServiceImplTest.kt index 97ed144d4af..1615dffc1b4 100644 --- a/components/ledger/ledger-utxo-flow/src/test/kotlin/net/corda/ledger/utxo/flow/impl/persistence/UtxoLedgerPersistenceServiceImplTest.kt +++ b/components/ledger/ledger-utxo-flow/src/test/kotlin/net/corda/ledger/utxo/flow/impl/persistence/UtxoLedgerPersistenceServiceImplTest.kt @@ -26,6 +26,7 @@ import net.corda.ledger.utxo.flow.impl.transaction.UtxoSignedTransactionImpl import net.corda.ledger.utxo.flow.impl.transaction.UtxoSignedTransactionInternal import net.corda.ledger.utxo.flow.impl.transaction.factory.UtxoLedgerTransactionFactory import net.corda.ledger.utxo.flow.impl.transaction.factory.UtxoSignedTransactionFactory +import net.corda.ledger.utxo.flow.impl.transaction.verifier.NotarySignatureVerificationServiceInternal import net.corda.sandboxgroupcontext.CurrentSandboxGroupContext import net.corda.sandboxgroupcontext.SandboxGroupContext import net.corda.sandboxgroupcontext.VirtualNodeContext @@ -57,6 +58,7 @@ class UtxoLedgerPersistenceServiceImplTest { private val externalEventExecutor = mock() private val serializationService = mock() private val transactionSignatureService = mock() + private val notarySignatureVerificationService = mock() private val utxoSignedTransactionFactory = mock() private val utxoLedgerTransactionFactory = mock() private val sandbox = mock() @@ -174,6 +176,7 @@ class UtxoLedgerPersistenceServiceImplTest { val expectedObj = UtxoSignedTransactionImpl( serializationService, transactionSignatureService, + notarySignatureVerificationService, mock(), wireTransaction, signatures diff --git a/components/ledger/ledger-utxo-flow/src/test/kotlin/net/corda/ledger/utxo/flow/impl/transaction/UtxoSignedTransactionImplTest.kt b/components/ledger/ledger-utxo-flow/src/test/kotlin/net/corda/ledger/utxo/flow/impl/transaction/UtxoSignedTransactionImplTest.kt index b04ddc7c220..2b5f8e4c78f 100644 --- a/components/ledger/ledger-utxo-flow/src/test/kotlin/net/corda/ledger/utxo/flow/impl/transaction/UtxoSignedTransactionImplTest.kt +++ b/components/ledger/ledger-utxo-flow/src/test/kotlin/net/corda/ledger/utxo/flow/impl/transaction/UtxoSignedTransactionImplTest.kt @@ -9,12 +9,9 @@ import net.corda.ledger.utxo.testkit.getUtxoStateExample import net.corda.ledger.utxo.testkit.utxoTimeWindowExample import net.corda.v5.base.exceptions.CordaRuntimeException import net.corda.v5.base.types.MemberX500Name -import net.corda.v5.ledger.common.transaction.TransactionSignatureException import net.corda.v5.membership.NotaryInfo -import org.assertj.core.api.Assertions import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test -import org.junit.jupiter.api.assertDoesNotThrow import org.junit.jupiter.api.assertThrows import org.mockito.kotlin.mock import org.mockito.kotlin.whenever @@ -51,23 +48,6 @@ internal class UtxoSignedTransactionImplTest : UtxoLedgerTest() { .toSignedTransaction() as UtxoSignedTransactionInternal } - @Test - fun `verifyAttachedNotarySignature throws on unnotarized transaction`() { - Assertions.assertThatThrownBy { signedTransaction.verifyAttachedNotarySignature() }.isInstanceOf( - TransactionSignatureException::class.java - ) - .hasMessageContaining("did not fulfil requirements of notary service key") - } - - @Test - fun `verifyAttachedNotarySignature does not throw on notarized transaction`() { - val sig = getSignatureWithMetadataExample(notaryNode1PublicKey) - signedTransaction = signedTransaction.addSignature(sig) - assertDoesNotThrow { - signedTransaction.verifyAttachedNotarySignature() - } - } - @Test fun `receiving notary signature with key id not matching notary key throws`() { val notExistingNotaryKey = kpg.generateKeyPair().public diff --git a/components/ledger/ledger-utxo-flow/src/test/kotlin/net/corda/ledger/utxo/flow/impl/transaction/filtered/UtxoFilteredTransactionBuilderImplTest.kt b/components/ledger/ledger-utxo-flow/src/test/kotlin/net/corda/ledger/utxo/flow/impl/transaction/filtered/UtxoFilteredTransactionBuilderImplTest.kt index d9ccf23562c..4e193793d6f 100644 --- a/components/ledger/ledger-utxo-flow/src/test/kotlin/net/corda/ledger/utxo/flow/impl/transaction/filtered/UtxoFilteredTransactionBuilderImplTest.kt +++ b/components/ledger/ledger-utxo-flow/src/test/kotlin/net/corda/ledger/utxo/flow/impl/transaction/filtered/UtxoFilteredTransactionBuilderImplTest.kt @@ -1,6 +1,8 @@ package net.corda.ledger.utxo.flow.impl.transaction.filtered -import net.corda.ledger.common.flow.transaction.filtered.factory.ComponentGroupFilterParameters +import net.corda.ledger.common.flow.transaction.filtered.factory.ComponentGroupFilterParameters.AuditProof +import net.corda.ledger.common.flow.transaction.filtered.factory.ComponentGroupFilterParameters.AuditProof.AuditProofPredicate +import net.corda.ledger.common.flow.transaction.filtered.factory.ComponentGroupFilterParameters.SizeProof import net.corda.ledger.utxo.data.transaction.UtxoComponentGroup import net.corda.v5.ledger.utxo.Command import net.corda.v5.ledger.utxo.ContractState @@ -28,126 +30,157 @@ class UtxoFilteredTransactionBuilderImplTest { @Test fun withSignatoriesSize() { val componentGroupFilterParameters = utxoFilteredTransactionBuilder.withSignatoriesSize().signatories - assertThat(componentGroupFilterParameters).isInstanceOf(ComponentGroupFilterParameters.SizeProof::class.java) + assertThat(componentGroupFilterParameters).isInstanceOf(SizeProof::class.java) assertThat((componentGroupFilterParameters!!).componentGroupIndex).isEqualTo(UtxoComponentGroup.SIGNATORIES.ordinal) } @Test fun withSignatories() { val componentGroupFilterParameters = utxoFilteredTransactionBuilder.withSignatories().signatories - assertThat(componentGroupFilterParameters).isInstanceOf(ComponentGroupFilterParameters.AuditProof::class.java) + assertThat(componentGroupFilterParameters).isInstanceOf(AuditProof::class.java) assertThat((componentGroupFilterParameters!!).componentGroupIndex).isEqualTo(UtxoComponentGroup.SIGNATORIES.ordinal) - assertThat((componentGroupFilterParameters as ComponentGroupFilterParameters.AuditProof).predicate.test(mock())) - .isEqualTo(true) + assertThat( + ((componentGroupFilterParameters as AuditProof).predicate as AuditProofPredicate.Content) + .test(mock()) + ).isEqualTo(true) } @Test fun `withSignatories predicate`() { val componentGroupFilterParameters = utxoFilteredTransactionBuilder.withSignatories { false }.signatories - assertThat(componentGroupFilterParameters).isInstanceOf(ComponentGroupFilterParameters.AuditProof::class.java) + assertThat(componentGroupFilterParameters).isInstanceOf(AuditProof::class.java) assertThat((componentGroupFilterParameters!!).componentGroupIndex).isEqualTo(UtxoComponentGroup.SIGNATORIES.ordinal) - assertThat((componentGroupFilterParameters as ComponentGroupFilterParameters.AuditProof).predicate.test(mock())) - .isEqualTo(false) + assertThat( + ((componentGroupFilterParameters as AuditProof).predicate as AuditProofPredicate.Content) + .test(mock()) + ).isEqualTo(false) } @Test fun withInputStatesSize() { val componentGroupFilterParameters = utxoFilteredTransactionBuilder.withInputStatesSize().inputStates - assertThat(componentGroupFilterParameters).isInstanceOf(ComponentGroupFilterParameters.SizeProof::class.java) + assertThat(componentGroupFilterParameters).isInstanceOf(SizeProof::class.java) assertThat((componentGroupFilterParameters!!).componentGroupIndex).isEqualTo(UtxoComponentGroup.INPUTS.ordinal) } @Test fun withInputStates() { val componentGroupFilterParameters = utxoFilteredTransactionBuilder.withInputStates().inputStates - assertThat(componentGroupFilterParameters).isInstanceOf(ComponentGroupFilterParameters.AuditProof::class.java) + assertThat(componentGroupFilterParameters).isInstanceOf(AuditProof::class.java) assertThat((componentGroupFilterParameters!!).componentGroupIndex).isEqualTo(UtxoComponentGroup.INPUTS.ordinal) - assertThat((componentGroupFilterParameters as ComponentGroupFilterParameters.AuditProof).predicate.test(mock())) - .isEqualTo(true) + assertThat( + ((componentGroupFilterParameters as AuditProof).predicate as AuditProofPredicate.Content) + .test(mock()) + ).isEqualTo(true) } @Test fun `withInputStates predicate`() { val componentGroupFilterParameters = utxoFilteredTransactionBuilder.withInputStates { false }.inputStates - assertThat(componentGroupFilterParameters).isInstanceOf(ComponentGroupFilterParameters.AuditProof::class.java) + assertThat(componentGroupFilterParameters).isInstanceOf(AuditProof::class.java) assertThat((componentGroupFilterParameters!!).componentGroupIndex).isEqualTo(UtxoComponentGroup.INPUTS.ordinal) - assertThat((componentGroupFilterParameters as ComponentGroupFilterParameters.AuditProof).predicate.test(mock())) - .isEqualTo(false) + assertThat( + ((componentGroupFilterParameters as AuditProof).predicate as AuditProofPredicate.Content) + .test(mock()) + ).isEqualTo(false) } @Test fun withReferenceStatesSize() { val componentGroupFilterParameters = utxoFilteredTransactionBuilder.withReferenceStatesSize().referenceStates - assertThat(componentGroupFilterParameters).isInstanceOf(ComponentGroupFilterParameters.SizeProof::class.java) + assertThat(componentGroupFilterParameters).isInstanceOf(SizeProof::class.java) assertThat((componentGroupFilterParameters!!).componentGroupIndex).isEqualTo(UtxoComponentGroup.REFERENCES.ordinal) } @Test fun withReferenceStates() { val componentGroupFilterParameters = utxoFilteredTransactionBuilder.withReferenceStates().referenceStates - assertThat(componentGroupFilterParameters).isInstanceOf(ComponentGroupFilterParameters.AuditProof::class.java) + assertThat(componentGroupFilterParameters).isInstanceOf(AuditProof::class.java) assertThat((componentGroupFilterParameters!!).componentGroupIndex).isEqualTo(UtxoComponentGroup.REFERENCES.ordinal) - assertThat((componentGroupFilterParameters as ComponentGroupFilterParameters.AuditProof).predicate.test(mock())) - .isEqualTo(true) + assertThat( + ((componentGroupFilterParameters as AuditProof).predicate as AuditProofPredicate.Content) + .test(mock()) + ).isEqualTo(true) } @Test fun `withReferenceStates predicate`() { val componentGroupFilterParameters = utxoFilteredTransactionBuilder.withReferenceStates { false }.referenceStates - assertThat(componentGroupFilterParameters).isInstanceOf(ComponentGroupFilterParameters.AuditProof::class.java) + assertThat(componentGroupFilterParameters).isInstanceOf(AuditProof::class.java) assertThat((componentGroupFilterParameters!!).componentGroupIndex).isEqualTo(UtxoComponentGroup.REFERENCES.ordinal) - assertThat((componentGroupFilterParameters as ComponentGroupFilterParameters.AuditProof).predicate.test(mock())) - .isEqualTo(false) + assertThat( + ((componentGroupFilterParameters as AuditProof).predicate as AuditProofPredicate.Content) + .test(mock()) + ).isEqualTo(false) } @Test fun withOutputStatesSize() { val componentGroupFilterParameters = utxoFilteredTransactionBuilder.withOutputStatesSize().outputStates - assertThat(componentGroupFilterParameters).isInstanceOf(ComponentGroupFilterParameters.SizeProof::class.java) + assertThat(componentGroupFilterParameters).isInstanceOf(SizeProof::class.java) assertThat((componentGroupFilterParameters!!).componentGroupIndex).isEqualTo(UtxoComponentGroup.OUTPUTS.ordinal) } @Test fun withOutputStates() { val componentGroupFilterParameters = utxoFilteredTransactionBuilder.withOutputStates().outputStates - assertThat(componentGroupFilterParameters).isInstanceOf(ComponentGroupFilterParameters.AuditProof::class.java) + assertThat(componentGroupFilterParameters).isInstanceOf(AuditProof::class.java) assertThat((componentGroupFilterParameters!!).componentGroupIndex).isEqualTo(UtxoComponentGroup.OUTPUTS.ordinal) - assertThat((componentGroupFilterParameters as ComponentGroupFilterParameters.AuditProof).predicate.test(mock())) - .isEqualTo(true) + assertThat( + ((componentGroupFilterParameters as AuditProof).predicate as AuditProofPredicate.Content) + .test(mock()) + ).isEqualTo(true) } @Test fun `withOutputStates predicate`() { val componentGroupFilterParameters = utxoFilteredTransactionBuilder.withOutputStates { false }.outputStates - assertThat(componentGroupFilterParameters).isInstanceOf(ComponentGroupFilterParameters.AuditProof::class.java) + assertThat(componentGroupFilterParameters).isInstanceOf(AuditProof::class.java) assertThat((componentGroupFilterParameters!!).componentGroupIndex).isEqualTo(UtxoComponentGroup.OUTPUTS.ordinal) - assertThat((componentGroupFilterParameters as ComponentGroupFilterParameters.AuditProof).predicate.test(mock())) - .isEqualTo(false) + assertThat( + ((componentGroupFilterParameters as AuditProof).predicate as AuditProofPredicate.Content) + .test(mock()) + ).isEqualTo(false) + } + + @Test + fun `withOutputStates indexes`() { + val componentGroupFilterParameters = utxoFilteredTransactionBuilder.withOutputStates(listOf(0)).outputStates + assertThat(componentGroupFilterParameters).isInstanceOf(AuditProof::class.java) + assertThat((componentGroupFilterParameters!!).componentGroupIndex).isEqualTo(UtxoComponentGroup.OUTPUTS.ordinal) + assertThat( + ((componentGroupFilterParameters as AuditProof).predicate as AuditProofPredicate.Index) + .test(0) + ).isEqualTo(true) } @Test fun withCommandsSize() { val componentGroupFilterParameters = utxoFilteredTransactionBuilder.withCommandsSize().commands - assertThat(componentGroupFilterParameters).isInstanceOf(ComponentGroupFilterParameters.SizeProof::class.java) + assertThat(componentGroupFilterParameters).isInstanceOf(SizeProof::class.java) assertThat((componentGroupFilterParameters!!).componentGroupIndex).isEqualTo(UtxoComponentGroup.COMMANDS.ordinal) } @Test fun withCommands() { val componentGroupFilterParameters = utxoFilteredTransactionBuilder.withCommands().commands - assertThat(componentGroupFilterParameters).isInstanceOf(ComponentGroupFilterParameters.AuditProof::class.java) + assertThat(componentGroupFilterParameters).isInstanceOf(AuditProof::class.java) assertThat((componentGroupFilterParameters!!).componentGroupIndex).isEqualTo(UtxoComponentGroup.COMMANDS.ordinal) - assertThat((componentGroupFilterParameters as ComponentGroupFilterParameters.AuditProof).predicate.test(mock())) - .isEqualTo(true) + assertThat( + ((componentGroupFilterParameters as AuditProof).predicate as AuditProofPredicate.Content) + .test(mock()) + ).isEqualTo(true) } @Test fun `withCommands predicate`() { val componentGroupFilterParameters = utxoFilteredTransactionBuilder.withCommands { false }.commands - assertThat(componentGroupFilterParameters).isInstanceOf(ComponentGroupFilterParameters.AuditProof::class.java) + assertThat(componentGroupFilterParameters).isInstanceOf(AuditProof::class.java) assertThat((componentGroupFilterParameters!!).componentGroupIndex).isEqualTo(UtxoComponentGroup.COMMANDS.ordinal) - assertThat((componentGroupFilterParameters as ComponentGroupFilterParameters.AuditProof).predicate.test(mock())) - .isEqualTo(false) + assertThat( + ((componentGroupFilterParameters as AuditProof).predicate as AuditProofPredicate.Content) + .test(mock()) + ).isEqualTo(false) } @Test @@ -173,11 +206,11 @@ class UtxoFilteredTransactionBuilderImplTest { .withCommands() as UtxoFilteredTransactionBuilderInternal assertThat(builder.notary).isTrue assertThat(builder.timeWindow).isTrue - assertThat(builder.signatories).isInstanceOf(ComponentGroupFilterParameters.SizeProof::class.java) - assertThat(builder.inputStates).isInstanceOf(ComponentGroupFilterParameters.AuditProof::class.java) - assertThat(builder.referenceStates).isInstanceOf(ComponentGroupFilterParameters.SizeProof::class.java) - assertThat(builder.outputStates).isInstanceOf(ComponentGroupFilterParameters.SizeProof::class.java) - assertThat(builder.commands).isInstanceOf(ComponentGroupFilterParameters.AuditProof::class.java) + assertThat(builder.signatories).isInstanceOf(SizeProof::class.java) + assertThat(builder.inputStates).isInstanceOf(AuditProof::class.java) + assertThat(builder.referenceStates).isInstanceOf(SizeProof::class.java) + assertThat(builder.outputStates).isInstanceOf(SizeProof::class.java) + assertThat(builder.commands).isInstanceOf(AuditProof::class.java) } @Test @@ -189,9 +222,9 @@ class UtxoFilteredTransactionBuilderImplTest { assertThat(builder.notary).isFalse assertThat(builder.timeWindow).isFalse assertThat(builder.signatories).isNull() - assertThat(builder.inputStates).isInstanceOf(ComponentGroupFilterParameters.AuditProof::class.java) - assertThat(builder.referenceStates).isInstanceOf(ComponentGroupFilterParameters.SizeProof::class.java) + assertThat(builder.inputStates).isInstanceOf(AuditProof::class.java) + assertThat(builder.referenceStates).isInstanceOf(SizeProof::class.java) assertThat(builder.outputStates).isNull() - assertThat(builder.commands).isInstanceOf(ComponentGroupFilterParameters.AuditProof::class.java) + assertThat(builder.commands).isInstanceOf(AuditProof::class.java) } } diff --git a/components/ledger/ledger-utxo-flow/src/test/kotlin/net/corda/ledger/utxo/flow/impl/transaction/filtered/UtxoFilteredTransactionImplTest.kt b/components/ledger/ledger-utxo-flow/src/test/kotlin/net/corda/ledger/utxo/flow/impl/transaction/filtered/UtxoFilteredTransactionImplTest.kt index c482637f429..87029607b9e 100644 --- a/components/ledger/ledger-utxo-flow/src/test/kotlin/net/corda/ledger/utxo/flow/impl/transaction/filtered/UtxoFilteredTransactionImplTest.kt +++ b/components/ledger/ledger-utxo-flow/src/test/kotlin/net/corda/ledger/utxo/flow/impl/transaction/filtered/UtxoFilteredTransactionImplTest.kt @@ -2,6 +2,7 @@ package net.corda.ledger.utxo.flow.impl.transaction.filtered import net.corda.ledger.common.data.transaction.TransactionMetadataImpl import net.corda.ledger.common.flow.transaction.filtered.factory.ComponentGroupFilterParameters +import net.corda.ledger.common.flow.transaction.filtered.factory.ComponentGroupFilterParameters.AuditProof.AuditProofPredicate import net.corda.ledger.common.testkit.publicKeyExample import net.corda.ledger.utxo.data.transaction.UtxoComponentGroup import net.corda.ledger.utxo.data.transaction.UtxoOutputInfoComponent @@ -24,8 +25,9 @@ class UtxoFilteredTransactionImplTest : UtxoFilteredTransactionTestBase() { componentGroupFilterParameters = listOf( ComponentGroupFilterParameters.AuditProof( UtxoComponentGroup.METADATA.ordinal, - TransactionMetadataImpl::class.java - ) { true } + TransactionMetadataImpl::class.java, + AuditProofPredicate.Content { true } + ) ) ) @@ -78,26 +80,35 @@ class UtxoFilteredTransactionImplTest : UtxoFilteredTransactionTestBase() { componentGroupFilterParameters = listOf( ComponentGroupFilterParameters.AuditProof( UtxoComponentGroup.METADATA.ordinal, - TransactionMetadataImpl::class.java - ) { true }, - ComponentGroupFilterParameters.AuditProof(UtxoComponentGroup.NOTARY.ordinal, Any::class.java) { true }, + TransactionMetadataImpl::class.java, + AuditProofPredicate.Content { true } + ), + ComponentGroupFilterParameters.AuditProof( + UtxoComponentGroup.NOTARY.ordinal, + Any::class.java, + AuditProofPredicate.Content { true } + ), ComponentGroupFilterParameters.AuditProof( UtxoComponentGroup.OUTPUTS_INFO.ordinal, - UtxoOutputInfoComponent::class.java - ) { true }, + UtxoOutputInfoComponent::class.java, + AuditProofPredicate.Content { true } + ), ComponentGroupFilterParameters.SizeProof(UtxoComponentGroup.COMMANDS_INFO.ordinal), ComponentGroupFilterParameters.AuditProof( UtxoComponentGroup.INPUTS.ordinal, - StateRef::class.java - ) { it.index != 0 }, + StateRef::class.java, + AuditProofPredicate.Content { it.index != 0 } + ), ComponentGroupFilterParameters.AuditProof( UtxoComponentGroup.REFERENCES.ordinal, - StateRef::class.java - ) { it.index != 0 }, + StateRef::class.java, + AuditProofPredicate.Content { it.index != 0 } + ), ComponentGroupFilterParameters.AuditProof( UtxoComponentGroup.OUTPUTS.ordinal, - ContractState::class.java - ) { true }, + ContractState::class.java, + AuditProofPredicate.Content { true } + ), ComponentGroupFilterParameters.SizeProof(UtxoComponentGroup.COMMANDS.ordinal), ) ) @@ -135,32 +146,41 @@ class UtxoFilteredTransactionImplTest : UtxoFilteredTransactionTestBase() { componentGroupFilterParameters = listOf( ComponentGroupFilterParameters.AuditProof( UtxoComponentGroup.METADATA.ordinal, - TransactionMetadataImpl::class.java - ) { true }, - ComponentGroupFilterParameters.AuditProof(UtxoComponentGroup.NOTARY.ordinal, Any::class.java) { - when (it) { - is MemberX500Name -> false - is PublicKey -> false - else -> true + TransactionMetadataImpl::class.java, + AuditProofPredicate.Content { true } + ), + ComponentGroupFilterParameters.AuditProof( + UtxoComponentGroup.NOTARY.ordinal, + Any::class.java, + AuditProofPredicate.Content { + when (it) { + is MemberX500Name -> false + is PublicKey -> false + else -> true + } } - }, + ), ComponentGroupFilterParameters.AuditProof( UtxoComponentGroup.OUTPUTS_INFO.ordinal, - UtxoOutputInfoComponent::class.java - ) { true }, + UtxoOutputInfoComponent::class.java, + AuditProofPredicate.Content { true } + ), ComponentGroupFilterParameters.SizeProof(UtxoComponentGroup.COMMANDS_INFO.ordinal), ComponentGroupFilterParameters.AuditProof( UtxoComponentGroup.INPUTS.ordinal, - StateRef::class.java - ) { true }, + StateRef::class.java, + AuditProofPredicate.Content { true } + ), ComponentGroupFilterParameters.AuditProof( UtxoComponentGroup.REFERENCES.ordinal, - StateRef::class.java - ) { true }, + StateRef::class.java, + AuditProofPredicate.Content { true } + ), ComponentGroupFilterParameters.AuditProof( UtxoComponentGroup.OUTPUTS.ordinal, - ContractState::class.java - ) { true }, + ContractState::class.java, + AuditProofPredicate.Content { true } + ), ComponentGroupFilterParameters.SizeProof(UtxoComponentGroup.COMMANDS.ordinal), ) ) @@ -179,25 +199,30 @@ class UtxoFilteredTransactionImplTest : UtxoFilteredTransactionTestBase() { componentGroupFilterParameters = listOf( ComponentGroupFilterParameters.AuditProof( UtxoComponentGroup.METADATA.ordinal, - TransactionMetadataImpl::class.java - ) { true }, + TransactionMetadataImpl::class.java, + AuditProofPredicate.Content { true } + ), ComponentGroupFilterParameters.AuditProof( UtxoComponentGroup.OUTPUTS_INFO.ordinal, - UtxoOutputInfoComponent::class.java - ) { true }, + UtxoOutputInfoComponent::class.java, + AuditProofPredicate.Content { true } + ), ComponentGroupFilterParameters.SizeProof(UtxoComponentGroup.COMMANDS_INFO.ordinal), ComponentGroupFilterParameters.AuditProof( UtxoComponentGroup.INPUTS.ordinal, - StateRef::class.java - ) { true }, + StateRef::class.java, + AuditProofPredicate.Content { true } + ), ComponentGroupFilterParameters.AuditProof( UtxoComponentGroup.REFERENCES.ordinal, - StateRef::class.java - ) { true }, + StateRef::class.java, + AuditProofPredicate.Content { true } + ), ComponentGroupFilterParameters.AuditProof( UtxoComponentGroup.OUTPUTS.ordinal, - ContractState::class.java - ) { true }, + ContractState::class.java, + AuditProofPredicate.Content { true } + ), ComponentGroupFilterParameters.SizeProof(UtxoComponentGroup.COMMANDS.ordinal), ) ) diff --git a/components/ledger/ledger-utxo-flow/src/test/kotlin/net/corda/ledger/utxo/flow/impl/transaction/filtered/UtxoFilteredTransactionTestBase.kt b/components/ledger/ledger-utxo-flow/src/test/kotlin/net/corda/ledger/utxo/flow/impl/transaction/filtered/UtxoFilteredTransactionTestBase.kt index 3d586707ab6..7607184a5a0 100644 --- a/components/ledger/ledger-utxo-flow/src/test/kotlin/net/corda/ledger/utxo/flow/impl/transaction/filtered/UtxoFilteredTransactionTestBase.kt +++ b/components/ledger/ledger-utxo-flow/src/test/kotlin/net/corda/ledger/utxo/flow/impl/transaction/filtered/UtxoFilteredTransactionTestBase.kt @@ -12,6 +12,7 @@ import net.corda.ledger.common.data.transaction.WireTransaction import net.corda.ledger.common.flow.impl.transaction.filtered.factory.FilteredTransactionFactoryImpl import net.corda.ledger.common.flow.transaction.filtered.FilteredTransaction import net.corda.ledger.common.flow.transaction.filtered.factory.ComponentGroupFilterParameters +import net.corda.ledger.common.flow.transaction.filtered.factory.ComponentGroupFilterParameters.AuditProof.AuditProofPredicate import net.corda.ledger.common.testkit.getWireTransactionExample import net.corda.ledger.common.testkit.publicKeyExample import net.corda.ledger.utxo.data.transaction.UtxoComponentGroup @@ -119,19 +120,30 @@ open class UtxoFilteredTransactionTestBase { componentGroupFilterParameters = listOf( ComponentGroupFilterParameters.AuditProof( UtxoComponentGroup.METADATA.ordinal, - TransactionMetadataImpl::class.java - ) { true }, - ComponentGroupFilterParameters.AuditProof(UtxoComponentGroup.NOTARY.ordinal, Any::class.java) { true }, + TransactionMetadataImpl::class.java, + AuditProofPredicate.Content { true } + ), + ComponentGroupFilterParameters.AuditProof( + UtxoComponentGroup.NOTARY.ordinal, + Any::class.java, + AuditProofPredicate.Content { true } + ), ComponentGroupFilterParameters.AuditProof( UtxoComponentGroup.OUTPUTS_INFO.ordinal, - UtxoOutputInfoComponent::class.java - ) { true }, + UtxoOutputInfoComponent::class.java, + AuditProofPredicate.Content { true } + ), ComponentGroupFilterParameters.SizeProof(UtxoComponentGroup.COMMANDS_INFO.ordinal), - ComponentGroupFilterParameters.AuditProof(UtxoComponentGroup.INPUTS.ordinal, StateRef::class.java) { true }, + ComponentGroupFilterParameters.AuditProof( + UtxoComponentGroup.INPUTS.ordinal, + StateRef::class.java, + AuditProofPredicate.Content { true } + ), ComponentGroupFilterParameters.AuditProof( UtxoComponentGroup.OUTPUTS.ordinal, - ContractState::class.java - ) { true }, + ContractState::class.java, + AuditProofPredicate.Content { true } + ), ComponentGroupFilterParameters.SizeProof(UtxoComponentGroup.COMMANDS.ordinal), ) ) diff --git a/components/ledger/ledger-utxo-flow/src/test/kotlin/net/corda/ledger/utxo/flow/impl/transaction/filtered/factory/UtxoFilteredTransactionFactoryImplTest.kt b/components/ledger/ledger-utxo-flow/src/test/kotlin/net/corda/ledger/utxo/flow/impl/transaction/filtered/factory/UtxoFilteredTransactionFactoryImplTest.kt index b1eb40f07a0..35a8e9938d0 100644 --- a/components/ledger/ledger-utxo-flow/src/test/kotlin/net/corda/ledger/utxo/flow/impl/transaction/filtered/factory/UtxoFilteredTransactionFactoryImplTest.kt +++ b/components/ledger/ledger-utxo-flow/src/test/kotlin/net/corda/ledger/utxo/flow/impl/transaction/filtered/factory/UtxoFilteredTransactionFactoryImplTest.kt @@ -4,12 +4,14 @@ import net.corda.ledger.common.flow.transaction.filtered.factory.ComponentGroupF import net.corda.ledger.common.flow.transaction.filtered.factory.FilteredTransactionFactory import net.corda.ledger.common.testkit.publicKeyExample import net.corda.ledger.utxo.data.transaction.UtxoComponentGroup +import net.corda.ledger.utxo.flow.impl.timewindow.TimeWindowBetweenImpl import net.corda.ledger.utxo.flow.impl.transaction.UtxoSignedTransactionInternal import net.corda.ledger.utxo.flow.impl.transaction.filtered.UtxoFilteredTransactionBuilderImpl import net.corda.ledger.utxo.flow.impl.transaction.filtered.UtxoFilteredTransactionBuilderInternal import net.corda.ledger.utxo.test.UtxoLedgerTest import net.corda.ledger.utxo.testkit.notaryX500Name import net.corda.ledger.utxo.testkit.utxoTimeWindowExample +import net.corda.v5.base.types.MemberX500Name import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test @@ -18,6 +20,8 @@ import org.mockito.kotlin.argumentCaptor import org.mockito.kotlin.mock import org.mockito.kotlin.verify import org.mockito.kotlin.whenever +import java.security.PublicKey +import java.util.function.Predicate class UtxoFilteredTransactionFactoryImplTest : UtxoLedgerTest() { @@ -75,9 +79,9 @@ class UtxoFilteredTransactionFactoryImplTest : UtxoLedgerTest() { assertThat(componentGroups).containsExactly(UtxoComponentGroup.METADATA.ordinal, UtxoComponentGroup.NOTARY.ordinal) val predicate = componentGroupFilterParameters[1].let { (it as ComponentGroupFilterParameters.AuditProof).predicate } - assertThat(predicate.test(notaryX500Name)).isTrue - assertThat(predicate.test(publicKeyExample)).isTrue - assertThat(predicate.test(utxoTimeWindowExample)).isFalse + assertThat((predicate as Predicate).test(notaryX500Name)).isTrue + assertThat((predicate as Predicate).test(publicKeyExample)).isTrue + assertThat((predicate as Predicate).test(utxoTimeWindowExample)).isFalse } @Suppress("UNCHECKED_CAST") @@ -93,9 +97,9 @@ class UtxoFilteredTransactionFactoryImplTest : UtxoLedgerTest() { assertThat(componentGroups).containsExactly(UtxoComponentGroup.METADATA.ordinal, UtxoComponentGroup.NOTARY.ordinal) val predicate = componentGroupFilterParameters[1].let { (it as ComponentGroupFilterParameters.AuditProof).predicate } - assertThat(predicate.test(notaryX500Name)).isFalse - assertThat(predicate.test(publicKeyExample)).isFalse - assertThat(predicate.test(utxoTimeWindowExample)).isTrue + assertThat((predicate as Predicate).test(notaryX500Name)).isFalse + assertThat((predicate as Predicate).test(publicKeyExample)).isFalse + assertThat((predicate as Predicate).test(utxoTimeWindowExample)).isTrue } @Suppress("UNCHECKED_CAST") @@ -112,9 +116,9 @@ class UtxoFilteredTransactionFactoryImplTest : UtxoLedgerTest() { assertThat(componentGroups).containsExactly(UtxoComponentGroup.METADATA.ordinal, UtxoComponentGroup.NOTARY.ordinal) val predicate = componentGroupFilterParameters[1].let { (it as ComponentGroupFilterParameters.AuditProof).predicate } - assertThat(predicate.test(notaryX500Name)).isTrue - assertThat(predicate.test(publicKeyExample)).isTrue - assertThat(predicate.test(utxoTimeWindowExample)).isTrue + assertThat((predicate as Predicate).test(notaryX500Name)).isTrue + assertThat((predicate as Predicate).test(publicKeyExample)).isTrue + assertThat((predicate as Predicate).test(utxoTimeWindowExample)).isTrue } @Test diff --git a/components/ledger/ledger-utxo-flow/src/test/kotlin/net/corda/ledger/utxo/flow/impl/transaction/verifier/NotarySignatureVerificationServiceImplTest.kt b/components/ledger/ledger-utxo-flow/src/test/kotlin/net/corda/ledger/utxo/flow/impl/transaction/verifier/NotarySignatureVerificationServiceImplTest.kt new file mode 100644 index 00000000000..a2dd65738bb --- /dev/null +++ b/components/ledger/ledger-utxo-flow/src/test/kotlin/net/corda/ledger/utxo/flow/impl/transaction/verifier/NotarySignatureVerificationServiceImplTest.kt @@ -0,0 +1,160 @@ +package net.corda.ledger.utxo.flow.impl.transaction.verifier + +import net.corda.crypto.cipher.suite.SignatureSpecImpl +import net.corda.crypto.core.DigitalSignatureWithKeyId +import net.corda.crypto.core.SecureHashImpl +import net.corda.crypto.core.fullIdHash +import net.corda.ledger.common.flow.transaction.TransactionSignatureServiceInternal +import net.corda.v5.application.crypto.DigitalSignatureAndMetadata +import net.corda.v5.application.crypto.DigitalSignatureMetadata +import net.corda.v5.crypto.CompositeKey +import net.corda.v5.crypto.SecureHash +import net.corda.v5.ledger.common.transaction.TransactionSignatureException +import net.corda.v5.ledger.common.transaction.TransactionWithMetadata +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertDoesNotThrow +import org.junit.jupiter.api.assertThrows +import org.mockito.kotlin.doReturn +import org.mockito.kotlin.mock +import org.mockito.kotlin.whenever +import java.security.MessageDigest +import java.security.PublicKey +import java.time.Instant +import kotlin.test.assertEquals + +class NotarySignatureVerificationServiceImplTest { + private lateinit var notarySignatureVerificationService: NotarySignatureVerificationServiceImpl + private val transactionSignatureServiceInternal = mock() + + // notarykeys + private val notaryVNodeAliceKey = mock().also { whenever(it.encoded).thenReturn(byteArrayOf(0x01)) } + private val notaryVNodeBobKey = mock().also { whenever(it.encoded).thenReturn(byteArrayOf(0x02)) } + private val notaryServiceCompositeKey = mock { + on { leafKeys } doReturn setOf(notaryVNodeAliceKey) + on { isFulfilledBy(notaryVNodeAliceKey) } doReturn true + on { isFulfilledBy(setOf(notaryVNodeAliceKey)) } doReturn true + } + + // transactionId + private val transaction = mock().also { + whenever(it.id).thenReturn(transactionId) + } + private val transactionId = mock() + + // signatures + private val signatureAlice = digitalSignatureAndMetadata(notaryVNodeAliceKey, byteArrayOf(1, 2, 0)) + private val signatureBob = digitalSignatureAndMetadata(notaryVNodeBobKey, byteArrayOf(1, 2, 3)) + + private val keyIdToNotaryKeysMap: MutableMap> = mutableMapOf() + + // keyIds + private val keyIdOfAlice = SecureHashImpl( + signatureAlice.by.algorithm, + MessageDigest.getInstance(signatureAlice.by.algorithm).digest(notaryVNodeAliceKey.encoded) + ) + private val keyIdOfBob = SecureHashImpl( + signatureBob.by.algorithm, + MessageDigest.getInstance(signatureBob.by.algorithm).digest(notaryVNodeBobKey.encoded) + ) + + @BeforeEach + fun setup() { + notarySignatureVerificationService = NotarySignatureVerificationServiceImpl( + transactionSignatureServiceInternal + ) + } + + @Test + fun `notary signature verification with a valid public key`() { + whenever( + transactionSignatureServiceInternal.getIdOfPublicKey( + notaryVNodeAliceKey, + signatureAlice.by.algorithm + ) + ).thenReturn(keyIdOfAlice) + assertDoesNotThrow { + notarySignatureVerificationService.verifyNotarySignatures( + transaction, + notaryVNodeAliceKey, + listOf(signatureAlice), + keyIdToNotaryKeysMap + ) + } + } + + @Test + fun `notary signature verification with a valid composite key`() { + whenever( + transactionSignatureServiceInternal.getIdOfPublicKey( + notaryVNodeAliceKey, + signatureAlice.by.algorithm + ) + ).thenReturn(keyIdOfAlice) + assertDoesNotThrow { + notarySignatureVerificationService.verifyNotarySignatures( + transaction, + notaryServiceCompositeKey, + listOf(signatureAlice), + keyIdToNotaryKeysMap + ) + } + } + + @Test + fun `notary signature verification with an invalid notary key`() { + whenever( + transactionSignatureServiceInternal.getIdOfPublicKey( + notaryVNodeBobKey, + signatureBob.by.algorithm + ) + ).thenReturn(keyIdOfBob) + + val exception = assertThrows { + notarySignatureVerificationService.verifyNotarySignatures( + transaction, + notaryServiceCompositeKey, + listOf(signatureBob), + keyIdToNotaryKeysMap + ) + } + + assertEquals( + "Notary signing keys [] did not fulfil requirements of notary service key $notaryServiceCompositeKey", + exception.message + ) + } + + @Test + fun `notary signature verification with failed signature verification`() { + whenever( + transactionSignatureServiceInternal.getIdOfPublicKey( + notaryVNodeBobKey, + signatureBob.by.algorithm + ) + ).thenReturn(keyIdOfBob) + whenever(transactionSignatureServiceInternal.verifySignature(transaction, signatureBob, notaryVNodeBobKey)) + .thenThrow(TransactionSignatureException(transactionId, "", null)) + + val exception = assertThrows { + notarySignatureVerificationService.verifyNotarySignatures( + transaction, + notaryVNodeBobKey, + listOf(signatureBob), + keyIdToNotaryKeysMap + ) + } + + assertEquals( + "Failed to verify signature of ${signatureBob.signature} for transaction $transaction. Message: ", + exception.message + ) + } + + private fun digitalSignatureAndMetadata(publicKey: PublicKey, byteArray: ByteArray): DigitalSignatureAndMetadata { + return DigitalSignatureAndMetadata( + DigitalSignatureWithKeyId(publicKey.fullIdHash(), byteArray), + DigitalSignatureMetadata(Instant.now(), SignatureSpecImpl("dummySignatureName"), emptyMap()) + ) + } +} diff --git a/components/ledger/ledger-utxo-token-cache/build.gradle b/components/ledger/ledger-utxo-token-cache/build.gradle index 2493fceaefd..25a87d4c46c 100644 --- a/components/ledger/ledger-utxo-token-cache/build.gradle +++ b/components/ledger/ledger-utxo-token-cache/build.gradle @@ -43,9 +43,6 @@ dependencies { implementation 'org.jetbrains.kotlin:kotlin-osgi-bundle' implementation "org.slf4j:slf4j-api:$slf4jVersion" - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation "org.apache.felix:org.apache.felix.framework:$felixVersion" testImplementation "com.fasterxml.jackson.module:jackson-module-kotlin:$jacksonVersion" diff --git a/components/ledger/ledger-verification/build.gradle b/components/ledger/ledger-verification/build.gradle index ed5c584f0d6..3bdc95bcfd3 100644 --- a/components/ledger/ledger-verification/build.gradle +++ b/components/ledger/ledger-verification/build.gradle @@ -53,8 +53,6 @@ dependencies { runtimeOnly project(":libs:crypto:crypto-serialization-impl") runtimeOnly project(':libs:crypto:merkle-impl') - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" - testImplementation project(':libs:ledger:ledger-utxo-data') testImplementation project(":libs:lifecycle:lifecycle-test-impl") testImplementation project(":libs:lifecycle:lifecycle-impl") @@ -71,7 +69,7 @@ dependencies { // IMPORTANT: do NOT attempt to use mockito-kotlin in the integration tests. // It's not an OSGi bundle, so you will get errors (despite Intellij appearing to allow you to use it). - integrationTestImplementation("org.mockito:mockito-core:$mockitoVersion") + integrationTestImplementation libs.mockito.core integrationTestImplementation("com.fasterxml.jackson.module:jackson-module-kotlin:$jacksonVersion") integrationTestImplementation project(':components:virtual-node:cpi-info-read-service') diff --git a/components/ledger/notary-worker-selection-impl/build.gradle b/components/ledger/notary-worker-selection-impl/build.gradle index b7fbeb348b3..ce4a99a081d 100644 --- a/components/ledger/notary-worker-selection-impl/build.gradle +++ b/components/ledger/notary-worker-selection-impl/build.gradle @@ -17,7 +17,4 @@ dependencies { implementation project(':components:ledger:notary-worker-selection') implementation project(':components:membership:membership-group-read') implementation project(':libs:sandbox-types') - - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/components/ledger/notary-worker-selection/build.gradle b/components/ledger/notary-worker-selection/build.gradle index 6cfb04d0726..4d71acbf0ab 100644 --- a/components/ledger/notary-worker-selection/build.gradle +++ b/components/ledger/notary-worker-selection/build.gradle @@ -14,7 +14,4 @@ dependencies { api platform("net.corda:corda-api:$cordaApiVersion") api 'org.jetbrains.kotlin:kotlin-osgi-bundle' api 'net.corda:corda-ledger-common' - - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/components/link-manager/build.gradle b/components/link-manager/build.gradle index c8950c3747d..8772df9ea02 100644 --- a/components/link-manager/build.gradle +++ b/components/link-manager/build.gradle @@ -68,8 +68,6 @@ dependencies { testImplementation project(":testing:test-utilities") testImplementation project(":testing:p2p:certificates") - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation "org.apache.logging.log4j:log4j-core:$log4jVersion" testRuntimeOnly "org.apache.logging.log4j:log4j-slf4j-impl:$log4jVersion" @@ -88,6 +86,7 @@ dependencies { nonOsgiIntegrationTestImplementation project(":libs:messaging:db-message-bus-impl") nonOsgiIntegrationTestImplementation project(":components:crypto:crypto-client") nonOsgiIntegrationTestImplementation project(':libs:schema-registry:schema-registry') + nonOsgiIntegrationTestImplementation project(':libs:platform-info') nonOsgiIntegrationTestImplementation "net.corda:corda-avro-schema" nonOsgiIntegrationTestImplementation project(":libs:schema-registry:schema-registry-impl") nonOsgiIntegrationTestRuntimeOnly 'org.osgi:osgi.core' diff --git a/components/link-manager/src/nonOsgiIntegrationTest/kotlin/net/corda/p2p/P2PLayerEndToEndTest.kt b/components/link-manager/src/nonOsgiIntegrationTest/kotlin/net/corda/p2p/P2PLayerEndToEndTest.kt index d1c0b3c677e..b5d1e51863e 100644 --- a/components/link-manager/src/nonOsgiIntegrationTest/kotlin/net/corda/p2p/P2PLayerEndToEndTest.kt +++ b/components/link-manager/src/nonOsgiIntegrationTest/kotlin/net/corda/p2p/P2PLayerEndToEndTest.kt @@ -40,6 +40,7 @@ import net.corda.libs.configuration.schema.p2p.LinkManagerConfiguration.Companio import net.corda.libs.configuration.schema.p2p.LinkManagerConfiguration.Companion.SESSIONS_PER_PEER_KEY import net.corda.libs.configuration.schema.p2p.LinkManagerConfiguration.Companion.SESSION_REFRESH_THRESHOLD_KEY import net.corda.libs.configuration.schema.p2p.LinkManagerConfiguration.Companion.SESSION_TIMEOUT_KEY +import net.corda.libs.platform.PlatformInfoProvider import net.corda.lifecycle.Lifecycle import net.corda.lifecycle.LifecycleCoordinatorName import net.corda.lifecycle.LifecycleStatus @@ -78,6 +79,7 @@ import net.corda.schema.Schemas.P2P.P2P_IN_TOPIC import net.corda.schema.Schemas.P2P.P2P_OUT_MARKERS import net.corda.schema.Schemas.P2P.P2P_OUT_TOPIC import net.corda.schema.configuration.BootConfig.INSTANCE_ID +import net.corda.schema.configuration.BootConfig.P2P_LINK_MANAGER_WORKER_REST_ENDPOINT import net.corda.schema.configuration.ConfigKeys import net.corda.schema.configuration.MessagingConfig import net.corda.schema.registry.impl.AvroSchemaRegistryImpl @@ -665,6 +667,17 @@ class P2PLayerEndToEndTest { mock(), mock(), ) + private val platformInfoProvider = object : PlatformInfoProvider { + override val activePlatformVersion = 1 + override val localWorkerPlatformVersion = 1 + override val localWorkerSoftwareVersion = "5.2" + } + private val bootConfig = SmartConfigFactory.createWithoutSecurityServices() + .create(ConfigFactory.empty()) + .withValue( + P2P_LINK_MANAGER_WORKER_REST_ENDPOINT, + ConfigValueFactory.fromAnyRef("localhost:8080"), + ) private val gateway = Gateway( @@ -672,9 +685,11 @@ class P2PLayerEndToEndTest { subscriptionFactory, publisherFactory, lifecycleCoordinatorFactory, - bootstrapConfig, cryptoOpsClient, - AvroSchemaRegistryImpl() + AvroSchemaRegistryImpl(), + platformInfoProvider, + bootConfig, + bootstrapConfig, ) private fun Publisher.publishConfig(key: String, config: Config) { diff --git a/components/membership/certificates-client-impl/build.gradle b/components/membership/certificates-client-impl/build.gradle index d959843852c..05aa4fba19a 100644 --- a/components/membership/certificates-client-impl/build.gradle +++ b/components/membership/certificates-client-impl/build.gradle @@ -27,7 +27,5 @@ dependencies { implementation project(':libs:membership:certificates-common') implementation project(":libs:rest:rest") - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation project(':testing:test-utilities') } diff --git a/components/membership/certificates-service-impl/build.gradle b/components/membership/certificates-service-impl/build.gradle index 9cdb45b423c..d76dc9e90d7 100644 --- a/components/membership/certificates-service-impl/build.gradle +++ b/components/membership/certificates-service-impl/build.gradle @@ -25,9 +25,6 @@ dependencies { testImplementation project(':libs:db:db-orm-impl') testImplementation project(':testing:db-testkit') - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" - testRuntimeOnly "org.hsqldb:hsqldb:$hsqldbVersion" testRuntimeOnly "org.postgresql:postgresql:$postgresDriverVersion" } diff --git a/components/membership/group-params-writer-service-impl/build.gradle b/components/membership/group-params-writer-service-impl/build.gradle index f13dcc7aac1..146406c4b1b 100644 --- a/components/membership/group-params-writer-service-impl/build.gradle +++ b/components/membership/group-params-writer-service-impl/build.gradle @@ -22,8 +22,6 @@ dependencies { implementation project(':libs:layered-property-map') implementation project(':libs:messaging:messaging') - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation project(':libs:membership:membership-impl') testImplementation project(":testing:layered-property-map-testkit") testImplementation project(":testing:test-utilities") diff --git a/components/membership/group-policy-configuration-validation-impl/build.gradle b/components/membership/group-policy-configuration-validation-impl/build.gradle index 4fdf04f5422..9e7431708fc 100644 --- a/components/membership/group-policy-configuration-validation-impl/build.gradle +++ b/components/membership/group-policy-configuration-validation-impl/build.gradle @@ -16,7 +16,4 @@ dependencies { implementation project(':libs:membership:membership-common') implementation project(':components:membership:group-policy-configuration-validation') implementation project(':components:configuration:configuration-read-service') - - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/components/membership/group-policy-impl/build.gradle b/components/membership/group-policy-impl/build.gradle index 0bf4228d92b..8429c699821 100644 --- a/components/membership/group-policy-impl/build.gradle +++ b/components/membership/group-policy-impl/build.gradle @@ -29,8 +29,6 @@ dependencies { implementation "com.typesafe:config:$typeSafeConfigVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation project(':components:membership:registration-impl') testImplementation project(':components:configuration:configuration-read-service') testImplementation project(':libs:messaging:messaging') diff --git a/components/membership/locally-hosted-identities-service-impl/build.gradle b/components/membership/locally-hosted-identities-service-impl/build.gradle index c5c4c121d76..3760bb1588e 100644 --- a/components/membership/locally-hosted-identities-service-impl/build.gradle +++ b/components/membership/locally-hosted-identities-service-impl/build.gradle @@ -22,7 +22,4 @@ dependencies { implementation 'net.corda:corda-config-schema' implementation 'net.corda:corda-topic-schema' implementation 'org.jetbrains.kotlin:kotlin-osgi-bundle' - - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/components/membership/members-client-certificate-publisher-service-impl/build.gradle b/components/membership/members-client-certificate-publisher-service-impl/build.gradle index f43af5aad47..310bf145e11 100644 --- a/components/membership/members-client-certificate-publisher-service-impl/build.gradle +++ b/components/membership/members-client-certificate-publisher-service-impl/build.gradle @@ -20,7 +20,4 @@ dependencies { implementation 'net.corda:corda-config-schema' implementation 'net.corda:corda-topic-schema' implementation 'org.jetbrains.kotlin:kotlin-osgi-bundle' - - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/components/membership/membership-client-impl/build.gradle b/components/membership/membership-client-impl/build.gradle index 5dcfa80efad..05abe2ac8b5 100644 --- a/components/membership/membership-client-impl/build.gradle +++ b/components/membership/membership-client-impl/build.gradle @@ -33,7 +33,4 @@ dependencies { testImplementation project(":testing:test-utilities") testImplementation "net.corda:corda-serialization" - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/components/membership/membership-group-read-impl/build.gradle b/components/membership/membership-group-read-impl/build.gradle index b6c1f663dc1..d164fe4e738 100644 --- a/components/membership/membership-group-read-impl/build.gradle +++ b/components/membership/membership-group-read-impl/build.gradle @@ -55,7 +55,5 @@ dependencies { testImplementation project(":testing:test-utilities") testImplementation "net.corda:corda-serialization" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testRuntimeOnly "org.slf4j:slf4j-simple:$slf4jVersion" } diff --git a/components/membership/membership-p2p-impl/build.gradle b/components/membership/membership-p2p-impl/build.gradle index 3b062690ff8..67632915487 100644 --- a/components/membership/membership-p2p-impl/build.gradle +++ b/components/membership/membership-p2p-impl/build.gradle @@ -28,9 +28,6 @@ dependencies { implementation project(':components:membership:membership-group-read') implementation project(':components:membership:membership-p2p') - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" - testImplementation "org.assertj:assertj-core:$assertjVersion" testImplementation project(':testing:test-utilities') } diff --git a/components/membership/membership-p2p/build.gradle b/components/membership/membership-p2p/build.gradle index ab8687c0c39..f3864328a1e 100644 --- a/components/membership/membership-p2p/build.gradle +++ b/components/membership/membership-p2p/build.gradle @@ -28,6 +28,4 @@ dependencies { implementation project(":libs:serialization:serialization-avro") testImplementation project(':testing:test-utilities') - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/components/membership/membership-persistence-client-impl/build.gradle b/components/membership/membership-persistence-client-impl/build.gradle index 64f281e753c..b190cc3383c 100644 --- a/components/membership/membership-persistence-client-impl/build.gradle +++ b/components/membership/membership-persistence-client-impl/build.gradle @@ -25,9 +25,6 @@ dependencies { implementation project(':libs:messaging:messaging') implementation project(':libs:utilities') - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" testImplementation project(':testing:layered-property-map-testkit') testImplementation project(':testing:test-utilities') } \ No newline at end of file diff --git a/components/membership/membership-persistence-service-impl/build.gradle b/components/membership/membership-persistence-service-impl/build.gradle index de5cb255ccf..f252434599d 100644 --- a/components/membership/membership-persistence-service-impl/build.gradle +++ b/components/membership/membership-persistence-service-impl/build.gradle @@ -38,13 +38,8 @@ dependencies { implementation project(':libs:utilities') implementation project(':libs:serialization:serialization-avro') - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" testImplementation project(':testing:test-utilities') - integrationTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" - integrationTestImplementation 'net.corda:corda-crypto' integrationTestImplementation 'net.corda:corda-membership' integrationTestImplementation project(':testing:db-testkit') diff --git a/components/membership/membership-rest-impl/build.gradle b/components/membership/membership-rest-impl/build.gradle index 5bd808938a8..a727c1ed41c 100644 --- a/components/membership/membership-rest-impl/build.gradle +++ b/components/membership/membership-rest-impl/build.gradle @@ -44,7 +44,4 @@ dependencies { testImplementation 'net.corda:corda-config-schema' testImplementation "net.corda:corda-serialization" - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/components/membership/membership-service-impl/build.gradle b/components/membership/membership-service-impl/build.gradle index 66ace83fd34..74f512103da 100644 --- a/components/membership/membership-service-impl/build.gradle +++ b/components/membership/membership-service-impl/build.gradle @@ -30,10 +30,6 @@ dependencies { implementation project(":components:crypto:crypto-client") implementation project(":libs:serialization:serialization-avro") - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" - testImplementation "org.assertj:assertj-core:$assertjVersion" testImplementation project(":testing:test-utilities") testImplementation project(':libs:lifecycle:lifecycle-test-impl') testImplementation project(":libs:membership:membership-impl") diff --git a/components/membership/mtls-mgm-allowed-list-reader-writer-impl/build.gradle b/components/membership/mtls-mgm-allowed-list-reader-writer-impl/build.gradle index 8c5886e7d70..05b2d25cfcd 100644 --- a/components/membership/mtls-mgm-allowed-list-reader-writer-impl/build.gradle +++ b/components/membership/mtls-mgm-allowed-list-reader-writer-impl/build.gradle @@ -25,6 +25,4 @@ dependencies { implementation 'org.jetbrains.kotlin:kotlin-osgi-bundle' implementation 'org.slf4j:slf4j-api' - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/components/membership/registration-impl/build.gradle b/components/membership/registration-impl/build.gradle index 8caee0be870..62535097196 100644 --- a/components/membership/registration-impl/build.gradle +++ b/components/membership/registration-impl/build.gradle @@ -70,7 +70,4 @@ dependencies { testImplementation project(":testing:test-utilities") testImplementation "org.apache.commons:commons-text:$commonsTextVersion" - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/components/membership/registration-impl/src/main/kotlin/net/corda/membership/impl/registration/dynamic/member/DynamicMemberRegistrationService.kt b/components/membership/registration-impl/src/main/kotlin/net/corda/membership/impl/registration/dynamic/member/DynamicMemberRegistrationService.kt index fa174cb135b..c28581b3976 100644 --- a/components/membership/registration-impl/src/main/kotlin/net/corda/membership/impl/registration/dynamic/member/DynamicMemberRegistrationService.kt +++ b/components/membership/registration-impl/src/main/kotlin/net/corda/membership/impl/registration/dynamic/member/DynamicMemberRegistrationService.kt @@ -61,6 +61,7 @@ import net.corda.membership.lib.MemberInfoExtension.Companion.MEMBER_CPI_SIGNER_ import net.corda.membership.lib.MemberInfoExtension.Companion.MEMBER_CPI_VERSION import net.corda.membership.lib.MemberInfoExtension.Companion.NOTARY_KEY_SPEC import net.corda.membership.lib.MemberInfoExtension.Companion.NOTARY_ROLE +import net.corda.membership.lib.MemberInfoExtension.Companion.NOTARY_SERVICE_BACKCHAIN_REQUIRED import net.corda.membership.lib.MemberInfoExtension.Companion.NOTARY_SERVICE_PROTOCOL_VERSIONS import net.corda.membership.lib.MemberInfoExtension.Companion.PARTY_NAME import net.corda.membership.lib.MemberInfoExtension.Companion.PARTY_SESSION_KEYS @@ -471,11 +472,12 @@ class DynamicMemberRegistrationService @Activate constructor( tlsSubject previousRegistrationContext?.let { previous -> + verifyBackchainFlagMovement(previousRegistrationContext, newRegistrationContext) ((newRegistrationContext.entries - previous.entries) + (previous.entries - newRegistrationContext.entries)).filter { it.key.startsWith(SESSION_KEYS) || it.key.startsWith(LEDGER_KEYS) || it.key.startsWith(ROLES_PREFIX) || - it.key.startsWith("corda.notary") + (it.key.startsWith("corda.notary") && !it.key.endsWith("service.backchain.required")) }.apply { require(isEmpty()) { throw InvalidMembershipRegistrationException( @@ -812,4 +814,17 @@ class DynamicMemberRegistrationService @Activate constructor( ) } } + + private fun verifyBackchainFlagMovement(previousContext: Map, newContext: Map) { + // This property can only be null when upgrading from 5.0/5.1, and we should move it to `true` + // because pre-5.2 notaries do not support optional backchain + // Once the flag is set it should never change during re-registrations + // (i.e. no true->false or false->true change allowed) + val previousOptionalBackchainValue = previousContext[NOTARY_SERVICE_BACKCHAIN_REQUIRED]?.toBoolean() + val currentOptionalBackchainValue = newContext[NOTARY_SERVICE_BACKCHAIN_REQUIRED]?.toBoolean() + require((previousOptionalBackchainValue == null && currentOptionalBackchainValue == true) + || previousOptionalBackchainValue == currentOptionalBackchainValue) { + "Optional back-chain flag can only move from 'none' to 'true' during re-registration." + } + } } diff --git a/components/membership/registration-impl/src/test/kotlin/net/corda/membership/impl/registration/dynamic/member/DynamicMemberRegistrationServiceTest.kt b/components/membership/registration-impl/src/test/kotlin/net/corda/membership/impl/registration/dynamic/member/DynamicMemberRegistrationServiceTest.kt index 3f4fd6f6fd2..a7474ed6efd 100644 --- a/components/membership/registration-impl/src/test/kotlin/net/corda/membership/impl/registration/dynamic/member/DynamicMemberRegistrationServiceTest.kt +++ b/components/membership/registration-impl/src/test/kotlin/net/corda/membership/impl/registration/dynamic/member/DynamicMemberRegistrationServiceTest.kt @@ -57,9 +57,8 @@ import net.corda.membership.lib.MemberInfoExtension.Companion.LEDGER_KEY_SIGNATU import net.corda.membership.lib.MemberInfoExtension.Companion.MEMBER_CPI_NAME import net.corda.membership.lib.MemberInfoExtension.Companion.MEMBER_CPI_SIGNER_HASH import net.corda.membership.lib.MemberInfoExtension.Companion.MEMBER_CPI_VERSION -import net.corda.membership.lib.MemberInfoExtension.Companion.NOTARY_KEY_HASH -import net.corda.membership.lib.MemberInfoExtension.Companion.NOTARY_KEY_PEM import net.corda.membership.lib.MemberInfoExtension.Companion.NOTARY_KEY_SPEC +import net.corda.membership.lib.MemberInfoExtension.Companion.NOTARY_SERVICE_BACKCHAIN_REQUIRED import net.corda.membership.lib.MemberInfoExtension.Companion.NOTARY_SERVICE_NAME import net.corda.membership.lib.MemberInfoExtension.Companion.NOTARY_SERVICE_PROTOCOL import net.corda.membership.lib.MemberInfoExtension.Companion.NOTARY_SERVICE_PROTOCOL_VERSIONS @@ -155,13 +154,20 @@ class DynamicMemberRegistrationServiceTest { const val TEST_KEY_ID = "DDD123456789" const val PUBLISHER_CLIENT_ID = "dynamic-member-registration-service" const val GROUP_NAME = "dummy_group" + const val NOTARY_KEY_PEM = "1234" + const val NOTARY_KEY_HASH = "SHA-256:73A2AF8864FC500FA49048BF3003776C19938F360E56BD03663866FB3087884A" + const val NOTARY_KEY_SIG_SPEC = "SHA256withECDSA" val MEMBER_CONTEXT_BYTES = "2222".toByteArray() val REQUEST_BYTES = "3333".toByteArray() val UNAUTH_REQUEST_BYTES = "4444".toByteArray() const val SESSION_KEY_ID_KEY = "corda.session.keys.0.id" const val LEDGER_KEY_ID_KEY = "corda.ledger.keys.0.id" + const val NOTARY_KEY_ID_KEY = "corda.notary.keys.0.id" + const val NOTARY_KEY_PEM_KEY = "corda.notary.keys.0.pem" + const val NOTARY_KEY_HASH_KEY = "corda.notary.keys.0.hash" + const val NOTARY_KEY_SIG_SPEC_KEY = "corda.notary.keys.0.signature.spec" } private val ecdhKey: PublicKey = mock() @@ -418,6 +424,15 @@ class DynamicMemberRegistrationServiceTest { MEMBER_CPI_SIGNER_HASH to testCpiSignerSummaryHash.toString(), ) + private val previousNotaryRegistrationContext = previousRegistrationContext.filter { + !it.key.contains(LEDGER_KEYS) + } + mapOf( + "$ROLES_PREFIX.0" to "notary", + NOTARY_SERVICE_PROTOCOL to "net.corda.notary.MyNotaryService", + NOTARY_SERVICE_NAME to "O=MyNotaryService, L=London, C=GB", + NOTARY_KEY_ID_KEY to NOTARY_KEY_ID + ) + @AfterEach fun cleanUp() { registrationContextCustomFieldsVerifier.close() @@ -1457,6 +1472,96 @@ class DynamicMemberRegistrationServiceTest { registrationService.stop() } + @Test + fun `re-registration allows optional backchain flag to be set to true from null`() { + val notaryKeyConvertedFields = mapOf( + NOTARY_KEY_PEM_KEY to NOTARY_KEY_PEM, + NOTARY_KEY_HASH_KEY to NOTARY_KEY_HASH, + NOTARY_KEY_SIG_SPEC_KEY to NOTARY_KEY_SIG_SPEC + ) + + val previous = mock { + on { entries } doReturn (previousNotaryRegistrationContext + notaryKeyConvertedFields).entries + } + val newContextEntries = (previousNotaryRegistrationContext).toMutableMap().apply { + put(SESSION_KEY_ID_KEY, SESSION_KEY_ID) + put(NOTARY_SERVICE_BACKCHAIN_REQUIRED, "true") + }.entries + + val newContext = mock { + on { entries } doReturn newContextEntries + } + whenever(memberInfo.memberProvidedContext).doReturn(previous) + whenever(groupReader.lookup(eq(memberName), any())).doReturn(memberInfo) + + assertDoesNotThrow { + registrationService.register(registrationResultId, member, newContext.toMap()) + } + } + + @Test + fun `re-registration does not allow optional backchain flag to be set to false from null`() { + val notaryKeyConvertedFields = mapOf( + NOTARY_KEY_PEM_KEY to NOTARY_KEY_PEM, + NOTARY_KEY_HASH_KEY to NOTARY_KEY_HASH, + NOTARY_KEY_SIG_SPEC_KEY to NOTARY_KEY_SIG_SPEC + ) + + val previous = mock { + on { entries } doReturn (previousNotaryRegistrationContext + notaryKeyConvertedFields).entries + } + val newContextEntries = (previousNotaryRegistrationContext).toMutableMap().apply { + put(SESSION_KEY_ID_KEY, SESSION_KEY_ID) + put(NOTARY_SERVICE_BACKCHAIN_REQUIRED, "false") + }.entries + + val newContext = mock { + on { entries } doReturn newContextEntries + } + whenever(memberInfo.memberProvidedContext).doReturn(previous) + whenever(groupReader.lookup(eq(memberName), any())).doReturn(memberInfo) + + val registrationException = assertThrows { + registrationService.register(registrationResultId, member, newContext.toMap()) + } + + assertThat(registrationException) + .hasStackTraceContaining("Optional back-chain flag can only move from 'none' to 'true' during re-registration.") + } + + @Test + fun `re-registration does not allow optional backchain flag to be set to false from true`() { + val notaryKeyConvertedFields = mapOf( + NOTARY_KEY_PEM_KEY to NOTARY_KEY_PEM, + NOTARY_KEY_HASH_KEY to NOTARY_KEY_HASH, + NOTARY_KEY_SIG_SPEC_KEY to NOTARY_KEY_SIG_SPEC + ) + + val previousNotaryRegistrationContextWithBackchainFlag = previousNotaryRegistrationContext + + mapOf(NOTARY_SERVICE_BACKCHAIN_REQUIRED to "true") + + val previous = mock { + on { entries } doReturn (previousNotaryRegistrationContextWithBackchainFlag + notaryKeyConvertedFields).entries + } + val newContextEntries = (previousNotaryRegistrationContextWithBackchainFlag).toMutableMap().apply { + put(SESSION_KEY_ID_KEY, SESSION_KEY_ID) + put(NOTARY_SERVICE_BACKCHAIN_REQUIRED, "false") + }.entries + + val newContext = mock { + on { entries } doReturn newContextEntries + } + whenever(memberInfo.memberProvidedContext).doReturn(previous) + whenever(groupReader.lookup(eq(memberName), any())).doReturn(memberInfo) + + val registrationException = assertThrows { + registrationService.register(registrationResultId, member, newContext.toMap()) + } + + assertThat(registrationException) + .hasStackTraceContaining("Optional back-chain flag can only move from 'none' to 'true' during re-registration.") + } + @Test fun `registration fails when notary keys are numbered incorrectly`() { val testProperties = @@ -1533,8 +1638,8 @@ class DynamicMemberRegistrationServiceTest { .containsEntry(String.format(ROLES_PREFIX, 0), "notary") .containsKey(NOTARY_SERVICE_NAME) .containsEntry(NOTARY_KEY_ID_KEY, NOTARY_KEY_ID) - .containsEntry(String.format(NOTARY_KEY_PEM, 0), "1234") - .containsKey(String.format(NOTARY_KEY_HASH, 0)) + .containsEntry(String.format(NOTARY_KEY_PEM_KEY, 0), "1234") + .containsKey(String.format(NOTARY_KEY_HASH_KEY, 0)) .containsEntry(String.format(NOTARY_KEY_SPEC, 0), SignatureSpecs.ECDSA_SHA256.signatureName) } diff --git a/components/membership/synchronisation-impl/build.gradle b/components/membership/synchronisation-impl/build.gradle index 52588951f2d..f1aba7ee6d6 100644 --- a/components/membership/synchronisation-impl/build.gradle +++ b/components/membership/synchronisation-impl/build.gradle @@ -35,9 +35,6 @@ dependencies { implementation project(':libs:serialization:serialization-avro') testImplementation "org.apache.commons:commons-text:$commonsTextVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" testImplementation project(':components:crypto:crypto-hes') testImplementation project(":libs:membership:membership-impl") testImplementation project(':testing:layered-property-map-testkit') diff --git a/components/permissions/permission-management-cache-service/build.gradle b/components/permissions/permission-management-cache-service/build.gradle index 95a34f32c56..09f79e8fc27 100644 --- a/components/permissions/permission-management-cache-service/build.gradle +++ b/components/permissions/permission-management-cache-service/build.gradle @@ -25,7 +25,4 @@ dependencies { implementation project(':libs:permissions:permission-storage-common') api project(':libs:permissions:permission-management-cache') - - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } \ No newline at end of file diff --git a/components/permissions/permission-management-service/build.gradle b/components/permissions/permission-management-service/build.gradle index 1a21e6d4627..8370ecda8e4 100644 --- a/components/permissions/permission-management-service/build.gradle +++ b/components/permissions/permission-management-service/build.gradle @@ -33,7 +33,4 @@ dependencies { implementation 'org.jetbrains.kotlin:kotlin-osgi-bundle' implementation "org.slf4j:slf4j-api:$slf4jVersion" - - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/components/permissions/permission-rest-resource-impl/build.gradle b/components/permissions/permission-rest-resource-impl/build.gradle index 44b5f8c3ddb..6c0e58b42d7 100644 --- a/components/permissions/permission-rest-resource-impl/build.gradle +++ b/components/permissions/permission-rest-resource-impl/build.gradle @@ -32,7 +32,4 @@ dependencies { implementation 'org.jetbrains.kotlin:kotlin-osgi-bundle' implementation "org.slf4j:slf4j-api:$slf4jVersion" - - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/components/permissions/permission-storage-reader-service/build.gradle b/components/permissions/permission-storage-reader-service/build.gradle index 00a06db95f2..498d81f7c89 100644 --- a/components/permissions/permission-storage-reader-service/build.gradle +++ b/components/permissions/permission-storage-reader-service/build.gradle @@ -35,7 +35,4 @@ dependencies { implementation 'org.jetbrains.kotlin:kotlin-osgi-bundle' implementation "javax.persistence:javax.persistence-api" implementation "org.slf4j:slf4j-api:$slf4jVersion" - - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/components/permissions/permission-storage-writer-service/build.gradle b/components/permissions/permission-storage-writer-service/build.gradle index ab030e3b5d4..a56c662fce3 100644 --- a/components/permissions/permission-storage-writer-service/build.gradle +++ b/components/permissions/permission-storage-writer-service/build.gradle @@ -34,7 +34,4 @@ dependencies { implementation 'org.jetbrains.kotlin:kotlin-osgi-bundle' implementation 'javax.persistence:javax.persistence-api' implementation "org.slf4j:slf4j-api:$slf4jVersion" - - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/components/permissions/permission-validation-cache-service/build.gradle b/components/permissions/permission-validation-cache-service/build.gradle index 85274890bff..97d554b694a 100644 --- a/components/permissions/permission-validation-cache-service/build.gradle +++ b/components/permissions/permission-validation-cache-service/build.gradle @@ -25,7 +25,4 @@ dependencies { implementation project(':libs:permissions:permission-storage-common') api project(':libs:permissions:permission-validation-cache') - - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } \ No newline at end of file diff --git a/components/persistence/entity-processor-service-impl/build.gradle b/components/persistence/entity-processor-service-impl/build.gradle index c333ff49c66..cbbaeb6bd51 100644 --- a/components/persistence/entity-processor-service-impl/build.gradle +++ b/components/persistence/entity-processor-service-impl/build.gradle @@ -51,8 +51,6 @@ dependencies { testImplementation project(':testing:db-testkit') testImplementation project(':testing:persistence-testkit') - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" - testRuntimeOnly "org.ops4j.pax.jdbc:pax-jdbc-hsqldb:$paxJdbcVersion" testRuntimeOnly "org.postgresql:postgresql:$postgresDriverVersion" @@ -68,7 +66,7 @@ dependencies { // IMPORTANT: do NOT attempt to use mockito-kotlin in the integration tests. // It's not an OSGi bundle, so you will get errors (despite Intellij appearing to allow you to use it). - integrationTestImplementation("org.mockito:mockito-core:$mockitoVersion") + integrationTestImplementation libs.mockito.core integrationTestImplementation project(":testing:db-message-bus-testkit") diff --git a/components/persistence/persistence-service-common/build.gradle b/components/persistence/persistence-service-common/build.gradle index e543259f54e..7ad59e62212 100644 --- a/components/persistence/persistence-service-common/build.gradle +++ b/components/persistence/persistence-service-common/build.gradle @@ -32,7 +32,4 @@ dependencies { implementation "org.hibernate:hibernate-core:$hibernateVersion" runtimeOnly project(":libs:crypto:crypto-serialization-impl") - - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/components/rbac-security-manager-service/build.gradle b/components/rbac-security-manager-service/build.gradle index 5132f53f41d..3088f4e5fd4 100644 --- a/components/rbac-security-manager-service/build.gradle +++ b/components/rbac-security-manager-service/build.gradle @@ -20,7 +20,4 @@ dependencies { api project(":libs:lifecycle:lifecycle") api project(':libs:rest:rest-security-read') - - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/components/reconciliation/reconciliation-impl/build.gradle b/components/reconciliation/reconciliation-impl/build.gradle index d9979755fc2..af2efa2e97e 100644 --- a/components/reconciliation/reconciliation-impl/build.gradle +++ b/components/reconciliation/reconciliation-impl/build.gradle @@ -19,8 +19,4 @@ dependencies { implementation project(':libs:metrics') implementation project(':libs:utilities') implementation project(':components:reconciliation:reconciliation') - - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/components/rest-gateway-comp/build.gradle b/components/rest-gateway-comp/build.gradle index e5a5a3571ea..a53c127a8f5 100644 --- a/components/rest-gateway-comp/build.gradle +++ b/components/rest-gateway-comp/build.gradle @@ -30,7 +30,4 @@ dependencies { implementation project(":libs:utilities") implementation project(":osgi-framework-api") - - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/components/scheduler/build.gradle b/components/scheduler/build.gradle index 8a11321a7a8..15bfe727396 100644 --- a/components/scheduler/build.gradle +++ b/components/scheduler/build.gradle @@ -27,9 +27,5 @@ dependencies { implementation project(':libs:scheduler:scheduler-datamodel') implementation project(':libs:utilities') - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" - runtimeOnly project(":libs:lifecycle:lifecycle-impl") } diff --git a/components/uniqueness/backing-store-impl/build.gradle b/components/uniqueness/backing-store-impl/build.gradle index d4777d0a8a9..ff208d1adc5 100644 --- a/components/uniqueness/backing-store-impl/build.gradle +++ b/components/uniqueness/backing-store-impl/build.gradle @@ -55,9 +55,6 @@ dependencies { implementation project(":libs:utilities") testImplementation "org.hibernate:hibernate-core:$hibernateVersion" - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation project(":testing:crypto-testkit") testImplementation project(":testing:test-utilities") testImplementation project(":testing:uniqueness:backing-store-fake") diff --git a/components/uniqueness/uniqueness-checker-client-service-impl/build.gradle b/components/uniqueness/uniqueness-checker-client-service-impl/build.gradle index 2be8dd03c18..365bae2561a 100644 --- a/components/uniqueness/uniqueness-checker-client-service-impl/build.gradle +++ b/components/uniqueness/uniqueness-checker-client-service-impl/build.gradle @@ -31,9 +31,5 @@ dependencies { implementation project(':libs:utilities') implementation project(':libs:virtual-node:virtual-node-info') - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" - testImplementation project(":testing:crypto-testkit") } diff --git a/components/uniqueness/uniqueness-checker-impl/build.gradle b/components/uniqueness/uniqueness-checker-impl/build.gradle index aeafe32fcd6..e9d3b7e110f 100644 --- a/components/uniqueness/uniqueness-checker-impl/build.gradle +++ b/components/uniqueness/uniqueness-checker-impl/build.gradle @@ -31,10 +31,6 @@ dependencies { implementation project(":libs:utilities") implementation project(":libs:web:web") - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" - testImplementation project(":libs:virtual-node:virtual-node-info") testImplementation project(":testing:crypto-testkit") testImplementation project(":testing:test-utilities") diff --git a/components/virtual-node/cpi-info-read-service-impl/build.gradle b/components/virtual-node/cpi-info-read-service-impl/build.gradle index 23367fd5ce7..f0e45ad0872 100644 --- a/components/virtual-node/cpi-info-read-service-impl/build.gradle +++ b/components/virtual-node/cpi-info-read-service-impl/build.gradle @@ -33,8 +33,4 @@ dependencies { testImplementation project(":libs:lifecycle:lifecycle-impl") testImplementation project(":libs:lifecycle:registry") - - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/components/virtual-node/cpi-info-write-service-impl/build.gradle b/components/virtual-node/cpi-info-write-service-impl/build.gradle index 0b78b3ebd8a..6dab0312904 100644 --- a/components/virtual-node/cpi-info-write-service-impl/build.gradle +++ b/components/virtual-node/cpi-info-write-service-impl/build.gradle @@ -35,7 +35,4 @@ dependencies { testImplementation project(":libs:lifecycle:lifecycle-impl") testImplementation project(":libs:lifecycle:registry") - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/components/virtual-node/cpi-info-write-service/build.gradle b/components/virtual-node/cpi-info-write-service/build.gradle index 93cd8de08da..d489aacc847 100644 --- a/components/virtual-node/cpi-info-write-service/build.gradle +++ b/components/virtual-node/cpi-info-write-service/build.gradle @@ -34,7 +34,4 @@ dependencies { testImplementation project(":libs:lifecycle:lifecycle-impl") testImplementation project(":libs:lifecycle:registry") - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/components/virtual-node/cpi-upload-rest-service/build.gradle b/components/virtual-node/cpi-upload-rest-service/build.gradle index a7d12fa8ee5..a58c3b85929 100644 --- a/components/virtual-node/cpi-upload-rest-service/build.gradle +++ b/components/virtual-node/cpi-upload-rest-service/build.gradle @@ -32,7 +32,5 @@ dependencies { implementation project(':libs:utilities') implementation project(':libs:platform-info') - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation project(':libs:virtual-node:cpi-upload-manager-impl') } diff --git a/components/virtual-node/cpk-read-service-impl/build.gradle b/components/virtual-node/cpk-read-service-impl/build.gradle index 702847b8dcb..408e00efff8 100644 --- a/components/virtual-node/cpk-read-service-impl/build.gradle +++ b/components/virtual-node/cpk-read-service-impl/build.gradle @@ -28,9 +28,6 @@ dependencies { api project(":components:virtual-node:cpk-read-service") - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation "com.google.jimfs:jimfs:$jimfsVersion" testRuntimeOnly "org.slf4j:slf4j-simple:$slf4jVersion" } diff --git a/components/virtual-node/cpk-write-service-impl/build.gradle b/components/virtual-node/cpk-write-service-impl/build.gradle index dde6ca8b039..4cc11837ff7 100644 --- a/components/virtual-node/cpk-write-service-impl/build.gradle +++ b/components/virtual-node/cpk-write-service-impl/build.gradle @@ -33,9 +33,6 @@ dependencies { api project(":components:virtual-node:cpk-write-service") - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation project(":libs:lifecycle:lifecycle-impl") testImplementation project(":libs:lifecycle:registry") diff --git a/components/virtual-node/sandbox-group-context-service/build.gradle b/components/virtual-node/sandbox-group-context-service/build.gradle index fb72f214396..da669f4d01c 100644 --- a/components/virtual-node/sandbox-group-context-service/build.gradle +++ b/components/virtual-node/sandbox-group-context-service/build.gradle @@ -46,9 +46,6 @@ dependencies { testImplementation 'net.corda:corda-serialization' - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation project(':testing:test-utilities') testCompileOnly 'org.osgi:osgi.core' diff --git a/components/virtual-node/virtual-node-info-read-service-rest-extensions/build.gradle b/components/virtual-node/virtual-node-info-read-service-rest-extensions/build.gradle index fab9bb9c21c..b7a3c6fdabd 100644 --- a/components/virtual-node/virtual-node-info-read-service-rest-extensions/build.gradle +++ b/components/virtual-node/virtual-node-info-read-service-rest-extensions/build.gradle @@ -18,6 +18,4 @@ dependencies { implementation project(":components:virtual-node:virtual-node-info-read-service") testImplementation project(":testing:test-utilities") - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/components/virtual-node/virtual-node-info-read-service/build.gradle b/components/virtual-node/virtual-node-info-read-service/build.gradle index 89c6d9fa780..008d3072c5c 100644 --- a/components/virtual-node/virtual-node-info-read-service/build.gradle +++ b/components/virtual-node/virtual-node-info-read-service/build.gradle @@ -38,8 +38,5 @@ dependencies { testImplementation project(":libs:lifecycle:lifecycle-impl") testImplementation project(":libs:lifecycle:registry") - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation project(':testing:test-utilities') } diff --git a/components/virtual-node/virtual-node-management-sender/build.gradle b/components/virtual-node/virtual-node-management-sender/build.gradle index c1c72d5740b..62bf598b533 100644 --- a/components/virtual-node/virtual-node-management-sender/build.gradle +++ b/components/virtual-node/virtual-node-management-sender/build.gradle @@ -27,6 +27,4 @@ dependencies { implementation 'net.corda:corda-config-schema' implementation 'net.corda:corda-topic-schema' // Test - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/components/virtual-node/virtual-node-rest-maintenance-impl/build.gradle b/components/virtual-node/virtual-node-rest-maintenance-impl/build.gradle index ee8a890511c..fbd79b34c4f 100644 --- a/components/virtual-node/virtual-node-rest-maintenance-impl/build.gradle +++ b/components/virtual-node/virtual-node-rest-maintenance-impl/build.gradle @@ -31,6 +31,4 @@ dependencies { implementation 'org.jetbrains.kotlin:kotlin-osgi-bundle' implementation "org.slf4j:slf4j-api:$slf4jVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } \ No newline at end of file diff --git a/components/virtual-node/virtual-node-rest-service-impl/build.gradle b/components/virtual-node/virtual-node-rest-service-impl/build.gradle index eb1aae6c0f9..628c378a8df 100644 --- a/components/virtual-node/virtual-node-rest-service-impl/build.gradle +++ b/components/virtual-node/virtual-node-rest-service-impl/build.gradle @@ -36,7 +36,4 @@ dependencies { implementation 'net.corda:corda-topic-schema' implementation 'org.jetbrains.kotlin:kotlin-osgi-bundle' implementation "org.slf4j:slf4j-api:$slf4jVersion" - - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/components/virtual-node/virtual-node-write-service-impl/build.gradle b/components/virtual-node/virtual-node-write-service-impl/build.gradle index b435ebea6c3..1ed87ea94be 100644 --- a/components/virtual-node/virtual-node-write-service-impl/build.gradle +++ b/components/virtual-node/virtual-node-write-service-impl/build.gradle @@ -56,9 +56,6 @@ dependencies { testImplementation project(':testing:db-testkit') testImplementation project(':testing:test-utilities') - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" - testRuntimeOnly "org.hsqldb:hsqldb:$hsqldbVersion" testRuntimeOnly "org.postgresql:postgresql:$postgresDriverVersion" testRuntimeOnly "org.slf4j:slf4j-simple:$slf4jVersion" diff --git a/gradle.properties b/gradle.properties index cef9e3881dd..7e7885ca1df 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,6 @@ artifactoryContextUrl=https://software.r3.com/artifactory publicArtifactURL = https://download.corda.net/maven kotlin.code.style=official -kotlinVersion=1.8.21 kotlin.stdlib.default.dependency=false kotlinMetadataVersion=0.7.0 @@ -46,7 +45,7 @@ commonsTextVersion = 1.10.0 bouncycastleVersion=1.76 # Corda API libs revision (change in 4th digit indicates a breaking change) # Change to 5.2.0.xx-SNAPSHOT to pick up maven local published copy -cordaApiVersion=5.2.0.12-alpha-1702488104039 +cordaApiVersion=5.2.0.15-alpha-1702488104039 disruptorVersion=3.4.4 felixConfigAdminVersion=1.9.26 @@ -105,14 +104,10 @@ osgiJdbcServiceVersion=1.1.0 paxJdbcVersion=1.5.3 # Test dependency versions -assertjVersion=3.24.2 dom4jOsgiVersion = 2.1.3_1 hamcrestVersion=2.2 hsqldbVersion=2.7.2 jimfsVersion = 1.3.0 -junit5Version=5.10.0 -mockitoKotlinVersion=4.1.0 -mockitoVersion=5.5.0 osgiTestJunit5Version=1.2.1 postgresDriverVersion=42.6.0 mssqlDriverVersion=11.2.3.jre17 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 00000000000..aa4ffa21f7c --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,34 @@ +[versions] +kotlinVersion = "1.8.21" + +# Testing +assertjVersion = "3.24.2" +junitVersion = "5.10.0" +mockitoVersion = "5.5.0" +mockitoKotlinVersion = "4.1.0" + +[libraries] +assertj-core = { group = "org.assertj", name = "assertj-core", version.ref = "assertjVersion" } +junit = { group = "org.junit.jupiter", name = "junit-jupiter", version.ref = "junitVersion" } +junit-api = { group = "org.junit.jupiter", name = "junit-jupiter-api", version.ref = "junitVersion" } +junit-params = { group = "org.junit.jupiter", name = "junit-jupiter-params", version.ref = "junitVersion" } +junit-engine = { group = "org.junit.jupiter", name = "junit-jupiter-engine", version.ref = "junitVersion" } +junit-platform = { group = "org.junit.platform", name = "junit-platform-launcher" } +kotlin-stdlib = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib", version.ref = "kotlinVersion" } +kotlin-stdlib-common = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib-common", version.ref = "kotlinVersion" } +kotlin-stdlib-jdk7 = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib-jdk7", version.ref = "kotlinVersion" } +kotlin-stdlib-jdk8 = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib-jdk8", version.ref = "kotlinVersion" } +kotlin-osgi-bundle = { group = "org.jetbrains.kotlin", name = "kotlin-osgi-bundle", version.ref = "kotlinVersion" } +kotlin-reflect= { group = "org.jetbrains.kotlin", name = "kotlin-reflect", version.ref = "kotlinVersion" } +kotlin-test = { group = "org.jetbrains.kotlin", name = "kotlin-test", version.ref = "kotlinVersion" } +mockito-core = { group = "org.mockito", name = "mockito-core", version.ref = "mockitoVersion" } +mockito-kotlin = { group = "org.mockito.kotlin", name = "mockito-kotlin", version.ref = "mockitoKotlinVersion" } + +[bundles] +test = ["junit", "junit-api", "junit-params", "mockito-core", "mockito-kotlin", "assertj-core", "kotlin-test"] +test-runtime = ["junit-engine", "junit-platform"] + +[plugins] +kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlinVersion" } +kotlin-allopen = { id = "org.jetbrains.kotlin.plugin.allopen", version.ref = "kotlinVersion" } +kotlin-jpa = { id = "org.jetbrains.kotlin.plugin.jpa", version.ref = "kotlinVersion" } \ No newline at end of file diff --git a/libs/application/application-impl/build.gradle b/libs/application/application-impl/build.gradle index 8439d3527d8..cbd6ded6b32 100644 --- a/libs/application/application-impl/build.gradle +++ b/libs/application/application-impl/build.gradle @@ -21,8 +21,5 @@ dependencies { implementation "com.fasterxml.jackson.module:jackson-module-kotlin:$jacksonVersion" implementation 'org.slf4j:slf4j-api' - testImplementation "org.assertj:assertj-core:$assertjVersion" testImplementation "com.google.jimfs:jimfs:$jimfsVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/libs/cache/cache-caffeine/build.gradle b/libs/cache/cache-caffeine/build.gradle index 7ad4e0b94b3..b4f97ecb550 100644 --- a/libs/cache/cache-caffeine/build.gradle +++ b/libs/cache/cache-caffeine/build.gradle @@ -18,8 +18,5 @@ dependencies { implementation 'org.jetbrains.kotlin:kotlin-osgi-bundle' implementation 'org.slf4j:slf4j-api' - testImplementation "org.assertj:assertj-core:$assertjVersion" testImplementation "com.google.jimfs:jimfs:$jimfsVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/libs/chunking/chunking-core/build.gradle b/libs/chunking/chunking-core/build.gradle index 01482e889b7..9304fe43406 100644 --- a/libs/chunking/chunking-core/build.gradle +++ b/libs/chunking/chunking-core/build.gradle @@ -21,9 +21,6 @@ dependencies { implementation project(':libs:crypto:crypto-core') implementation project(':libs:utilities') - testImplementation "org.assertj:assertj-core:$assertjVersion" testImplementation "com.google.jimfs:jimfs:$jimfsVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testRuntimeOnly "org.slf4j:slf4j-simple:$slf4jVersion" } diff --git a/libs/configuration/configuration-core/build.gradle b/libs/configuration/configuration-core/build.gradle index fd4a7467658..a0305b60331 100644 --- a/libs/configuration/configuration-core/build.gradle +++ b/libs/configuration/configuration-core/build.gradle @@ -20,8 +20,4 @@ dependencies { implementation 'org.jetbrains.kotlin:kotlin-osgi-bundle' implementation project(":libs:crypto:crypto-core") - - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/libs/configuration/configuration-datamodel/build.gradle b/libs/configuration/configuration-datamodel/build.gradle index 3da45883147..0bb7252fb23 100644 --- a/libs/configuration/configuration-datamodel/build.gradle +++ b/libs/configuration/configuration-datamodel/build.gradle @@ -22,9 +22,6 @@ dependencies { integrationTestRuntimeOnly "org.hsqldb:hsqldb:$hsqldbVersion" integrationTestRuntimeOnly "org.postgresql:postgresql:$postgresDriverVersion" - - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } tasks.named('jar', Jar) { diff --git a/libs/configuration/configuration-merger/build.gradle b/libs/configuration/configuration-merger/build.gradle index a9a64ac22ca..14f294d23ee 100644 --- a/libs/configuration/configuration-merger/build.gradle +++ b/libs/configuration/configuration-merger/build.gradle @@ -20,7 +20,4 @@ dependencies { implementation 'org.jetbrains.kotlin:kotlin-osgi-bundle' implementation 'org.slf4j:slf4j-api' - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/libs/configuration/configuration-validation/build.gradle b/libs/configuration/configuration-validation/build.gradle index fb3514b493f..f5c119ec9e1 100644 --- a/libs/configuration/configuration-validation/build.gradle +++ b/libs/configuration/configuration-validation/build.gradle @@ -27,7 +27,4 @@ dependencies { because "Version bundled with current version of 'com.networknt:json-schema-validator' does not have OSGi manifest." } } - - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } \ No newline at end of file diff --git a/libs/crypto/cipher-suite-impl/build.gradle b/libs/crypto/cipher-suite-impl/build.gradle index 7190f2b0a8a..80e75ad92de 100644 --- a/libs/crypto/cipher-suite-impl/build.gradle +++ b/libs/crypto/cipher-suite-impl/build.gradle @@ -21,9 +21,4 @@ dependencies { api project(':libs:crypto:crypto-impl') api project(':libs:sandbox-types') implementation project(':libs:utilities') - - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/libs/crypto/cipher-suite/build.gradle b/libs/crypto/cipher-suite/build.gradle index 980ccccad82..12f79974fb1 100644 --- a/libs/crypto/cipher-suite/build.gradle +++ b/libs/crypto/cipher-suite/build.gradle @@ -20,10 +20,5 @@ dependencies { api "org.bouncycastle:bcprov-jdk18on:$bouncycastleVersion" api "org.bouncycastle:bcpkix-jdk18on:$bouncycastleVersion" - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" - testImplementation "org.junit.jupiter:junit-jupiter-api:$junit5Version" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/libs/crypto/crypto-config-impl/build.gradle b/libs/crypto/crypto-config-impl/build.gradle index c06f3fb0fc5..00b58cf7a67 100644 --- a/libs/crypto/crypto-config-impl/build.gradle +++ b/libs/crypto/crypto-config-impl/build.gradle @@ -18,9 +18,5 @@ dependencies { implementation project(':libs:crypto:cipher-suite') implementation project(":libs:crypto:crypto-core") - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation project(':libs:configuration:configuration-validation') } diff --git a/libs/crypto/crypto-core/build.gradle b/libs/crypto/crypto-core/build.gradle index 130b3de88d2..4118e4f4135 100644 --- a/libs/crypto/crypto-core/build.gradle +++ b/libs/crypto/crypto-core/build.gradle @@ -20,11 +20,7 @@ dependencies { api "net.corda:corda-crypto-extensions" testImplementation "javax.persistence:javax.persistence-api" - testImplementation "org.assertj:assertj-core:$assertjVersion" testImplementation "org.hibernate:hibernate-core:$hibernateVersion" - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation project(":testing:test-utilities") } diff --git a/libs/crypto/crypto-flow/build.gradle b/libs/crypto/crypto-flow/build.gradle index a82df05f80b..6057142ea67 100644 --- a/libs/crypto/crypto-flow/build.gradle +++ b/libs/crypto/crypto-flow/build.gradle @@ -17,11 +17,6 @@ dependencies { api project(':libs:crypto:cipher-suite') implementation project(":libs:crypto:cipher-suite-impl") - - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/libs/crypto/crypto-impl/build.gradle b/libs/crypto/crypto-impl/build.gradle index 65dbfd6c855..0425caf7000 100644 --- a/libs/crypto/crypto-impl/build.gradle +++ b/libs/crypto/crypto-impl/build.gradle @@ -29,11 +29,7 @@ dependencies { testImplementation project(":testing:layered-property-map-testkit") testImplementation "javax.persistence:javax.persistence-api" - testImplementation "org.assertj:assertj-core:$assertjVersion" testImplementation "org.hibernate:hibernate-core:$hibernateVersion" - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } tasks.named('jar', Jar) { diff --git a/libs/crypto/crypto-serialization-impl/build.gradle b/libs/crypto/crypto-serialization-impl/build.gradle index 1c66ac697ba..66b1f5ca614 100644 --- a/libs/crypto/crypto-serialization-impl/build.gradle +++ b/libs/crypto/crypto-serialization-impl/build.gradle @@ -19,9 +19,4 @@ dependencies { implementation project(":libs:crypto:crypto-core") implementation project(':libs:serialization:serialization-internal') implementation project(":libs:utilities") - - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/libs/crypto/delegated-signing/build.gradle b/libs/crypto/delegated-signing/build.gradle index 561accbd5f1..e426152d813 100644 --- a/libs/crypto/delegated-signing/build.gradle +++ b/libs/crypto/delegated-signing/build.gradle @@ -10,8 +10,6 @@ dependencies { implementation 'net.corda:corda-base' implementation "net.corda:corda-crypto" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } description 'Crypto Delegated Signing' diff --git a/libs/crypto/merkle-impl/build.gradle b/libs/crypto/merkle-impl/build.gradle index 4543500a94a..7ad5d50bdaa 100644 --- a/libs/crypto/merkle-impl/build.gradle +++ b/libs/crypto/merkle-impl/build.gradle @@ -23,10 +23,6 @@ dependencies { implementation project(":libs:crypto:crypto-core") implementation project(':libs:sandbox-types') - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.junit.jupiter:junit-jupiter-api:$junit5Version" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation project(":libs:crypto:cipher-suite-impl") testImplementation project(":testing:test-utilities") diff --git a/libs/db/db-admin-impl/build.gradle b/libs/db/db-admin-impl/build.gradle index 690e5138f88..3039b61a224 100644 --- a/libs/db/db-admin-impl/build.gradle +++ b/libs/db/db-admin-impl/build.gradle @@ -27,9 +27,6 @@ dependencies { runtimeOnly "commons-beanutils:commons-beanutils:$beanutilsVersion" - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testRuntimeOnly "org.slf4j:slf4j-simple:$slf4jVersion" integrationTestRuntimeOnly "org.hsqldb:hsqldb:$hsqldbVersion" diff --git a/libs/db/db-core/build.gradle b/libs/db/db-core/build.gradle index b5a333f839c..b496999e12a 100644 --- a/libs/db/db-core/build.gradle +++ b/libs/db/db-core/build.gradle @@ -18,9 +18,6 @@ dependencies { api "com.zaxxer:HikariCP:$hikariCpVersion" - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" integrationTestRuntimeOnly 'org.osgi:osgi.core' integrationTestRuntimeOnly "org.hsqldb:hsqldb:$hsqldbVersion" diff --git a/libs/db/db-orm-impl/build.gradle b/libs/db/db-orm-impl/build.gradle index 228942fa937..96d4ee0a510 100644 --- a/libs/db/db-orm-impl/build.gradle +++ b/libs/db/db-orm-impl/build.gradle @@ -33,9 +33,6 @@ dependencies { implementation project(":libs:db:db-orm") implementation project(":libs:utilities") - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testRuntimeOnly "org.postgresql:postgresql:$postgresDriverVersion" diff --git a/libs/db/db-orm/build.gradle b/libs/db/db-orm/build.gradle index 708a5df7e95..b71b7eb6796 100644 --- a/libs/db/db-orm/build.gradle +++ b/libs/db/db-orm/build.gradle @@ -14,7 +14,4 @@ dependencies { compileOnly "org.osgi:osgi.annotation" api "javax.persistence:javax.persistence-api" - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } \ No newline at end of file diff --git a/libs/external-messaging/build.gradle b/libs/external-messaging/build.gradle index 058908b89b9..f4ea285dba2 100644 --- a/libs/external-messaging/build.gradle +++ b/libs/external-messaging/build.gradle @@ -17,8 +17,5 @@ dependencies { implementation project(":libs:virtual-node:virtual-node-info") implementation project(":libs:configuration:configuration-core") - testImplementation "org.assertj:assertj-core:$assertjVersion" testImplementation "com.google.jimfs:jimfs:$jimfsVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/libs/flows/external-event-responses-impl/build.gradle b/libs/flows/external-event-responses-impl/build.gradle index 27f4d8eb6ee..a4bc0571d29 100644 --- a/libs/flows/external-event-responses-impl/build.gradle +++ b/libs/flows/external-event-responses-impl/build.gradle @@ -17,9 +17,6 @@ dependencies { implementation project(":libs:messaging:messaging") implementation project(":libs:utilities") implementation project(":libs:serialization:serialization-avro") - - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } description 'Flow External Events Library Implementation' diff --git a/libs/flows/session-manager-impl/build.gradle b/libs/flows/session-manager-impl/build.gradle index 010d47f9deb..6915c2b3444 100644 --- a/libs/flows/session-manager-impl/build.gradle +++ b/libs/flows/session-manager-impl/build.gradle @@ -23,9 +23,6 @@ dependencies { implementation "net.corda:corda-config-schema" implementation "net.corda:corda-topic-schema" - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation project(":testing:flow:flow-utilities") testImplementation project(":libs:flows:flow-utils") } diff --git a/libs/kotlin-heap-fix/build.gradle b/libs/kotlin-heap-fix/build.gradle index 57773064111..c54a8ede249 100644 --- a/libs/kotlin-heap-fix/build.gradle +++ b/libs/kotlin-heap-fix/build.gradle @@ -14,7 +14,7 @@ dependencies { processResources { filesMatching('**/configuration.properties') { - expand([ 'kotlinVersion': kotlinVersion ]) + expand([ 'kotlinVersion': libs.versions.kotlinVersion.get() ]) } } diff --git a/libs/kotlin-reflection/build.gradle b/libs/kotlin-reflection/build.gradle index aea5cfdd89e..ad9593eb061 100644 --- a/libs/kotlin-reflection/build.gradle +++ b/libs/kotlin-reflection/build.gradle @@ -45,17 +45,18 @@ dependencies { implementation platform("net.corda:corda-api:$cordaApiVersion") testCompileOnly 'org.jetbrains:annotations' - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.junit.jupiter:junit-jupiter-params:$junit5Version" + testImplementation libs.assertj.core + testImplementation libs.junit.params + testRuntimeOnly libs.junit.engine testRuntimeOnly "org.jetbrains.kotlinx:kotlinx-metadata-jvm:$kotlinMetadataVersion" testRuntimeOnly "org.ow2.asm:asm:$asmVersion" integrationTestImplementation project(':libs:kotlin-reflection:kotlin-reflection-test-example') integrationTestImplementation 'org.slf4j:slf4j-api' integrationTestImplementation "org.apache.felix:org.apache.felix.framework:$felixVersion" - integrationTestImplementation "org.junit.jupiter:junit-jupiter:$junit5Version" - integrationTestRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junit5Version" - integrationTestRuntimeOnly 'org.junit.platform:junit-platform-launcher' + integrationTestImplementation libs.junit + integrationTestRuntimeOnly libs.junit.engine + integrationTestRuntimeOnly libs.junit.platform integrationTestRuntimeOnly "org.slf4j:slf4j-simple:$slf4jVersion" } diff --git a/libs/layered-property-map/build.gradle b/libs/layered-property-map/build.gradle index 066191384d9..6e1dd26671c 100644 --- a/libs/layered-property-map/build.gradle +++ b/libs/layered-property-map/build.gradle @@ -18,7 +18,6 @@ dependencies { implementation "net.corda:corda-serialization" implementation project(':libs:crypto:cipher-suite') - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" testImplementation "net.corda:corda-crypto" testImplementation project(':libs:crypto:crypto-core') testImplementation project(":testing:test-utilities") diff --git a/libs/ledger/ledger-common-data/build.gradle b/libs/ledger/ledger-common-data/build.gradle index f44e7013a6b..b87724265ca 100644 --- a/libs/ledger/ledger-common-data/build.gradle +++ b/libs/ledger/ledger-common-data/build.gradle @@ -26,13 +26,8 @@ dependencies { implementation project(':libs:serialization:serialization-internal') implementation project(':libs:utilities') - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" - testImplementation project(':testing:test-serialization') testImplementation project(':testing:kryo-serialization-testkit') testImplementation project(':testing:ledger:ledger-common-base-test') - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/libs/ledger/ledger-utxo-data/build.gradle b/libs/ledger/ledger-utxo-data/build.gradle index 18f85eb0107..a4672b5a5ce 100644 --- a/libs/ledger/ledger-utxo-data/build.gradle +++ b/libs/ledger/ledger-utxo-data/build.gradle @@ -22,10 +22,6 @@ dependencies { implementation project(':libs:serialization:serialization-internal') implementation project(':libs:utilities') - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" - testImplementation project(':testing:ledger:ledger-common-base-test') testImplementation project(':testing:ledger:ledger-utxo-testkit') testImplementation project(':testing:test-serialization') diff --git a/libs/ledger/ledger-utxo-transaction-verifier/build.gradle b/libs/ledger/ledger-utxo-transaction-verifier/build.gradle index 4b333a6e799..f9695f2b175 100644 --- a/libs/ledger/ledger-utxo-transaction-verifier/build.gradle +++ b/libs/ledger/ledger-utxo-transaction-verifier/build.gradle @@ -24,7 +24,4 @@ dependencies { testImplementation project(':testing:ledger:ledger-utxo-testkit') - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" } \ No newline at end of file diff --git a/libs/lifecycle/lifecycle-impl/build.gradle b/libs/lifecycle/lifecycle-impl/build.gradle index 72593d0a081..b2cccd5dec7 100644 --- a/libs/lifecycle/lifecycle-impl/build.gradle +++ b/libs/lifecycle/lifecycle-impl/build.gradle @@ -20,6 +20,4 @@ dependencies { testImplementation project(":testing:test-utilities") testImplementation project(":libs:lifecycle:lifecycle-test-impl") - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/libs/lifecycle/lifecycle-test-impl/build.gradle b/libs/lifecycle/lifecycle-test-impl/build.gradle index bb5dd56fc7d..d4c91206f48 100644 --- a/libs/lifecycle/lifecycle-test-impl/build.gradle +++ b/libs/lifecycle/lifecycle-test-impl/build.gradle @@ -16,9 +16,9 @@ dependencies { implementation platform("net.corda:corda-api:$cordaApiVersion") implementation 'org.jetbrains.kotlin:kotlin-osgi-bundle' - implementation "org.assertj:assertj-core:$assertjVersion" - implementation "org.mockito:mockito-core:$mockitoVersion" - implementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" + implementation libs.assertj.core + implementation libs.mockito.core + implementation libs.mockito.kotlin implementation 'net.corda:corda-base' implementation 'org.slf4j:slf4j-api' } diff --git a/libs/lifecycle/lifecycle/build.gradle b/libs/lifecycle/lifecycle/build.gradle index 08fbcd81348..66b8b0d480c 100644 --- a/libs/lifecycle/lifecycle/build.gradle +++ b/libs/lifecycle/lifecycle/build.gradle @@ -14,6 +14,4 @@ dependencies { implementation 'net.corda:corda-base' implementation 'org.slf4j:slf4j-api' - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/libs/lifecycle/registry/build.gradle b/libs/lifecycle/registry/build.gradle index 85eef106120..bd27b877fb1 100644 --- a/libs/lifecycle/registry/build.gradle +++ b/libs/lifecycle/registry/build.gradle @@ -14,6 +14,4 @@ dependencies { implementation 'org.slf4j:slf4j-api' implementation project(":libs:lifecycle:lifecycle") - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/libs/membership/membership-common/build.gradle b/libs/membership/membership-common/build.gradle index 73c7f5ab3c9..4295d8e35d1 100644 --- a/libs/membership/membership-common/build.gradle +++ b/libs/membership/membership-common/build.gradle @@ -23,7 +23,5 @@ dependencies { implementation project(':libs:configuration:configuration-core') implementation project(':libs:serialization:serialization-avro') - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation project(":testing:test-utilities") } diff --git a/libs/membership/membership-datamodel/build.gradle b/libs/membership/membership-datamodel/build.gradle index 5940b37729c..df48b0dcb74 100644 --- a/libs/membership/membership-datamodel/build.gradle +++ b/libs/membership/membership-datamodel/build.gradle @@ -20,9 +20,6 @@ dependencies { implementation project(":libs:db:db-orm") testImplementation 'net.corda:corda-avro-schema' - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } // This is required for Hibernate Proxy generation. Without it OSGi will report: diff --git a/libs/membership/membership-impl/build.gradle b/libs/membership/membership-impl/build.gradle index 094eb05390e..e8ae94b9464 100644 --- a/libs/membership/membership-impl/build.gradle +++ b/libs/membership/membership-impl/build.gradle @@ -32,8 +32,4 @@ dependencies { testImplementation project(':testing:test-serialization') testImplementation project(':libs:serialization:serialization-amqp') testImplementation project(":testing:test-utilities") - - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/libs/membership/network-info/build.gradle b/libs/membership/network-info/build.gradle index 61e1f83b15f..bd13cd082c1 100644 --- a/libs/membership/network-info/build.gradle +++ b/libs/membership/network-info/build.gradle @@ -24,7 +24,4 @@ dependencies { testImplementation project(":testing:test-utilities") - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/libs/membership/schema-validation/build.gradle b/libs/membership/schema-validation/build.gradle index c75d043610b..39e33af34ba 100644 --- a/libs/membership/schema-validation/build.gradle +++ b/libs/membership/schema-validation/build.gradle @@ -22,8 +22,4 @@ dependencies { } } implementation project(':libs:membership:membership-common') - - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" } \ No newline at end of file diff --git a/libs/messaging/db-message-bus-impl/build.gradle b/libs/messaging/db-message-bus-impl/build.gradle index 10e4b05b50c..d5b7507f3fc 100644 --- a/libs/messaging/db-message-bus-impl/build.gradle +++ b/libs/messaging/db-message-bus-impl/build.gradle @@ -36,9 +36,6 @@ dependencies { runtimeOnly "com.sun.activation:javax.activation:$activationVersion" testImplementation project(":testing:test-utilities") - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testRuntimeOnly 'org.osgi:osgi.core' diff --git a/libs/messaging/db-topic-admin-impl/build.gradle b/libs/messaging/db-topic-admin-impl/build.gradle index 7dcbad3cce7..f9691a5fdaf 100644 --- a/libs/messaging/db-topic-admin-impl/build.gradle +++ b/libs/messaging/db-topic-admin-impl/build.gradle @@ -26,8 +26,6 @@ dependencies { implementation project(":libs:messaging:db-message-bus-datamodel") implementation project(":libs:messaging:db-message-bus-impl") - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" integrationTestImplementation project(":libs:db:db-admin") integrationTestImplementation project(":libs:db:db-admin-impl") diff --git a/libs/messaging/kafka-message-bus-impl/build.gradle b/libs/messaging/kafka-message-bus-impl/build.gradle index 8acab0a36cd..fc5045f472f 100644 --- a/libs/messaging/kafka-message-bus-impl/build.gradle +++ b/libs/messaging/kafka-message-bus-impl/build.gradle @@ -34,9 +34,6 @@ dependencies { implementation "com.typesafe:config:$typeSafeConfigVersion" - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation project(":testing:test-utilities") testRuntimeOnly 'org.osgi:osgi.core' diff --git a/libs/messaging/kafka-topic-admin-impl/build.gradle b/libs/messaging/kafka-topic-admin-impl/build.gradle index 3aae8c6f098..490f4316097 100644 --- a/libs/messaging/kafka-topic-admin-impl/build.gradle +++ b/libs/messaging/kafka-topic-admin-impl/build.gradle @@ -21,9 +21,6 @@ dependencies { implementation project(":libs:messaging:topic-admin") implementation project(":libs:utilities") - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" - testRuntimeOnly 'org.osgi:osgi.core' } diff --git a/libs/messaging/messaging-impl/build.gradle b/libs/messaging/messaging-impl/build.gradle index c918d4c3701..836a5c999a0 100644 --- a/libs/messaging/messaging-impl/build.gradle +++ b/libs/messaging/messaging-impl/build.gradle @@ -37,9 +37,6 @@ dependencies { implementation "com.typesafe:config:$typeSafeConfigVersion" implementation "com.google.guava:guava:$guavaVersion" - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation project(":testing:test-utilities") testImplementation project(':libs:platform-info') testImplementation project(':libs:web:web-impl') diff --git a/libs/messaging/messaging-impl/src/main/kotlin/net/corda/messaging/mediator/MultiSourceEventMediatorImpl.kt b/libs/messaging/messaging-impl/src/main/kotlin/net/corda/messaging/mediator/MultiSourceEventMediatorImpl.kt index e60852fbd9d..9ee3826b9af 100644 --- a/libs/messaging/messaging-impl/src/main/kotlin/net/corda/messaging/mediator/MultiSourceEventMediatorImpl.kt +++ b/libs/messaging/messaging-impl/src/main/kotlin/net/corda/messaging/mediator/MultiSourceEventMediatorImpl.kt @@ -27,6 +27,7 @@ import org.slf4j.LoggerFactory import java.lang.Thread.sleep import java.time.Duration import java.util.UUID +import java.util.concurrent.CompletionException import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.TimeUnit import java.util.concurrent.atomic.AtomicBoolean @@ -112,10 +113,11 @@ class MultiSourceEventMediatorImpl( consumer.subscribe() } pollAndProcessEvents(consumer) + attempts = 0 } catch (exception: Exception) { - when (exception) { + val cause = if (exception is CompletionException) exception.cause else exception + when (cause) { is CordaMessageAPIIntermittentException -> { - attempts++ log.warn( "Multi-source event mediator ${config.name} failed to process records, " + "Retrying poll and process. Attempts: $attempts.") diff --git a/libs/messaging/messaging-impl/src/test/kotlin/net/corda/messaging/mediator/MultiSourceEventMediatorImplTest.kt b/libs/messaging/messaging-impl/src/test/kotlin/net/corda/messaging/mediator/MultiSourceEventMediatorImplTest.kt index b446a17f605..aecaf5831c4 100644 --- a/libs/messaging/messaging-impl/src/test/kotlin/net/corda/messaging/mediator/MultiSourceEventMediatorImplTest.kt +++ b/libs/messaging/messaging-impl/src/test/kotlin/net/corda/messaging/mediator/MultiSourceEventMediatorImplTest.kt @@ -43,7 +43,7 @@ import java.util.concurrent.atomic.AtomicInteger class MultiSourceEventMediatorImplTest { companion object { - private const val TEST_TIMEOUT_SECONDS = 20L + private const val TEST_TIMEOUT_SECONDS = 2000L private const val TEST_PROCESSOR_RETRIES = 3 const val KEY1 = "key1" const val KEY2 = "key2" @@ -93,7 +93,7 @@ class MultiSourceEventMediatorImplTest { } val messageRouter = MessageRouter { _ -> - RoutingDestination.routeTo(messagingClient, "endpoint", RoutingDestination.Type.ASYNCHRONOUS) + RoutingDestination.routeTo(messagingClient, "endpoint", RoutingDestination.Type.SYNCHRONOUS) } whenever(messageRouterFactory.create(any())).thenReturn(messageRouter) @@ -176,8 +176,8 @@ class MultiSourceEventMediatorImplTest { verify(messagingClient, times(events.size)).send(any()) } -// @Test - fun `mediator retries after intermittent exceptions`() { + @Test + fun `mediator retries after intermittent exceptions wrapped in completion exception`() { val event1 = cordaConsumerRecords(KEY1, "event1") val sendCount = AtomicInteger(0) val errorsCount = TEST_PROCESSOR_RETRIES + 1 @@ -202,9 +202,9 @@ class MultiSourceEventMediatorImplTest { waitWhile(Duration.ofSeconds(TEST_TIMEOUT_SECONDS)) { sendCount.get() < expectedProcessingCount } mediator.close() - verify(mediatorConsumerFactory, times(2)).create(any>()) - verify(messagingClientFactory, times(2)).create(any()) - verify(messageRouterFactory, times(2)).create(any()) + verify(mediatorConsumerFactory, times(1)).create(any>()) + verify(messagingClientFactory, times(1)).create(any()) + verify(messageRouterFactory, times(1)).create(any()) verify(messageProcessor, times(expectedProcessingCount)).onNext(anyOrNull(), any()) verify(consumer, atLeast(expectedProcessingCount)).poll(any()) verify(messagingClient, times(expectedProcessingCount)).send(any()) diff --git a/libs/messaging/messaging/build.gradle b/libs/messaging/messaging/build.gradle index 31e52cedd13..8981a0c2248 100644 --- a/libs/messaging/messaging/build.gradle +++ b/libs/messaging/messaging/build.gradle @@ -29,9 +29,6 @@ dependencies { implementation project(":libs:messaging:message-bus") implementation project(":libs:configuration:configuration-core") implementation project(":libs:serialization:serialization-avro") - - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } description 'Messaging API' diff --git a/libs/messaging/messaging/src/main/kotlin/net/corda/messaging/api/constants/WorkerRPCPaths.kt b/libs/messaging/messaging/src/main/kotlin/net/corda/messaging/api/constants/WorkerRPCPaths.kt index f2b82e48308..7faa586a8e9 100644 --- a/libs/messaging/messaging/src/main/kotlin/net/corda/messaging/api/constants/WorkerRPCPaths.kt +++ b/libs/messaging/messaging/src/main/kotlin/net/corda/messaging/api/constants/WorkerRPCPaths.kt @@ -12,4 +12,5 @@ object WorkerRPCPaths { const val UNIQUENESS_PATH = "/uniqueness-checker" const val VERIFICATION_PATH = "/verification" const val TOKEN_SELECTION_PATH = "/token-selection" + const val P2P_LINK_MANAGER_PATH = "/p2p-link-manager" } diff --git a/libs/metrics/build.gradle b/libs/metrics/build.gradle index 8bb00d715ec..2940fc7273f 100644 --- a/libs/metrics/build.gradle +++ b/libs/metrics/build.gradle @@ -20,6 +20,5 @@ dependencies { exclude group: 'org.latencyutils', module: 'LatencyUtils' } - testImplementation "org.assertj:assertj-core:$assertjVersion" testRuntimeOnly "org.slf4j:slf4j-simple:$slf4jVersion" } diff --git a/libs/p2p-crypto/build.gradle b/libs/p2p-crypto/build.gradle index 58155829ff3..9e04224e88b 100644 --- a/libs/p2p-crypto/build.gradle +++ b/libs/p2p-crypto/build.gradle @@ -20,8 +20,6 @@ dependencies { api "org.bouncycastle:bcpkix-jdk18on:$bouncycastleVersion" testImplementation project(':libs:crypto:cipher-suite') - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" integrationTestImplementation project(":testing:p2p:certificates") } diff --git a/libs/packaging/packaging-core/build.gradle b/libs/packaging/packaging-core/build.gradle index d671fec2d6c..f7999cf6d9b 100644 --- a/libs/packaging/packaging-core/build.gradle +++ b/libs/packaging/packaging-core/build.gradle @@ -16,7 +16,4 @@ dependencies { implementation project(':libs:crypto:crypto-core') - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/libs/packaging/packaging-verify/build.gradle b/libs/packaging/packaging-verify/build.gradle index 474b334c840..ed84c018358 100644 --- a/libs/packaging/packaging-verify/build.gradle +++ b/libs/packaging/packaging-verify/build.gradle @@ -27,6 +27,4 @@ dependencies { testImplementation project(':testing:test-utilities') testImplementation project(':testing:packaging-test-utilities') - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/libs/packaging/packaging/build.gradle b/libs/packaging/packaging/build.gradle index 4b26a6a04df..590ffb0c91c 100644 --- a/libs/packaging/packaging/build.gradle +++ b/libs/packaging/packaging/build.gradle @@ -47,9 +47,6 @@ dependencies { implementation "com.fasterxml.jackson.module:jackson-module-kotlin:$jacksonVersion" testImplementation 'org.osgi:osgi.core' - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation project(':libs:crypto:cipher-suite') testImplementation project(":testing:test-utilities") testImplementation project(":testing:packaging-test-utilities") diff --git a/libs/permissions/permission-cache-common/build.gradle b/libs/permissions/permission-cache-common/build.gradle index 9c26b627941..f10a578b870 100644 --- a/libs/permissions/permission-cache-common/build.gradle +++ b/libs/permissions/permission-cache-common/build.gradle @@ -15,7 +15,5 @@ dependencies { implementation 'net.corda:corda-base' implementation project(":libs:messaging:messaging") - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation "net.corda:corda-avro-schema" } diff --git a/libs/permissions/permission-endpoint/build.gradle b/libs/permissions/permission-endpoint/build.gradle index d689d4cfca9..13cc353c288 100644 --- a/libs/permissions/permission-endpoint/build.gradle +++ b/libs/permissions/permission-endpoint/build.gradle @@ -19,7 +19,4 @@ dependencies { api project(":libs:rest:rest") implementation project(":libs:permissions:permission-manager") implementation project(":libs:lifecycle:lifecycle") - - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/libs/permissions/permission-management-cache-impl/build.gradle b/libs/permissions/permission-management-cache-impl/build.gradle index 7b4ca8dac54..7f431a72069 100644 --- a/libs/permissions/permission-management-cache-impl/build.gradle +++ b/libs/permissions/permission-management-cache-impl/build.gradle @@ -20,6 +20,4 @@ dependencies { implementation project(":libs:permissions:permission-management-cache") implementation project(":libs:permissions:permission-cache-common") - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/libs/permissions/permission-manager-impl/build.gradle b/libs/permissions/permission-manager-impl/build.gradle index 612a2280e0c..dca851025a5 100644 --- a/libs/permissions/permission-manager-impl/build.gradle +++ b/libs/permissions/permission-manager-impl/build.gradle @@ -28,6 +28,4 @@ dependencies { implementation project(":libs:cache:cache-caffeine") implementation project(":libs:crypto:crypto-core") - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } \ No newline at end of file diff --git a/libs/permissions/permission-password/build.gradle b/libs/permissions/permission-password/build.gradle index f291a96a9ea..fdea716b68b 100644 --- a/libs/permissions/permission-password/build.gradle +++ b/libs/permissions/permission-password/build.gradle @@ -18,6 +18,5 @@ dependencies { implementation project(":libs:crypto:crypto-core") implementation "org.apache.commons:commons-text:$commonsTextVersion" - testImplementation "org.assertj:assertj-core:$assertjVersion" testImplementation project(":libs:crypto:cipher-suite-impl") } diff --git a/libs/permissions/permission-storage-reader-impl/build.gradle b/libs/permissions/permission-storage-reader-impl/build.gradle index 87d342e3685..cbd6af73794 100644 --- a/libs/permissions/permission-storage-reader-impl/build.gradle +++ b/libs/permissions/permission-storage-reader-impl/build.gradle @@ -29,6 +29,4 @@ dependencies { implementation "javax.persistence:javax.persistence-api" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/libs/permissions/permission-storage-writer-impl/build.gradle b/libs/permissions/permission-storage-writer-impl/build.gradle index 4a55f2d1afb..066a4e8732f 100644 --- a/libs/permissions/permission-storage-writer-impl/build.gradle +++ b/libs/permissions/permission-storage-writer-impl/build.gradle @@ -27,6 +27,4 @@ dependencies { implementation "javax.persistence:javax.persistence-api" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/libs/permissions/permission-validation-cache-impl/build.gradle b/libs/permissions/permission-validation-cache-impl/build.gradle index 0354424fb99..01054b47c75 100644 --- a/libs/permissions/permission-validation-cache-impl/build.gradle +++ b/libs/permissions/permission-validation-cache-impl/build.gradle @@ -20,6 +20,4 @@ dependencies { implementation project(":libs:permissions:permission-validation-cache") implementation project(":libs:permissions:permission-cache-common") - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/libs/permissions/permission-validation-impl/build.gradle b/libs/permissions/permission-validation-impl/build.gradle index 84a88393279..71e8b39885f 100644 --- a/libs/permissions/permission-validation-impl/build.gradle +++ b/libs/permissions/permission-validation-impl/build.gradle @@ -26,7 +26,4 @@ dependencies { implementation "net.corda:corda-avro-schema" implementation "net.corda:corda-topic-schema" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" } diff --git a/libs/platform-info/build.gradle b/libs/platform-info/build.gradle index c1670ff9c83..22963b03021 100644 --- a/libs/platform-info/build.gradle +++ b/libs/platform-info/build.gradle @@ -13,7 +13,5 @@ dependencies { implementation "net.corda:corda-base" implementation 'org.jetbrains.kotlin:kotlin-osgi-bundle' - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation "org.osgi:osgi.core" } diff --git a/libs/rest/json-serialization/build.gradle b/libs/rest/json-serialization/build.gradle index 9f0e47aa469..792e770c3c8 100644 --- a/libs/rest/json-serialization/build.gradle +++ b/libs/rest/json-serialization/build.gradle @@ -19,6 +19,4 @@ dependencies { implementation "org.slf4j:slf4j-api:$slf4jVersion" implementation project(":libs:serialization:json-serializers") implementation project(':libs:rest:rest') - - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" } diff --git a/libs/rest/rbac-security-manager/build.gradle b/libs/rest/rbac-security-manager/build.gradle index 7755853fd1e..a18a1f8e990 100644 --- a/libs/rest/rbac-security-manager/build.gradle +++ b/libs/rest/rbac-security-manager/build.gradle @@ -18,6 +18,4 @@ dependencies { implementation project(":libs:permissions:permission-manager") implementation project(":libs:permissions:permission-validation") - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } \ No newline at end of file diff --git a/libs/rest/rest-client/build.gradle b/libs/rest/rest-client/build.gradle index 0f6373830b5..5ae43fa907d 100644 --- a/libs/rest/rest-client/build.gradle +++ b/libs/rest/rest-client/build.gradle @@ -29,10 +29,6 @@ dependencies { implementation "com.konghq:unirest-objectmapper-jackson:$unirestVersion" implementation "com.fasterxml.jackson.module:jackson-module-kotlin:$jacksonVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" - - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" testImplementation project(":testing:test-utilities") testImplementation project(":libs:rest:rest-test-common") diff --git a/libs/rest/rest-common/build.gradle b/libs/rest/rest-common/build.gradle index 25d25612578..781f1b1c13b 100644 --- a/libs/rest/rest-common/build.gradle +++ b/libs/rest/rest-common/build.gradle @@ -18,6 +18,4 @@ dependencies { implementation project(':libs:messaging:messaging') implementation 'org.jetbrains.kotlin:kotlin-osgi-bundle' - - testImplementation "org.mockito:mockito-core:$mockitoVersion" } diff --git a/libs/rest/rest-server-impl/build.gradle b/libs/rest/rest-server-impl/build.gradle index 343705083ec..a8c84ee5973 100644 --- a/libs/rest/rest-server-impl/build.gradle +++ b/libs/rest/rest-server-impl/build.gradle @@ -48,8 +48,6 @@ dependencies { implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jacksonVersion" testImplementation project(":libs:rest:rest-test-common") - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testRuntimeOnly 'org.osgi:osgi.core' testRuntimeOnly "org.slf4j:slf4j-simple:$slf4jVersion" @@ -61,11 +59,6 @@ dependencies { integrationTestImplementation "com.konghq:unirest-java:$unirestVersion" - integrationTestImplementation "org.mockito:mockito-core:$mockitoVersion" - integrationTestImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" - - integrationTestImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" - integrationTestImplementation project(':libs:rest:ssl-cert-read-impl') integrationTestImplementation project(":testing:test-utilities") } diff --git a/libs/rest/rest-test-common/build.gradle b/libs/rest/rest-test-common/build.gradle index 08ac90e5ca7..6a3d5cbad3b 100644 --- a/libs/rest/rest-test-common/build.gradle +++ b/libs/rest/rest-test-common/build.gradle @@ -17,7 +17,7 @@ dependencies { implementation "com.nimbusds:oauth2-oidc-sdk:$nimbusVersion" implementation "com.konghq:unirest-java:$unirestVersion" - implementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" + implementation libs.mockito.kotlin implementation project(":libs:rest:rest") implementation project(":libs:rest:rest-common") diff --git a/libs/rest/rest/build.gradle b/libs/rest/rest/build.gradle index 75544117911..2d2723b3aa4 100644 --- a/libs/rest/rest/build.gradle +++ b/libs/rest/rest/build.gradle @@ -12,6 +12,4 @@ dependencies { implementation platform("net.corda:corda-api:$cordaApiVersion") implementation 'org.jetbrains.kotlin:kotlin-osgi-bundle' - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/libs/rest/ssl-cert-read-impl/build.gradle b/libs/rest/ssl-cert-read-impl/build.gradle index 24f3c809302..e8e9e63f898 100644 --- a/libs/rest/ssl-cert-read-impl/build.gradle +++ b/libs/rest/ssl-cert-read-impl/build.gradle @@ -19,7 +19,4 @@ dependencies { implementation "org.bouncycastle:bcpkix-jdk18on:$bouncycastleVersion" api project(':libs:rest:ssl-cert-read') - - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } \ No newline at end of file diff --git a/libs/sandbox-hooks/build.gradle b/libs/sandbox-hooks/build.gradle index e4f1d223d46..87bba16f1e6 100644 --- a/libs/sandbox-hooks/build.gradle +++ b/libs/sandbox-hooks/build.gradle @@ -19,8 +19,6 @@ dependencies { implementation project(':libs:kotlin-heap-fix') implementation project(':libs:sandbox') - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testRuntimeOnly "org.apache.felix:org.apache.felix.framework:$felixVersion" testRuntimeOnly "org.apache.felix:org.apache.felix.scr:$felixScrVersion" } diff --git a/libs/sandbox-internal/build.gradle b/libs/sandbox-internal/build.gradle index 239b75b3fb1..5c6c0757d1d 100644 --- a/libs/sandbox-internal/build.gradle +++ b/libs/sandbox-internal/build.gradle @@ -31,8 +31,6 @@ dependencies { runtimeOnly project(':libs:sandbox-hooks') testCompileOnly 'org.osgi:osgi.core' - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation project(":testing:crypto-testkit") testRuntimeOnly "org.apache.felix:org.apache.felix.framework:$felixVersion" testRuntimeOnly "org.apache.felix:org.apache.felix.scr:$felixScrVersion" diff --git a/libs/scheduler/scheduler-datamodel/build.gradle b/libs/scheduler/scheduler-datamodel/build.gradle index d262c7fc2a8..3a85eb7073f 100644 --- a/libs/scheduler/scheduler-datamodel/build.gradle +++ b/libs/scheduler/scheduler-datamodel/build.gradle @@ -14,8 +14,6 @@ dependencies { implementation 'org.jetbrains.kotlin:kotlin-osgi-bundle' implementation project(':libs:db:db-core') - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" integrationTestImplementation project(':libs:db:db-admin') integrationTestImplementation project(':libs:db:db-admin-impl') diff --git a/libs/serialization/json-serializers/build.gradle b/libs/serialization/json-serializers/build.gradle index ec3b961c376..95f1b957bbb 100644 --- a/libs/serialization/json-serializers/build.gradle +++ b/libs/serialization/json-serializers/build.gradle @@ -12,6 +12,4 @@ dependencies { implementation "net.corda:corda-application" implementation 'net.corda:corda-base' implementation "com.fasterxml.jackson.module:jackson-module-kotlin:$jacksonVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/libs/serialization/json-validator/build.gradle b/libs/serialization/json-validator/build.gradle index d643a3c94b4..44a67f76cd0 100644 --- a/libs/serialization/json-validator/build.gradle +++ b/libs/serialization/json-validator/build.gradle @@ -30,8 +30,6 @@ dependencies { } } implementation "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion" - - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" } def jar = tasks.named('jar', Jar) { diff --git a/libs/serialization/serialization-amqp/build.gradle b/libs/serialization/serialization-amqp/build.gradle index d76033cfa1c..85945c95336 100644 --- a/libs/serialization/serialization-amqp/build.gradle +++ b/libs/serialization/serialization-amqp/build.gradle @@ -45,13 +45,8 @@ dependencies { testImplementation project(':libs:crypto:crypto-serialization-impl') testImplementation project(':testing:test-serialization') testImplementation project(':libs:crypto:cipher-suite') - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.junit.jupiter:junit-jupiter-api:$junit5Version" - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" testImplementation "org.hamcrest:hamcrest-library:$hamcrestVersion" testImplementation "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testRuntimeOnly "org.slf4j:slf4j-simple:$slf4jVersion" testRuntimeOnly 'org.osgi:osgi.core' diff --git a/libs/serialization/serialization-kryo/build.gradle b/libs/serialization/serialization-kryo/build.gradle index 14b85a83b97..054a9e82843 100644 --- a/libs/serialization/serialization-kryo/build.gradle +++ b/libs/serialization/serialization-kryo/build.gradle @@ -45,10 +45,6 @@ dependencies { cpbs project(path: 'cpks:serializable-cpk-two', configuration: 'cordaCPB') testCompileOnly 'org.osgi:osgi.core' - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.junit.jupiter:junit-jupiter-api:$junit5Version" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testRuntimeOnly "org.apache.felix:org.apache.felix.framework:$felixVersion" testRuntimeOnly "co.paralleluniverse:quasar-core-osgi:$quasarVersion:framework-extension" testImplementation project(":testing:kryo-serialization-testkit") diff --git a/libs/state-manager/state-manager-db-impl/build.gradle b/libs/state-manager/state-manager-db-impl/build.gradle index 290146754fc..853992408ef 100644 --- a/libs/state-manager/state-manager-db-impl/build.gradle +++ b/libs/state-manager/state-manager-db-impl/build.gradle @@ -22,8 +22,6 @@ dependencies { implementation "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion" implementation "com.fasterxml.jackson.module:jackson-module-kotlin:$jacksonVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" integrationTestImplementation project(':libs:db:db-admin') integrationTestImplementation project(':testing:db-testkit') diff --git a/libs/task-manager/build.gradle b/libs/task-manager/build.gradle index 92c44653b1f..e8eda79362a 100644 --- a/libs/task-manager/build.gradle +++ b/libs/task-manager/build.gradle @@ -13,8 +13,4 @@ dependencies { implementation project(":libs:utilities") implementation 'org.jetbrains.kotlin:kotlin-osgi-bundle' - - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" - testImplementation "org.assertj:assertj-core:$assertjVersion" } diff --git a/libs/utilities/build.gradle b/libs/utilities/build.gradle index 49f0b57a9cc..81376ad82dc 100644 --- a/libs/utilities/build.gradle +++ b/libs/utilities/build.gradle @@ -22,10 +22,7 @@ dependencies { implementation project(":libs:configuration:configuration-core") - testImplementation "org.assertj:assertj-core:$assertjVersion" testImplementation "com.google.jimfs:jimfs:$jimfsVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testRuntimeOnly 'org.osgi:osgi.core' } diff --git a/libs/virtual-node/cpi-upload-manager-impl/build.gradle b/libs/virtual-node/cpi-upload-manager-impl/build.gradle index dc80f28bb69..00d8ef30163 100644 --- a/libs/virtual-node/cpi-upload-manager-impl/build.gradle +++ b/libs/virtual-node/cpi-upload-manager-impl/build.gradle @@ -22,6 +22,4 @@ dependencies { implementation "net.corda:corda-topic-schema" implementation 'net.corda:corda-crypto' implementation 'org.jetbrains.kotlin:kotlin-osgi-bundle' - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/libs/virtual-node/sandbox-group-context/build.gradle b/libs/virtual-node/sandbox-group-context/build.gradle index 5deea37d07b..ff05561f262 100644 --- a/libs/virtual-node/sandbox-group-context/build.gradle +++ b/libs/virtual-node/sandbox-group-context/build.gradle @@ -16,7 +16,4 @@ dependencies { api project(':libs:sandbox-types') api project(':libs:virtual-node:virtual-node-info') - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/libs/virtual-node/virtual-node-info/build.gradle b/libs/virtual-node/virtual-node-info/build.gradle index a39fc2e28f0..8fdd5b3a6c7 100644 --- a/libs/virtual-node/virtual-node-info/build.gradle +++ b/libs/virtual-node/virtual-node-info/build.gradle @@ -17,8 +17,5 @@ dependencies { api project(':libs:crypto:crypto-core') api project(':libs:packaging:packaging-core') - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation project(':testing:test-utilities') } diff --git a/libs/web/web-impl/build.gradle b/libs/web/web-impl/build.gradle index 85eacdd2d9a..ffee91948e8 100644 --- a/libs/web/web-impl/build.gradle +++ b/libs/web/web-impl/build.gradle @@ -32,8 +32,5 @@ dependencies { testImplementation 'org.osgi:osgi.core' - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" - integrationTestRuntimeOnly "org.slf4j:slf4j-simple:$slf4jVersion" } \ No newline at end of file diff --git a/libs/web/web/build.gradle b/libs/web/web/build.gradle index d85df7e411a..228a5e741ba 100644 --- a/libs/web/web/build.gradle +++ b/libs/web/web/build.gradle @@ -16,7 +16,4 @@ dependencies { compileOnly 'org.osgi:org.osgi.service.component.annotations' compileOnly "org.osgi:osgi.annotation" compileOnly 'org.osgi:osgi.core' - - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } \ No newline at end of file diff --git a/notary-plugins/notary-plugin-common/src/main/kotlin/com/r3/corda/notary/plugin/common/CommonNotaryExceptions.kt b/notary-plugins/notary-plugin-common/src/main/kotlin/com/r3/corda/notary/plugin/common/CommonNotaryExceptions.kt index 5620006eb5c..d6e7b8c3f89 100644 --- a/notary-plugins/notary-plugin-common/src/main/kotlin/com/r3/corda/notary/plugin/common/CommonNotaryExceptions.kt +++ b/notary-plugins/notary-plugin-common/src/main/kotlin/com/r3/corda/notary/plugin/common/CommonNotaryExceptions.kt @@ -102,6 +102,34 @@ class NotaryExceptionMalformedRequest( txId ) +/** + * Occurs when a valid signature is not found in received signatures. + * + * @property errorText The error text produced by signature verification + */ +@CordaSerializable +class NotaryExceptionInvalidSignature( + val errorText: String?, + txId: SecureHash? = null +) : NotaryExceptionFatal( + "Signature invalid Error: $errorText", + txId +) + +/** + * Occurs when a received transaction is invalid. + * + * @property errorText The error text produced by transaction verification + */ +@CordaSerializable +class NotaryExceptionTransactionVerificationFailure( + val errorText: String?, + txId: SecureHash? = null +) : NotaryExceptionFatal( + "Transaction verification failure Error: $errorText", + txId +) + /** * Error type used for scenarios that were unexpected, or couldn't be mapped. * diff --git a/notary-plugins/notary-plugin-non-validating/notary-plugin-non-validating-server/src/main/kotlin/com/r3/corda/notary/plugin/nonvalidating/server/NonValidatingNotaryTransactionDetails.kt b/notary-plugins/notary-plugin-common/src/main/kotlin/com/r3/corda/notary/plugin/common/NotaryTransactionDetails.kt similarity index 90% rename from notary-plugins/notary-plugin-non-validating/notary-plugin-non-validating-server/src/main/kotlin/com/r3/corda/notary/plugin/nonvalidating/server/NonValidatingNotaryTransactionDetails.kt rename to notary-plugins/notary-plugin-common/src/main/kotlin/com/r3/corda/notary/plugin/common/NotaryTransactionDetails.kt index 1ba11a314ba..452b11fa700 100644 --- a/notary-plugins/notary-plugin-non-validating/notary-plugin-non-validating-server/src/main/kotlin/com/r3/corda/notary/plugin/nonvalidating/server/NonValidatingNotaryTransactionDetails.kt +++ b/notary-plugins/notary-plugin-common/src/main/kotlin/com/r3/corda/notary/plugin/common/NotaryTransactionDetails.kt @@ -1,4 +1,4 @@ -package com.r3.corda.notary.plugin.nonvalidating.server +package com.r3.corda.notary.plugin.common import net.corda.v5.base.types.MemberX500Name import net.corda.v5.crypto.SecureHash @@ -12,7 +12,7 @@ import java.security.PublicKey * A representation of a transaction (non-validating). It is easier to perform operations on this representation than * on the actual transaction object (e.g. FilteredTransaction). */ -data class NonValidatingNotaryTransactionDetails( +data class NotaryTransactionDetails( private val id: SecureHash, private val metadata: TransactionMetadata, val numOutputs: Int, @@ -31,4 +31,4 @@ data class NonValidatingNotaryTransactionDetails( override fun getMetadata(): TransactionMetadata { return metadata } -} +} \ No newline at end of file diff --git a/notary-plugins/notary-plugin-contract-verifying/notary-plugin-contract-verifying-api/build.gradle b/notary-plugins/notary-plugin-contract-verifying/notary-plugin-contract-verifying-api/build.gradle new file mode 100644 index 00000000000..bd1d554ecc2 --- /dev/null +++ b/notary-plugins/notary-plugin-contract-verifying/notary-plugin-contract-verifying-api/build.gradle @@ -0,0 +1,34 @@ +plugins { + id 'org.jetbrains.kotlin.jvm' + id 'corda.common-publishing' + id 'net.corda.plugins.cordapp-cpk2' + id 'corda.javadoc-generation' +} + +ext { + releasable = true +} + +description 'Corda Contract Verifying Notary Plugin API' + +group 'com.r3.corda.notary.plugin.contractverifying' + +cordapp { + targetPlatformVersion platformVersion.toInteger() + workflow { + name "Corda Contract Verifying Notary - API" + versionId 1 + vendor "R3" + } +} + +dependencies { + cordaProvided platform("net.corda:corda-api:$cordaApiVersion") + + cordaProvided 'net.corda:corda-application' + cordaProvided 'net.corda:corda-notary-plugin' + cordaProvided 'org.jetbrains.kotlin:kotlin-osgi-bundle' + cordaProvided 'org.slf4j:slf4j-api' + + cordapp project(":notary-plugins:notary-plugin-common") +} diff --git a/notary-plugins/notary-plugin-contract-verifying/notary-plugin-contract-verifying-api/src/main/kotlin/com/r3/corda/notary/plugin/contractverifying/api/ContractVerifyingNotarizationPayload.kt b/notary-plugins/notary-plugin-contract-verifying/notary-plugin-contract-verifying-api/src/main/kotlin/com/r3/corda/notary/plugin/contractverifying/api/ContractVerifyingNotarizationPayload.kt new file mode 100644 index 00000000000..f6d55308f9f --- /dev/null +++ b/notary-plugins/notary-plugin-contract-verifying/notary-plugin-contract-verifying-api/src/main/kotlin/com/r3/corda/notary/plugin/contractverifying/api/ContractVerifyingNotarizationPayload.kt @@ -0,0 +1,10 @@ +package com.r3.corda.notary.plugin.contractverifying.api + +import net.corda.v5.base.annotations.CordaSerializable +import net.corda.v5.ledger.utxo.transaction.UtxoSignedTransaction + +@CordaSerializable +data class ContractVerifyingNotarizationPayload( + val initialTransaction: UtxoSignedTransaction, + val filteredTransactionsAndSignatures: List, +) diff --git a/notary-plugins/notary-plugin-contract-verifying/notary-plugin-contract-verifying-api/src/main/kotlin/com/r3/corda/notary/plugin/contractverifying/api/FilteredTransactionAndSignatures.kt b/notary-plugins/notary-plugin-contract-verifying/notary-plugin-contract-verifying-api/src/main/kotlin/com/r3/corda/notary/plugin/contractverifying/api/FilteredTransactionAndSignatures.kt new file mode 100644 index 00000000000..244ae07f4b8 --- /dev/null +++ b/notary-plugins/notary-plugin-contract-verifying/notary-plugin-contract-verifying-api/src/main/kotlin/com/r3/corda/notary/plugin/contractverifying/api/FilteredTransactionAndSignatures.kt @@ -0,0 +1,11 @@ +package com.r3.corda.notary.plugin.contractverifying.api + +import net.corda.v5.application.crypto.DigitalSignatureAndMetadata +import net.corda.v5.base.annotations.CordaSerializable +import net.corda.v5.ledger.utxo.transaction.filtered.UtxoFilteredTransaction + +@CordaSerializable +data class FilteredTransactionAndSignatures( + val filteredTransaction: UtxoFilteredTransaction, + val signatures: List +) diff --git a/notary-plugins/notary-plugin-contract-verifying/notary-plugin-contract-verifying-client/build.gradle b/notary-plugins/notary-plugin-contract-verifying/notary-plugin-contract-verifying-client/build.gradle new file mode 100644 index 00000000000..47ad08154dd --- /dev/null +++ b/notary-plugins/notary-plugin-contract-verifying/notary-plugin-contract-verifying-client/build.gradle @@ -0,0 +1,41 @@ +plugins { + id 'org.jetbrains.kotlin.jvm' + id 'corda.common-publishing' + id 'net.corda.plugins.cordapp-cpk2' + id 'corda.javadoc-generation' +} + +ext { + releasable = true +} + +description 'Corda Contract Verifying Notary Plugin Client' + +group 'com.r3.corda.notary.plugin.contractverifying' + +cordapp { + targetPlatformVersion platformVersion.toInteger() + workflow { + name "Corda Contract Verifying Notary - Client" + versionId 1 + vendor "R3" + } +} + +dependencies { + cordaProvided platform("net.corda:corda-api:$cordaApiVersion") + + cordaProvided 'net.corda:corda-application' + cordaProvided 'net.corda:corda-notary-plugin' + cordaProvided 'org.jetbrains.kotlin:kotlin-osgi-bundle' + cordaProvided 'org.slf4j:slf4j-api' + + // Common package pulled in as transitive dependency through API + cordapp project(":notary-plugins:notary-plugin-contract-verifying:notary-plugin-contract-verifying-api") + + testImplementation libs.bundles.test + + testImplementation project(':libs:serialization:serialization-amqp') + testImplementation project(':libs:crypto:cipher-suite') + testImplementation project(":testing:crypto-testkit") +} diff --git a/notary-plugins/notary-plugin-contract-verifying/notary-plugin-contract-verifying-client/src/main/kotlin/com/r3/corda/notary/plugin/contractverifying/client/ContractVerifyingNotaryClientFlowImpl.kt b/notary-plugins/notary-plugin-contract-verifying/notary-plugin-contract-verifying-client/src/main/kotlin/com/r3/corda/notary/plugin/contractverifying/client/ContractVerifyingNotaryClientFlowImpl.kt new file mode 100644 index 00000000000..2d2ac3af046 --- /dev/null +++ b/notary-plugins/notary-plugin-contract-verifying/notary-plugin-contract-verifying-client/src/main/kotlin/com/r3/corda/notary/plugin/contractverifying/client/ContractVerifyingNotaryClientFlowImpl.kt @@ -0,0 +1,111 @@ +package com.r3.corda.notary.plugin.contractverifying.client + +import com.r3.corda.notary.plugin.common.NotarizationResponse +import com.r3.corda.notary.plugin.contractverifying.api.ContractVerifyingNotarizationPayload +import com.r3.corda.notary.plugin.contractverifying.api.FilteredTransactionAndSignatures +import net.corda.v5.application.crypto.DigestService +import net.corda.v5.application.crypto.DigitalSignatureAndMetadata +import net.corda.v5.application.flows.CordaInject +import net.corda.v5.application.flows.InitiatingFlow +import net.corda.v5.application.messaging.FlowMessaging +import net.corda.v5.base.annotations.Suspendable +import net.corda.v5.base.annotations.VisibleForTesting +import net.corda.v5.base.types.MemberX500Name +import net.corda.v5.crypto.DigestAlgorithmName +import net.corda.v5.ledger.notary.plugin.api.PluggableNotaryClientFlow +import net.corda.v5.ledger.utxo.UtxoLedgerService +import net.corda.v5.ledger.utxo.transaction.UtxoSignedTransaction +import org.slf4j.LoggerFactory + +@InitiatingFlow(protocol = "com.r3.corda.notary.plugin.contractverifying", version = [1]) +class ContractVerifyingNotaryClientFlowImpl( + private val signedTransaction: UtxoSignedTransaction, + private val notaryRepresentative: MemberX500Name +) : PluggableNotaryClientFlow { + private companion object { + private val logger = LoggerFactory.getLogger(this::class.java.enclosingClass) + } + + @CordaInject + private lateinit var flowMessaging: FlowMessaging + + @CordaInject + private lateinit var digestService: DigestService + + @CordaInject + private lateinit var utxoLedgerService: UtxoLedgerService + + /** + * Constructor used for testing to initialize the necessary services + */ + @VisibleForTesting + internal constructor( + stx: UtxoSignedTransaction, + notary: MemberX500Name, + flowMessaging: FlowMessaging, + utxoLedgerService: UtxoLedgerService, + digestService: DigestService + ): this(stx, notary) { + this.flowMessaging = flowMessaging + this.utxoLedgerService = utxoLedgerService + this.digestService = digestService + } + + @Suspendable + override fun call(): List { + if (logger.isTraceEnabled) { + logger.trace("Notarizing transaction {} with notary {}", signedTransaction.id, notaryRepresentative) + } + + val session = flowMessaging.initiateFlow(notaryRepresentative) + val payload = createPayload() + val notarizationResponse = session.sendAndReceive( + NotarizationResponse::class.java, + payload + ) + + return when (val error = notarizationResponse.error) { + null -> { + if (logger.isTraceEnabled) { + logger.trace( + "Received notarization response from notary service {} for transaction {}", + signedTransaction.notaryName, signedTransaction.id + ) + } + notarizationResponse.signatures + } + else -> { + if (logger.isTraceEnabled) { + logger.trace( + "Received notarization error from notary service {}. Error: {}", + signedTransaction.notaryName, error + ) + } + throw error + } + } + } + + @Suspendable + internal fun createPayload(): ContractVerifyingNotarizationPayload { + val hashedNotaryKey = digestService.hash(signedTransaction.notaryKey.encoded, DigestAlgorithmName.SHA2_256) + + val filteredDependenciesAndSignatures = signedTransaction.let { it.inputStateRefs + it.referenceStateRefs } + .groupBy { stateRef -> stateRef.transactionId } + .mapValues { (_, stateRefs) -> stateRefs.map { stateRef -> stateRef.index } } + .map { (transactionId, indexes) -> + val dependency = requireNotNull(utxoLedgerService.findSignedTransaction(transactionId)) { + "Dependent transaction $transactionId does not exist" + } + FilteredTransactionAndSignatures( + utxoLedgerService.filterSignedTransaction(dependency) + .withOutputStates(indexes) + .withNotary() + .withTimeWindow() + .build(), + dependency.signatures.filter { hashedNotaryKey == it.by } + ) + } + return ContractVerifyingNotarizationPayload(signedTransaction, filteredDependenciesAndSignatures) + } +} \ No newline at end of file diff --git a/notary-plugins/notary-plugin-contract-verifying/notary-plugin-contract-verifying-client/src/test/kotlin/com/r3/corda/notary/plugin/contractverifying/client/ContractVerifyingNotaryClientFlowImplTest.kt b/notary-plugins/notary-plugin-contract-verifying/notary-plugin-contract-verifying-client/src/test/kotlin/com/r3/corda/notary/plugin/contractverifying/client/ContractVerifyingNotaryClientFlowImplTest.kt new file mode 100644 index 00000000000..0a1d24a793e --- /dev/null +++ b/notary-plugins/notary-plugin-contract-verifying/notary-plugin-contract-verifying-client/src/test/kotlin/com/r3/corda/notary/plugin/contractverifying/client/ContractVerifyingNotaryClientFlowImplTest.kt @@ -0,0 +1,145 @@ +package com.r3.corda.notary.plugin.contractverifying.client + +import com.r3.corda.notary.plugin.common.NotarizationResponse +import com.r3.corda.notary.plugin.common.NotaryExceptionReferenceStateUnknown +import net.corda.crypto.cipher.suite.SignatureSpecImpl +import net.corda.crypto.testkit.SecureHashUtils +import net.corda.v5.application.crypto.DigestService +import net.corda.v5.application.crypto.DigitalSignatureAndMetadata +import net.corda.v5.application.crypto.DigitalSignatureMetadata +import net.corda.v5.application.messaging.FlowMessaging +import net.corda.v5.application.messaging.FlowSession +import net.corda.v5.base.types.MemberX500Name +import net.corda.v5.crypto.DigestAlgorithmName +import net.corda.v5.ledger.utxo.StateRef +import net.corda.v5.ledger.utxo.UtxoLedgerService +import net.corda.v5.ledger.utxo.transaction.UtxoSignedTransaction +import net.corda.v5.ledger.utxo.transaction.filtered.UtxoFilteredTransaction +import net.corda.v5.ledger.utxo.transaction.filtered.UtxoFilteredTransactionBuilder +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance +import org.junit.jupiter.api.assertAll +import org.junit.jupiter.api.assertThrows +import org.mockito.kotlin.any +import org.mockito.kotlin.doReturn +import org.mockito.kotlin.eq +import org.mockito.kotlin.mock +import java.security.PublicKey +import java.time.Instant + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class ContractVerifyingNotaryClientFlowImplTest { + + private companion object { + val txId = SecureHashUtils.randomSecureHash() + val hashedNotaryKey = SecureHashUtils.randomSecureHash() + } + + /* State Refs */ + private val mockStateRef = mock { + on { transactionId } doReturn txId + } + + /* notary public keys */ + private val encodedNotary = byteArrayOf(0x01) + private val notaryPublicKey = mock { + on { encoded } doReturn encodedNotary + } + + /* Transactions */ + private val mockFilteredTx = mock() + private val mockSignedTx = mock { + on { notaryKey } doReturn notaryPublicKey + on {inputStateRefs} doReturn listOf(mockStateRef) + on { referenceStateRefs } doReturn emptyList() + } + + /* Signature */ + private val dummyUniquenessSignature = DigitalSignatureAndMetadata( + mock(), + DigitalSignatureMetadata(Instant.now(), SignatureSpecImpl("dummySignatureName"), emptyMap()) + ) + private val mockDependency = mock { + on {signatures} doReturn listOf(dummyUniquenessSignature) + } + + @Test + fun `Contract verifying notary plugin client creates payload properly`() { + val client = createClient(mock()) + + val payload = client.createPayload() + + assertAll({ + assertThat(payload).isNotNull + assertThat(payload.initialTransaction).isEqualTo(mockSignedTx) + }) + } + + @Test + fun `Contract verifying notary plugin client returns signature on successful notarization`() { + val mockSession = mock { + on { sendAndReceive(eq(NotarizationResponse::class.java), any()) } doReturn NotarizationResponse( + listOf(dummyUniquenessSignature), + null + ) + } + val mockFlowMessaging = mock { + on { initiateFlow(any()) } doReturn mockSession + } + + val client = createClient(mockFlowMessaging) + + val signatures = client.call() + + assertThat(signatures).containsExactly(dummyUniquenessSignature) + } + + @Test + fun `Contract verifying notary plugin client throws error on failed notarization`() { + val mockSession = mock { + on { sendAndReceive(eq(NotarizationResponse::class.java), any()) } doReturn NotarizationResponse( + emptyList(), + NotaryExceptionReferenceStateUnknown(emptyList(), txId) + ) + } + val mockFlowMessaging = mock { + on { initiateFlow(any()) } doReturn mockSession + } + + val client = createClient(mockFlowMessaging) + + val ex = assertThrows { + client.call() + } + + assertThat(ex.txId).isEqualTo(txId) + } + + private fun createClient(flowMessaging: FlowMessaging): ContractVerifyingNotaryClientFlowImpl { + + val mockBuilder = mock { + on { withOutputStates(listOf(0)) } doReturn this.mock + on { withNotary() } doReturn this.mock + on { withTimeWindow() } doReturn this.mock + on { build() } doReturn mockFilteredTx + } + + val utxoLedgerService = mock { + on { filterSignedTransaction(any()) } doReturn mockBuilder + on { findSignedTransaction(any()) } doReturn mockDependency + } + + val digestService = mock { + on { hash( mockSignedTx.notaryKey.encoded, DigestAlgorithmName.SHA2_256) } doReturn hashedNotaryKey + } + + return ContractVerifyingNotaryClientFlowImpl( + mockSignedTx, + MemberX500Name("Alice", "Alice Corp", "LDN", "GB"), + flowMessaging, + utxoLedgerService, + digestService + ) + } +} diff --git a/notary-plugins/notary-plugin-contract-verifying/notary-plugin-contract-verifying-server/build.gradle b/notary-plugins/notary-plugin-contract-verifying/notary-plugin-contract-verifying-server/build.gradle new file mode 100644 index 00000000000..cba43f37b41 --- /dev/null +++ b/notary-plugins/notary-plugin-contract-verifying/notary-plugin-contract-verifying-server/build.gradle @@ -0,0 +1,37 @@ +plugins { + id 'org.jetbrains.kotlin.jvm' + id 'corda.common-publishing' + id 'net.corda.plugins.cordapp-cpk2' +} + +description 'Corda Contract Verifying Notary Plugin Server' + +group 'com.r3.corda.notary.plugin.contractverifying' + +cordapp { + targetPlatformVersion platformVersion.toInteger() + workflow { + name "Corda Cotract Verifying Notary - Server" + versionId 1 + vendor "R3" + } +} + +dependencies { + cordaProvided platform("net.corda:corda-api:$cordaApiVersion") + + cordaProvided 'net.corda:corda-application' + cordaProvided 'net.corda:corda-notary-plugin' + cordaProvided 'org.jetbrains.kotlin:kotlin-osgi-bundle' + cordaProvided 'org.slf4j:slf4j-api' + + // Common package pulled in as transitive dependency through API + cordapp project(":notary-plugins:notary-plugin-contract-verifying:notary-plugin-contract-verifying-api") + + testImplementation libs.bundles.test + + testImplementation project(":libs:crypto:crypto-core") + testImplementation project(":libs:uniqueness:common") + testImplementation project(":testing:crypto-testkit") + testImplementation project(':testing:ledger:ledger-common-testkit') +} diff --git a/notary-plugins/notary-plugin-contract-verifying/notary-plugin-contract-verifying-server/src/main/kotlin/com/r3/corda/notary/plugin/contractverifying/server/ContractVerifyingNotaryServerFlowImpl.kt b/notary-plugins/notary-plugin-contract-verifying/notary-plugin-contract-verifying-server/src/main/kotlin/com/r3/corda/notary/plugin/contractverifying/server/ContractVerifyingNotaryServerFlowImpl.kt new file mode 100644 index 00000000000..4fa71518d2d --- /dev/null +++ b/notary-plugins/notary-plugin-contract-verifying/notary-plugin-contract-verifying-server/src/main/kotlin/com/r3/corda/notary/plugin/contractverifying/server/ContractVerifyingNotaryServerFlowImpl.kt @@ -0,0 +1,217 @@ +package com.r3.corda.notary.plugin.contractverifying.server + +import com.r3.corda.notary.plugin.common.NotarizationResponse +import com.r3.corda.notary.plugin.common.NotaryExceptionGeneral +import com.r3.corda.notary.plugin.common.NotaryExceptionInvalidSignature +import com.r3.corda.notary.plugin.common.NotaryExceptionTransactionVerificationFailure +import com.r3.corda.notary.plugin.common.NotaryTransactionDetails +import com.r3.corda.notary.plugin.common.toNotarizationResponse +import com.r3.corda.notary.plugin.contractverifying.api.ContractVerifyingNotarizationPayload +import com.r3.corda.notary.plugin.contractverifying.api.FilteredTransactionAndSignatures +import net.corda.v5.application.flows.CordaInject +import net.corda.v5.application.flows.InitiatedBy +import net.corda.v5.application.flows.ResponderFlow +import net.corda.v5.application.membership.MemberLookup +import net.corda.v5.application.messaging.FlowSession +import net.corda.v5.application.uniqueness.model.UniquenessCheckResultSuccess +import net.corda.v5.base.annotations.Suspendable +import net.corda.v5.base.annotations.VisibleForTesting +import net.corda.v5.base.types.MemberX500Name +import net.corda.v5.crypto.SecureHash +import net.corda.v5.ledger.common.transaction.TransactionSignatureService +import net.corda.v5.ledger.notary.plugin.core.NotaryException +import net.corda.v5.ledger.utxo.NotarySignatureVerificationService +import net.corda.v5.ledger.utxo.StateAndRef +import net.corda.v5.ledger.utxo.UtxoLedgerService +import net.corda.v5.ledger.utxo.transaction.UtxoSignedTransaction +import net.corda.v5.ledger.utxo.transaction.filtered.UtxoFilteredData +import net.corda.v5.ledger.utxo.uniqueness.client.LedgerUniquenessCheckerClientService +import org.slf4j.LoggerFactory +import java.security.PublicKey + +@InitiatedBy(protocol = "com.r3.corda.notary.plugin.contractverifying", version = [1]) +class ContractVerifyingNotaryServerFlowImpl() : ResponderFlow { + private companion object { + private val logger = LoggerFactory.getLogger(this::class.java.enclosingClass) + const val NOTARY_SERVICE_NAME = "corda.notary.service.name" + } + + @CordaInject + private lateinit var clientService: LedgerUniquenessCheckerClientService + + @CordaInject + private lateinit var transactionSignatureService: TransactionSignatureService + + @CordaInject + private lateinit var utxoLedgerService: UtxoLedgerService + + @CordaInject + private lateinit var memberLookup: MemberLookup + + @CordaInject + private lateinit var notarySignatureVerificationService: NotarySignatureVerificationService + + /** + * Constructor used for testing to initialize the necessary services + */ + @VisibleForTesting + internal constructor( + clientService: LedgerUniquenessCheckerClientService, + transactionSignatureService: TransactionSignatureService, + utxoLedgerService: UtxoLedgerService, + memberLookup: MemberLookup, + notarySignatureVerificationService: NotarySignatureVerificationService + ) : this() { + this.clientService = clientService + this.transactionSignatureService = transactionSignatureService + this.utxoLedgerService = utxoLedgerService + this.memberLookup = memberLookup + this.notarySignatureVerificationService = notarySignatureVerificationService + } + + @Suspendable + override fun call(session: FlowSession) { + try { + val (initialTransaction, filteredTransactionsAndSignatures) = session.receive(ContractVerifyingNotarizationPayload::class.java) + if (logger.isTraceEnabled) { + logger.trace("Received notarization request for transaction {}", initialTransaction.id) + } + + val initialTransactionDetails = getInitialTransactionDetail(initialTransaction) + + validateTransactionNotaryAgainstCurrentNotary(initialTransactionDetails) + + verifySignatures(initialTransaction.notaryKey, filteredTransactionsAndSignatures) + + verifyTransaction(initialTransaction, filteredTransactionsAndSignatures) + + if (logger.isTraceEnabled) { + logger.trace("Requesting uniqueness check for transaction {}", initialTransactionDetails.id) + } + + val uniquenessResult = clientService.requestUniquenessCheck( + initialTransaction.id.toString(), + session.counterparty.toString(), + initialTransaction.inputStateRefs.map { it.toString() }, + initialTransaction.referenceStateRefs.map { it.toString() }, + initialTransaction.outputStateAndRefs.count(), + initialTransaction.timeWindow.from, + initialTransaction.timeWindow.until + ) + + if (logger.isDebugEnabled) { + logger.debug( + "Uniqueness check completed for transaction {}, result is: {}. Sending response to {}", + initialTransaction.id, uniquenessResult, session.counterparty + ) + } + + val signature = if (uniquenessResult is UniquenessCheckResultSuccess) { + transactionSignatureService.signBatch( + listOf(initialTransactionDetails), + listOf(initialTransaction.notaryKey) + ).first().first() + } else null + + session.send(uniquenessResult.toNotarizationResponse(initialTransactionDetails.id, signature)) + } catch (e: Exception) { + logger.warn("Error while processing request from client. Cause: $e ${e.stackTraceToString()}") + val exception = + if (e is NotaryException) e else NotaryExceptionGeneral("Error during notarization. Cause: ${e.message}") + session.send( + NotarizationResponse( + emptyList(), + exception + ) + ) + } + } + + /** + * A helper function that constructs an instance of [NotaryTransactionDetails] from the given transaction. + */ + @Suspendable + private fun getInitialTransactionDetail(initialTransaction: UtxoSignedTransaction): NotaryTransactionDetails { + return NotaryTransactionDetails( + initialTransaction.id, + initialTransaction.metadata, + initialTransaction.outputStateAndRefs.count(), + initialTransaction.timeWindow, + initialTransaction.inputStateRefs, + initialTransaction.referenceStateRefs, + initialTransaction.notaryName, + initialTransaction.notaryKey + ) + } + + @Suspendable + private fun validateTransactionNotaryAgainstCurrentNotary(txDetails: NotaryTransactionDetails) { + val currentNotaryContext = memberLookup + .myInfo() + .memberProvidedContext + val currentNotaryServiceName = currentNotaryContext + .parse(NOTARY_SERVICE_NAME, MemberX500Name::class.java) + + require(currentNotaryServiceName == txDetails.notaryName) { + "Notary service on the transaction ${txDetails.notaryName} does not match the notary service represented" + + " by this notary virtual node (${currentNotaryServiceName})" + } + } + + /** + * A function that will verify the signatures of the given [filteredTransactionsAndSignatures]. + */ + @Suspendable + fun verifySignatures( + notaryKey: PublicKey, + filteredTransactionsAndSignatures: List + ) { + val keyIdToNotaryKeys: MutableMap> = mutableMapOf() + + filteredTransactionsAndSignatures.forEach { (filteredTransaction, signatures) -> + filteredTransaction.verify() + try { + notarySignatureVerificationService.verifyNotarySignatures( + filteredTransaction, + notaryKey, + signatures, + keyIdToNotaryKeys + ) + } catch (e: Exception) { + throw NotaryExceptionInvalidSignature( + "A valid notary signature is not found with error message: ${e.message}." + ) + } + } + } + + @Suspendable + private fun verifyTransaction( + initialTransaction: UtxoSignedTransaction, + filteredTransactionsAndSignatures: List + ) { + try { + val dependentStateAndRefs = filteredTransactionsAndSignatures.flatMap { (filteredTransaction, _) -> + (filteredTransaction.outputStateAndRefs as UtxoFilteredData.Audit>).values.values + }.associateBy { it.ref } + + val inputStateAndRefs = initialTransaction.inputStateRefs.map { stateRef -> + requireNotNull(dependentStateAndRefs[stateRef]) { + "Missing input state and ref from the filtered transaction" + } + } + + val referenceStateAndRefs = initialTransaction.referenceStateRefs.map { stateRef -> + requireNotNull(dependentStateAndRefs[stateRef]) { + "Missing reference state and ref from the filtered transaction" + } + } + utxoLedgerService.verify(initialTransaction.toLedgerTransaction(inputStateAndRefs, referenceStateAndRefs)) + } catch (e: Exception) { + throw NotaryExceptionTransactionVerificationFailure( + "Transaction failed to verify with error message: ${e.message}.", + initialTransaction.id + ) + } + } +} \ No newline at end of file diff --git a/notary-plugins/notary-plugin-contract-verifying/notary-plugin-contract-verifying-server/src/test/kotlin/com/r3/corda/notary/plugin/contractverifying/server/ContractVerifyingNotaryServerFlowImplTest.kt b/notary-plugins/notary-plugin-contract-verifying/notary-plugin-contract-verifying-server/src/test/kotlin/com/r3/corda/notary/plugin/contractverifying/server/ContractVerifyingNotaryServerFlowImplTest.kt new file mode 100644 index 00000000000..19a29aa3566 --- /dev/null +++ b/notary-plugins/notary-plugin-contract-verifying/notary-plugin-contract-verifying-server/src/test/kotlin/com/r3/corda/notary/plugin/contractverifying/server/ContractVerifyingNotaryServerFlowImplTest.kt @@ -0,0 +1,504 @@ +package com.r3.corda.notary.plugin.contractverifying.server + +import com.r3.corda.notary.plugin.common.NotarizationResponse +import com.r3.corda.notary.plugin.common.NotaryExceptionGeneral +import com.r3.corda.notary.plugin.common.NotaryExceptionInvalidSignature +import com.r3.corda.notary.plugin.common.NotaryExceptionReferenceStateUnknown +import com.r3.corda.notary.plugin.common.NotaryExceptionTransactionVerificationFailure +import com.r3.corda.notary.plugin.contractverifying.api.ContractVerifyingNotarizationPayload +import com.r3.corda.notary.plugin.contractverifying.api.FilteredTransactionAndSignatures +import net.corda.crypto.core.fullIdHash +import net.corda.crypto.testkit.SecureHashUtils +import net.corda.ledger.common.flow.transaction.TransactionSignatureServiceInternal +import net.corda.ledger.common.testkit.getSignatureWithMetadataExample +import net.corda.uniqueness.datamodel.impl.UniquenessCheckErrorReferenceStateUnknownImpl +import net.corda.uniqueness.datamodel.impl.UniquenessCheckErrorUnhandledExceptionImpl +import net.corda.uniqueness.datamodel.impl.UniquenessCheckResultFailureImpl +import net.corda.uniqueness.datamodel.impl.UniquenessCheckResultSuccessImpl +import net.corda.uniqueness.datamodel.impl.UniquenessCheckStateRefImpl +import net.corda.v5.application.crypto.DigitalSignatureAndMetadata +import net.corda.v5.application.membership.MemberLookup +import net.corda.v5.application.messaging.FlowSession +import net.corda.v5.application.uniqueness.model.UniquenessCheckError +import net.corda.v5.application.uniqueness.model.UniquenessCheckResult +import net.corda.v5.base.types.MemberX500Name +import net.corda.v5.crypto.CompositeKey +import net.corda.v5.crypto.DigestAlgorithmName +import net.corda.v5.ledger.common.transaction.TransactionMetadata +import net.corda.v5.ledger.common.transaction.TransactionNoAvailableKeysException +import net.corda.v5.ledger.utxo.NotarySignatureVerificationService +import net.corda.v5.ledger.utxo.StateAndRef +import net.corda.v5.ledger.utxo.StateRef +import net.corda.v5.ledger.utxo.TimeWindow +import net.corda.v5.ledger.utxo.UtxoLedgerService +import net.corda.v5.ledger.utxo.transaction.UtxoSignedTransaction +import net.corda.v5.ledger.utxo.transaction.filtered.UtxoFilteredData +import net.corda.v5.ledger.utxo.transaction.filtered.UtxoFilteredTransaction +import net.corda.v5.ledger.utxo.uniqueness.client.LedgerUniquenessCheckerClientService +import net.corda.v5.membership.MemberContext +import net.corda.v5.membership.MemberInfo +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance +import org.mockito.kotlin.any +import org.mockito.kotlin.doAnswer +import org.mockito.kotlin.doReturn +import org.mockito.kotlin.doThrow +import org.mockito.kotlin.mock +import org.mockito.kotlin.whenever +import java.security.PublicKey +import java.time.Instant + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class ContractVerifyingNotaryServerFlowImplTest { + + private companion object { + const val NOTARY_SERVICE_NAME = "corda.notary.service.name" + const val NOTARY_SERVICE_BACKCHAIN_REQUIRED = "corda.notary.service.backchain.required" + } + + // Cache for storing response from server + private val responseFromServer = mutableListOf() + + // Notary vnodes + private val notaryVNodeAliceKey = mock().also { whenever(it.encoded).thenReturn(byteArrayOf(0x01)) } + private val notaryVNodeBobKey = mock().also { whenever(it.encoded).thenReturn(byteArrayOf(0x02)) } + private val invalidVnodeKey = mock().also { whenever(it.encoded).thenReturn(byteArrayOf(0x03)) } + + private val signatureAlice = getSignatureWithMetadataExample(notaryVNodeAliceKey) + private val signatureBob = getSignatureWithMetadataExample(notaryVNodeBobKey) + private val signatureInvalid = getSignatureWithMetadataExample(invalidVnodeKey) + + // Notary Service and key + private val notaryServiceCompositeKey = mock { + on { leafKeys } doReturn setOf(notaryVNodeAliceKey, notaryVNodeBobKey) + } + private val notaryServiceName = MemberX500Name.parse("O=MyNotaryService, L=London, C=GB") + + // The client that initiated the session with the notary server + private val memberCharlieName = MemberX500Name.parse("O=MemberCharlie, L=London, C=GB") + + // mock services + private val mockTransactionSignatureService = mock() + private val mockLedgerService = mock() + + // mock for notary member lookup + private val notaryInfo = mock() + private val memberProvidedContext = mock() + private val mockMemberLookup = mock() + + // mock fields for signed transaction + private val txId = SecureHashUtils.randomSecureHash() + private val transactionMetadata = mock() + private val mockTimeWindow = mock { + on { from } doReturn Instant.now() + on { until } doReturn Instant.now().plusMillis(100000) + } + private val mockInputRef = mock() + private val mockOutputStateAndRef = mock>() + + // mock signed transaction + private val signedTx = mock { + on { id } doReturn txId + on { inputStateRefs } doReturn listOf(mockInputRef) + on { referenceStateRefs } doReturn emptyList() + on { outputStateAndRefs } doReturn listOf(mockOutputStateAndRef) + on { timeWindow } doReturn mockTimeWindow + on { notaryKey } doReturn notaryServiceCompositeKey + on { notaryName } doReturn notaryServiceName + on { metadata } doReturn transactionMetadata + } + + @BeforeEach + fun clearCache() { + responseFromServer.clear() + whenever(mockTransactionSignatureService.signBatch(any(), any())).doAnswer { inv -> + List((inv.arguments.first() as List<*>).size) { + @Suppress("unchecked_cast") + (inv.arguments[1] as List).map { publicKey -> + getSignatureWithMetadataExample( + publicKey + ) + } + } + } + } + + @Test + fun `Contract verifying notary should respond with error if no keys found for signing`() { + // We sign with a key that is not part of the notary composite key + whenever(mockTransactionSignatureService.signBatch(any(), any())).thenThrow( + TransactionNoAvailableKeysException("The publicKeys do not have any private counterparts available.", null) + ) + createAndCallServer(mockSuccessfulUniquenessClientService(), notarySignature = signatureInvalid) + assertThat(responseFromServer).hasSize(1) + + val responseError = responseFromServer.first().error + assertThat(responseError).isNotNull + assertThat(responseFromServer.first().signatures).isEmpty() + assertThat(responseError).isInstanceOf(NotaryExceptionGeneral::class.java) + assertThat((responseError as NotaryExceptionGeneral).errorText) + .contains("The publicKeys do not have any private counterparts available.") + + } + + @Test + fun `Contract verifying notary plugin server should respond with error if request signature is invalid`() { + whenever(mockTransactionSignatureService.signBatch(any(), any())).thenReturn( + listOf(listOf(signatureAlice)) + ) + + createAndCallServer( + mockSuccessfulUniquenessClientService(), + filteredTxContents = mapOf("notaryKey" to invalidVnodeKey), + signatureVerificationLogic = ::throwVerify + + ) + assertThat(responseFromServer).hasSize(1) + + val responseError = responseFromServer.first().error + assertThat(responseError).isNotNull + assertThat(responseError).isInstanceOf(NotaryExceptionInvalidSignature::class.java) + assertThat((responseError as NotaryExceptionInvalidSignature).errorText) + .contains("A valid notary signature is not found with error message: DUMMY ERROR") + } + + @Test + fun `Contract verifying notary plugin server should respond with error if the uniqueness check fails`() { + val unknownStateRef = UniquenessCheckStateRefImpl(SecureHashUtils.randomSecureHash(), 0) + + createAndCallServer( + mockErrorUniquenessClientService( + UniquenessCheckErrorReferenceStateUnknownImpl(listOf(unknownStateRef)) + ) + ) + + assertThat(responseFromServer).hasSize(1) + val responseError = responseFromServer.first().error + assertThat(responseError).isNotNull + assertThat(responseFromServer.first().signatures).isEmpty() + assertThat(responseError).isInstanceOf(NotaryExceptionReferenceStateUnknown::class.java) + assertThat((responseError as NotaryExceptionReferenceStateUnknown).unknownStates).containsExactly( + unknownStateRef + ) + + } + + @Test + fun `Contract verifying notary plugin server should respond with error if an error encountered during uniqueness check`() { + createAndCallServer(mockThrowErrorUniquenessCheckClientService()) + assertThat(responseFromServer).hasSize(1) + + val responseError = responseFromServer.first().error + assertThat(responseError).isNotNull + assertThat(responseError).isInstanceOf(NotaryExceptionGeneral::class.java) + assertThat((responseError as NotaryExceptionGeneral).errorText) + .contains("Error during notarization. Cause: Uniqueness checker cannot be reached") + + } + + @Test + fun `Contract verifying notary plugin server should respond with signatures if alice key is in composite key`() { + whenever(mockTransactionSignatureService.signBatch(any(), any())).thenReturn( + listOf(listOf(signatureAlice)) + ) + + createAndCallServer( + mockSuccessfulUniquenessClientService(), + ) + assertThat(responseFromServer).hasSize(1) + + val response = responseFromServer.first() + assertThat(response.error).isNull() + assertThat(response.signatures).hasSize(1) + assertThat(response.signatures.first().by).isEqualTo(notaryVNodeAliceKey.fullIdHash()) + } + + @Test + fun `Contract verifying notary plugin server should respond with signatures if bob key is in composite key`() { + whenever(mockTransactionSignatureService.signBatch(any(), any())).thenReturn( + listOf(listOf(signatureBob)) + ) + + createAndCallServer( + mockSuccessfulUniquenessClientService(), + ) + assertThat(responseFromServer).hasSize(1) + + val response = responseFromServer.first() + assertThat(response.error).isNull() + assertThat(response.signatures).hasSize(1) + assertThat(response.signatures.first().by).isEqualTo(notaryVNodeBobKey.fullIdHash()) + } + + @Test + fun `Contract verifying notary plugin server should respond with error if time window not present on filtered tx`() { + createAndCallServer(mockSuccessfulUniquenessClientService(), filteredTxContents = mapOf("timeWindow" to null)) + assertThat(responseFromServer).hasSize(1) + + val responseError = responseFromServer.first().error + assertThat(responseError).isNotNull + assertThat(responseError).isInstanceOf(NotaryExceptionGeneral::class.java) + assertThat((responseError as NotaryExceptionGeneral).errorText).contains( + "Error during notarization." + ) + + } + + @Test + fun `Contract verifying notary plugin server should respond with error if notary name not present on filtered tx`() { + createAndCallServer( + mockSuccessfulUniquenessClientService(), + filteredTxContents = mapOf("notaryName" to null) + ) + assertThat(responseFromServer).hasSize(1) + + val responseError = responseFromServer.first().error + assertThat(responseError).isNotNull + assertThat(responseError).isInstanceOf(NotaryExceptionGeneral::class.java) + assertThat((responseError as NotaryExceptionGeneral).errorText).contains( + "Error during notarization." + ) + + } + + @Test + fun `Contract verifying notary plugin server should respond with error if notary key not present on filtered tx`() { + createAndCallServer( + mockSuccessfulUniquenessClientService(), + filteredTxContents = mapOf("notaryKey" to null) + ) + assertThat(responseFromServer).hasSize(1) + + val responseError = responseFromServer.first().error + assertThat(responseError).isNotNull + assertThat(responseError).isInstanceOf(NotaryExceptionGeneral::class.java) + assertThat((responseError as NotaryExceptionGeneral).errorText).contains( + "Error during notarization." + ) + + } + + @Test + fun `Contract verifying notary plugin server should respond with error if output states are not audit type in the filtered tx`() { + val mockOutputStateProof = mock>() + + createAndCallServer( + mockSuccessfulUniquenessClientService(), + filteredTxContents = mapOf("outputStateRefs" to mockOutputStateProof) + ) + assertThat(responseFromServer).hasSize(1) + + val responseError = responseFromServer.first().error + assertThat(responseError).isNotNull + assertThat(responseError).isInstanceOf(NotaryExceptionTransactionVerificationFailure::class.java) + assertThat((responseError as NotaryExceptionTransactionVerificationFailure).errorText).contains( + "Transaction failed to verify" + ) + } + + @Test + fun `Contract verifying notary plugin server should respond with error if transaction verification fails`() { + createAndCallServer(mockSuccessfulUniquenessClientService(), txVerificationLogic = ::throwVerify) + assertThat(responseFromServer).hasSize(1) + + val responseError = responseFromServer.first().error + assertThat(responseError).isNotNull + assertThat(responseError).isInstanceOf(NotaryExceptionGeneral::class.java) + assertThat((responseError as NotaryExceptionGeneral).errorText) + .contains("Error during notarization. Cause: DUMMY ERROR") + + } + + @Test + fun `Contract verifying notary plugin server should throw general error when unhandled exception in uniqueness checker`() { + createAndCallServer( + mockErrorUniquenessClientService( + UniquenessCheckErrorUnhandledExceptionImpl( + IllegalArgumentException::class.java.name, + "Unhandled error!" + ) + ) + ) + assertThat(responseFromServer).hasSize(1) + + val responseError = responseFromServer.first().error + assertThat(responseError).isNotNull + assertThat(responseError).isInstanceOf(NotaryExceptionGeneral::class.java) + assertThat((responseError as NotaryExceptionGeneral).errorText) + .contains( + "Unhandled exception of type java.lang.IllegalArgumentException encountered during " + + "uniqueness checking with message: Unhandled error!" + ) + + } + + @Test + fun `Contract verifying notary plugin server should respond with error if notary identity invalid`() { + createAndCallServer( + mockSuccessfulUniquenessClientService(), + // What party we pass in here does not matter, it just needs to be different from the notary server party + filteredTxContents = mapOf("notaryName" to MemberX500Name.parse("C=GB,L=London,O=Bob")) + ) + assertThat(responseFromServer).hasSize(1) + + val responseError = responseFromServer.first().error + assertThat(responseError).isNotNull + assertThat(responseError).isInstanceOf(NotaryExceptionGeneral::class.java) + assertThat((responseError as NotaryExceptionGeneral).errorText) + .contains("Error during notarization.") + + } + + + /** + * This function mocks up data such as filtered tx, signed tx and signatures to test verifying notary server. + * + * @param clientService {@link LedgerUniquenessCheckerClientService} mock with UniquenessCheckResult that will be either + * - UniquenessCheckResultFailureImpl using [mockErrorUniquenessClientService] + * - UniquenessCheckResultSuccessImpl using [mockSuccessfulUniquenessClientService] + * @param notaryServiceKey PublicKey of notary. CompositeKey by default. + * @param notarySignature DigitalSignatureAndMetadata of notary + * @param filteredTxContents Map of content of FilteredTransaction to mock up with. + * It will be mocked up with default values if it's empty. + * filtered contests that can be in a map: + * - outputStateRefs + * - notaryName + * - notaryKey + * - timeWindow + * @param txVerificationLogic lambda function to execute on UtxoFilteredTransaction.verify() call + * @param signatureVerificationLogic lambda function to execute on + * UtxoFilteredTransaction.verifyAttachedNotarySignature() call + * */ + @Suppress("LongParameterList") + private fun createAndCallServer( + clientService: LedgerUniquenessCheckerClientService, + notaryServiceKey: PublicKey = notaryServiceCompositeKey, + notarySignature: DigitalSignatureAndMetadata = signatureAlice, + filteredTxContents: Map = emptyMap(), + txVerificationLogic: () -> Unit = {}, + signatureVerificationLogic: () -> Unit = {} + ) { + // Get current notary and parse its data + whenever(mockMemberLookup.myInfo()).thenReturn(notaryInfo) + whenever(notaryInfo.memberProvidedContext).thenReturn(memberProvidedContext) + whenever(memberProvidedContext.parse(NOTARY_SERVICE_NAME, MemberX500Name::class.java)).thenReturn( + notaryServiceName + ) + whenever(memberProvidedContext.parse(NOTARY_SERVICE_BACKCHAIN_REQUIRED, Boolean::class.java)).thenReturn(true) + whenever( + mockTransactionSignatureService.getIdOfPublicKey( + signedTx.notaryKey, + DigestAlgorithmName.SHA2_256.name + ) + ).thenReturn(notarySignature.by) + + // Mock Filtered Transaction + val mockDependencyOutputStateAndRef = mock> { + on { ref } doReturn mockInputRef + } + + val mockOutputStateRefUtxoFilteredData = mock>> { + on { values } doReturn mapOf(0 to mockDependencyOutputStateAndRef) + } + val filteredTx = mock { + on { outputStateAndRefs } doAnswer { + @Suppress("unchecked_cast") + filteredTxContents["outputStateRefs"] as? UtxoFilteredData> + ?: mockOutputStateRefUtxoFilteredData + } + on { notaryName } doAnswer { + if (filteredTxContents.containsKey("notaryName")) { + filteredTxContents["notaryName"] as MemberX500Name? + } else { + notaryServiceName + } + } + on { notaryKey } doAnswer { + if (filteredTxContents.containsKey("notaryKey")) { + filteredTxContents["notaryKey"] as PublicKey? + } else { + notaryServiceKey + } + } + on { timeWindow } doAnswer { + if (filteredTxContents.containsKey("timeWindow")) { + filteredTxContents["timeWindow"] as TimeWindow? + } else { + mockTimeWindow + } + } + + on { verify() } doAnswer { + txVerificationLogic() + } + on { id } doReturn txId + } + + // Prepare filteredTransactionAndSignature data + val filteredTxAndSignature = FilteredTransactionAndSignatures( + filteredTx, + listOf(notarySignature) + ) + val filteredTxsAndSignatures = listOf( + filteredTxAndSignature + ) + + val mockNotarySignatureVerificationService = mock { + on { verifyNotarySignatures(any(), any(), any(), any()) } doAnswer { signatureVerificationLogic() } + } + + // Mock the receive and send from the counterparty session, unless it is overwritten + val paramOrDefaultSession = mock { + on { receive(ContractVerifyingNotarizationPayload::class.java) } doReturn ContractVerifyingNotarizationPayload( + signedTx, + filteredTxsAndSignatures + ) + on { send(any()) } doAnswer { + responseFromServer.add(it.arguments.first() as NotarizationResponse) + Unit + } + on { counterparty } doReturn memberCharlieName + } + + val server = ContractVerifyingNotaryServerFlowImpl( + clientService, + mockTransactionSignatureService, + mockLedgerService, + mockMemberLookup, + mockNotarySignatureVerificationService + ) + + server.call(paramOrDefaultSession) + } + + private fun throwVerify() { + throw IllegalArgumentException("DUMMY ERROR") + } + + private fun mockSuccessfulUniquenessClientService(): LedgerUniquenessCheckerClientService { + return mockUniquenessClientService(UniquenessCheckResultSuccessImpl(Instant.now())) + } + + private fun mockErrorUniquenessClientService( + errorType: UniquenessCheckError + ): LedgerUniquenessCheckerClientService { + return mockUniquenessClientService( + UniquenessCheckResultFailureImpl( + Instant.now(), + errorType + ) + ) + } + + private fun mockThrowErrorUniquenessCheckClientService() = mock { + on { requestUniquenessCheck(any(), any(), any(), any(), any(), any(), any()) } doThrow + IllegalArgumentException("Uniqueness checker cannot be reached") + } + + private fun mockUniquenessClientService(response: UniquenessCheckResult) = + mock { + on { requestUniquenessCheck(any(), any(), any(), any(), any(), any(), any()) } doReturn response + } +} \ No newline at end of file diff --git a/notary-plugins/notary-plugin-non-validating/notary-plugin-non-validating-client/build.gradle b/notary-plugins/notary-plugin-non-validating/notary-plugin-non-validating-client/build.gradle index c0d1cee5413..6f0342e96c4 100644 --- a/notary-plugins/notary-plugin-non-validating/notary-plugin-non-validating-client/build.gradle +++ b/notary-plugins/notary-plugin-non-validating/notary-plugin-non-validating-client/build.gradle @@ -33,10 +33,7 @@ dependencies { // Common package pulled in as transitive dependency through API cordapp project(":notary-plugins:notary-plugin-non-validating:notary-plugin-non-validating-api") - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" - + testImplementation libs.bundles.test testImplementation project(':libs:serialization:serialization-amqp') testImplementation project(':libs:crypto:cipher-suite') testImplementation project(":testing:crypto-testkit") diff --git a/notary-plugins/notary-plugin-non-validating/notary-plugin-non-validating-server/build.gradle b/notary-plugins/notary-plugin-non-validating/notary-plugin-non-validating-server/build.gradle index 42fa7472778..d8d1b6b9c27 100644 --- a/notary-plugins/notary-plugin-non-validating/notary-plugin-non-validating-server/build.gradle +++ b/notary-plugins/notary-plugin-non-validating/notary-plugin-non-validating-server/build.gradle @@ -28,10 +28,7 @@ dependencies { // Common package pulled in as transitive dependency through API cordapp project(":notary-plugins:notary-plugin-non-validating:notary-plugin-non-validating-api") - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" - + testImplementation libs.bundles.test testImplementation project(":libs:crypto:crypto-core") testImplementation project(':libs:serialization:serialization-amqp') testImplementation project(":libs:uniqueness:common") diff --git a/notary-plugins/notary-plugin-non-validating/notary-plugin-non-validating-server/src/main/kotlin/com/r3/corda/notary/plugin/nonvalidating/server/NonValidatingNotaryServerFlowImpl.kt b/notary-plugins/notary-plugin-non-validating/notary-plugin-non-validating-server/src/main/kotlin/com/r3/corda/notary/plugin/nonvalidating/server/NonValidatingNotaryServerFlowImpl.kt index 0cf15f89708..02ac88cbc56 100644 --- a/notary-plugins/notary-plugin-non-validating/notary-plugin-non-validating-server/src/main/kotlin/com/r3/corda/notary/plugin/nonvalidating/server/NonValidatingNotaryServerFlowImpl.kt +++ b/notary-plugins/notary-plugin-non-validating/notary-plugin-non-validating-server/src/main/kotlin/com/r3/corda/notary/plugin/nonvalidating/server/NonValidatingNotaryServerFlowImpl.kt @@ -1,5 +1,6 @@ package com.r3.corda.notary.plugin.nonvalidating.server +import com.r3.corda.notary.plugin.common.NotaryTransactionDetails import com.r3.corda.notary.plugin.common.NotarizationResponse import com.r3.corda.notary.plugin.common.NotaryExceptionGeneral import com.r3.corda.notary.plugin.common.toNotarizationResponse @@ -127,7 +128,7 @@ class NonValidatingNotaryServerFlowImpl() : ResponderFlow { * This function will validate selected notary is valid notary to notarize. * */ @Suspendable - private fun validateTransactionNotaryAgainstCurrentNotary(txDetails: NonValidatingNotaryTransactionDetails) { + private fun validateTransactionNotaryAgainstCurrentNotary(txDetails: NotaryTransactionDetails) { val currentNotaryContext = memberLookup .myInfo() .memberProvidedContext @@ -153,7 +154,7 @@ class NonValidatingNotaryServerFlowImpl() : ResponderFlow { */ @Suspendable @Suppress("TooGenericExceptionCaught") - private fun validateRequest(requestPayload: NonValidatingNotarizationPayload): NonValidatingNotaryTransactionDetails { + private fun validateRequest(requestPayload: NonValidatingNotarizationPayload): NotaryTransactionDetails { val transactionParts = try { extractParts(requestPayload) } catch (e: Exception) { @@ -167,10 +168,10 @@ class NonValidatingNotaryServerFlowImpl() : ResponderFlow { } /** - * A helper function that constructs an instance of [NonValidatingNotaryTransactionDetails] from the given transaction. + * A helper function that constructs an instance of [NotaryTransactionDetails] from the given transaction. */ @Suspendable - private fun extractParts(requestPayload: NonValidatingNotarizationPayload): NonValidatingNotaryTransactionDetails { + private fun extractParts(requestPayload: NonValidatingNotarizationPayload): NotaryTransactionDetails { val filteredTx = requestPayload.transaction as UtxoFilteredTransaction // The notary component is not needed by us but we validate that it is present just in case @@ -202,7 +203,7 @@ class NonValidatingNotaryServerFlowImpl() : ResponderFlow { "Could not fetch output states from the filtered transaction" } - return NonValidatingNotaryTransactionDetails( + return NotaryTransactionDetails( filteredTx.id, filteredTx.metadata, outputStates.size, diff --git a/osgi-framework-bootstrap/build.gradle b/osgi-framework-bootstrap/build.gradle index 8090f8bb65c..a4c8534ae82 100755 --- a/osgi-framework-bootstrap/build.gradle +++ b/osgi-framework-bootstrap/build.gradle @@ -29,10 +29,11 @@ dependencies { runtimeOnly "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion" runtimeOnly "com.fasterxml.jackson.core:jackson-annotations:$jacksonVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" + testImplementation libs.mockito.core testImplementation "org.apache.sling:org.apache.sling.testing.osgi-mock.junit5:$slingVersion" - testImplementation "org.junit.jupiter:junit-jupiter-api:$junit5Version" - testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$junit5Version" + testImplementation libs.junit.api + testImplementation libs.assertj.core + testRuntimeOnly libs.junit.engine testBundles project(':testing:apps:test-app') } diff --git a/processors/crypto-processor/build.gradle b/processors/crypto-processor/build.gradle index ddfdd90fd8e..574e151a821 100644 --- a/processors/crypto-processor/build.gradle +++ b/processors/crypto-processor/build.gradle @@ -98,9 +98,6 @@ dependencies { integrationTestRuntimeOnly "org.ops4j.pax.jdbc:pax-jdbc-hsqldb:$paxJdbcVersion" integrationTestRuntimeOnly "org.hsqldb:hsqldb:$hsqldbVersion" - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation project(':libs:lifecycle:lifecycle-test-impl') testRuntimeOnly project(':libs:lifecycle:lifecycle-impl') } diff --git a/processors/db-processor/build.gradle b/processors/db-processor/build.gradle index c4fb4634917..073934279b5 100644 --- a/processors/db-processor/build.gradle +++ b/processors/db-processor/build.gradle @@ -103,8 +103,5 @@ dependencies { testRuntimeOnly "org.postgresql:postgresql:$postgresDriverVersion" - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation project(':testing:test-utilities') } diff --git a/processors/db-processor/src/main/kotlin/net/corda/processors/db/internal/reconcile/db/DbReconcilerReader.kt b/processors/db-processor/src/main/kotlin/net/corda/processors/db/internal/reconcile/db/DbReconcilerReader.kt index 647b4966d3b..4d0da6a1084 100644 --- a/processors/db-processor/src/main/kotlin/net/corda/processors/db/internal/reconcile/db/DbReconcilerReader.kt +++ b/processors/db-processor/src/main/kotlin/net/corda/processors/db/internal/reconcile/db/DbReconcilerReader.kt @@ -85,6 +85,7 @@ class DbReconcilerReader( } } catch (e: Exception) { logger.warn("Error while retrieving DB records for reconciliation for ${context.prettyPrint()}", e) + context.close() Stream.empty() } } diff --git a/processors/gateway-processor/build.gradle b/processors/gateway-processor/build.gradle index 7d9e1fece40..10c0ba7b1b9 100644 --- a/processors/gateway-processor/build.gradle +++ b/processors/gateway-processor/build.gradle @@ -17,6 +17,7 @@ dependencies { implementation project(':libs:lifecycle:lifecycle') implementation project(':libs:messaging:messaging') implementation project(':libs:schema-registry:schema-registry') + implementation project(':libs:platform-info') implementation 'net.corda:corda-base' runtimeOnly project(':components:configuration:configuration-read-service-impl') diff --git a/processors/gateway-processor/src/main/kotlin/net/corda/processors/p2p/gateway/internal/GatewayProcessorImpl.kt b/processors/gateway-processor/src/main/kotlin/net/corda/processors/p2p/gateway/internal/GatewayProcessorImpl.kt index cfa4d27dafb..9f02c535dfa 100644 --- a/processors/gateway-processor/src/main/kotlin/net/corda/processors/p2p/gateway/internal/GatewayProcessorImpl.kt +++ b/processors/gateway-processor/src/main/kotlin/net/corda/processors/p2p/gateway/internal/GatewayProcessorImpl.kt @@ -4,6 +4,7 @@ import net.corda.configuration.read.ConfigurationReadService import net.corda.crypto.client.CryptoOpsClient import net.corda.libs.configuration.SmartConfig import net.corda.libs.configuration.merger.ConfigMerger +import net.corda.libs.platform.PlatformInfoProvider import net.corda.lifecycle.LifecycleCoordinator import net.corda.lifecycle.LifecycleCoordinatorFactory import net.corda.lifecycle.LifecycleCoordinatorName @@ -39,7 +40,9 @@ class GatewayProcessorImpl @Activate constructor( @Reference(service = CryptoOpsClient::class) private val cryptoOpsClient: CryptoOpsClient, @Reference(service = AvroSchemaRegistry::class) - private val avroSchemaRegistry: AvroSchemaRegistry + private val avroSchemaRegistry: AvroSchemaRegistry, + @Reference(service = PlatformInfoProvider::class) + private val platformInfoProvider: PlatformInfoProvider, ) : GatewayProcessor { private companion object { @@ -79,9 +82,11 @@ class GatewayProcessorImpl @Activate constructor( subscriptionFactory, publisherFactory, coordinatorFactory, - configMerger.getMessagingConfig(event.config), cryptoOpsClient, - avroSchemaRegistry + avroSchemaRegistry, + platformInfoProvider, + bootConfig = event.config, + messagingConfiguration = configMerger.getMessagingConfig(event.config), ) this.gateway = gateway diff --git a/processors/member-processor/build.gradle b/processors/member-processor/build.gradle index d5c0e94d25b..0f3fcab555a 100644 --- a/processors/member-processor/build.gradle +++ b/processors/member-processor/build.gradle @@ -65,8 +65,6 @@ dependencies { runtimeOnly project(':components:membership:members-client-certificate-publisher-service-impl') runtimeOnly project(":libs:web:web-impl") - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation project(":testing:test-utilities") testImplementation "net.corda:corda-topic-schema" testImplementation "net.corda:corda-config-schema" diff --git a/processors/persistence-processor/build.gradle b/processors/persistence-processor/build.gradle index d86e6b7b8ee..7a211e24dab 100644 --- a/processors/persistence-processor/build.gradle +++ b/processors/persistence-processor/build.gradle @@ -45,8 +45,5 @@ dependencies { testRuntimeOnly "org.postgresql:postgresql:$postgresDriverVersion" - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation project(':testing:test-utilities') } diff --git a/processors/rest-processor/build.gradle b/processors/rest-processor/build.gradle index 6b48db2cccd..c242f54d7c3 100644 --- a/processors/rest-processor/build.gradle +++ b/processors/rest-processor/build.gradle @@ -72,8 +72,6 @@ dependencies { runtimeOnly project(':libs:virtual-node:cpi-upload-manager-impl') runtimeOnly project(':components:virtual-node:cpi-upload-rest-service') - integrationTestImplementation "org.assertj:assertj-core:$assertjVersion" - integrationTestImplementation "org.osgi:org.osgi.test.junit5:$osgiTestJunit5Version" integrationTestImplementation "io.swagger.core.v3:swagger-core:$swaggerVersion" integrationTestImplementation project(':libs:rest:rest') diff --git a/processors/scheduler-processor/build.gradle b/processors/scheduler-processor/build.gradle index 6d06f143f85..13ebc2143d9 100644 --- a/processors/scheduler-processor/build.gradle +++ b/processors/scheduler-processor/build.gradle @@ -37,9 +37,6 @@ dependencies { testRuntimeOnly "org.postgresql:postgresql:$postgresDriverVersion" - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation project(':testing:test-utilities') integrationTestImplementation "net.corda:corda-avro-schema" diff --git a/settings.gradle b/settings.gradle index 69fc96c2395..bff78a63320 100644 --- a/settings.gradle +++ b/settings.gradle @@ -40,9 +40,6 @@ pluginManagement { id 'com.gradle.enterprise' version gradleEnterpriseVersion id 'com.gradle.common-custom-user-data-gradle-plugin' version gradleDataPlugin id 'net.corda.cordapp.cordapp-configuration' version cordaApiVersion - id 'org.jetbrains.kotlin.jvm' version kotlinVersion - id 'org.jetbrains.kotlin.plugin.allopen' version kotlinVersion - id 'org.jetbrains.kotlin.plugin.jpa' version kotlinVersion id 'net.corda.plugins.cordapp-cpk2' version cordaGradlePluginsVersion id 'net.corda.plugins.cordapp-cpb2' version cordaGradlePluginsVersion id 'io.gitlab.arturbosch.detekt' version detektPluginVersion @@ -375,6 +372,9 @@ include 'notary-plugins:notary-plugin-common' include 'notary-plugins:notary-plugin-non-validating:notary-plugin-non-validating-api' include 'notary-plugins:notary-plugin-non-validating:notary-plugin-non-validating-client' include 'notary-plugins:notary-plugin-non-validating:notary-plugin-non-validating-server' +include 'notary-plugins:notary-plugin-contract-verifying:notary-plugin-contract-verifying-api' +include 'notary-plugins:notary-plugin-contract-verifying:notary-plugin-contract-verifying-client' +include 'notary-plugins:notary-plugin-contract-verifying:notary-plugin-contract-verifying-server' include 'osgi-framework-api' include 'osgi-framework-bootstrap' include 'processors:crypto-processor' diff --git a/testing/apps/test-app/build.gradle b/testing/apps/test-app/build.gradle index d7a1626d3c2..88cf1cea581 100644 --- a/testing/apps/test-app/build.gradle +++ b/testing/apps/test-app/build.gradle @@ -18,6 +18,4 @@ dependencies { implementation 'org.jetbrains.kotlin:kotlin-osgi-bundle' compileOnly 'org.slf4j:slf4j-api' compileOnly project(':osgi-framework-api') - - testImplementation "org.junit.jupiter:junit-jupiter-api:$junit5Version" } diff --git a/testing/cpbs/ledger-consensual-demo-app/build.gradle b/testing/cpbs/ledger-consensual-demo-app/build.gradle index 068f5ccdbed..7b5ebd28a00 100644 --- a/testing/cpbs/ledger-consensual-demo-app/build.gradle +++ b/testing/cpbs/ledger-consensual-demo-app/build.gradle @@ -20,10 +20,9 @@ dependencies { cordapp project(':testing:cpbs:ledger-consensual-demo-contract') + testImplementation libs.bundles.test testImplementation project(":libs:application:application-impl") testImplementation project(':libs:crypto:crypto-core') testImplementation project(":libs:sandbox-types") - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/testing/cpbs/ledger-utxo-demo-app/build.gradle b/testing/cpbs/ledger-utxo-demo-app/build.gradle index eac5230bc5b..e35198a49ac 100644 --- a/testing/cpbs/ledger-utxo-demo-app/build.gradle +++ b/testing/cpbs/ledger-utxo-demo-app/build.gradle @@ -20,11 +20,10 @@ dependencies { cordapp project(':testing:cpbs:ledger-utxo-demo-contract') + testImplementation libs.bundles.test testImplementation project(":libs:application:application-impl") testImplementation project(':libs:crypto:crypto-core') testImplementation project(":libs:sandbox-types") - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" // Common and API packages pulled in as transitive dependencies through client cordapp project(':notary-plugins:notary-plugin-non-validating:notary-plugin-non-validating-client') diff --git a/testing/cpbs/ledger-utxo-demo-contract/build.gradle b/testing/cpbs/ledger-utxo-demo-contract/build.gradle index 38fa47c50e6..75796159d0c 100644 --- a/testing/cpbs/ledger-utxo-demo-contract/build.gradle +++ b/testing/cpbs/ledger-utxo-demo-contract/build.gradle @@ -20,6 +20,4 @@ dependencies { testImplementation project(":libs:application:application-impl") testImplementation project(":libs:sandbox-types") - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/testing/cpi-info-read-service-fake/build.gradle b/testing/cpi-info-read-service-fake/build.gradle index a45987c0a2f..8486e4d93b0 100644 --- a/testing/cpi-info-read-service-fake/build.gradle +++ b/testing/cpi-info-read-service-fake/build.gradle @@ -24,6 +24,4 @@ dependencies { testImplementation project(":libs:lifecycle:lifecycle-test-impl") testImplementation project(":libs:lifecycle:registry") - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/testing/db-message-bus-testkit/build.gradle b/testing/db-message-bus-testkit/build.gradle index 8a886961cc4..7d7eaf53395 100644 --- a/testing/db-message-bus-testkit/build.gradle +++ b/testing/db-message-bus-testkit/build.gradle @@ -9,7 +9,7 @@ dependencies { compileOnly 'org.osgi:org.osgi.service.component.annotations' implementation "org.osgi:org.osgi.test.junit5:$osgiTestJunit5Version" - implementation "org.junit.jupiter:junit-jupiter-api:$junit5Version" + implementation libs.junit.api implementation platform("net.corda:corda-api:$cordaApiVersion") implementation 'org.jetbrains.kotlin:kotlin-osgi-bundle' diff --git a/testing/e2e-test-utilities/build.gradle b/testing/e2e-test-utilities/build.gradle index 9a80cc782f0..20cb267734d 100644 --- a/testing/e2e-test-utilities/build.gradle +++ b/testing/e2e-test-utilities/build.gradle @@ -23,9 +23,9 @@ dependencies { implementation "com.konghq:unirest-java:$unirestVersion" implementation "com.typesafe:config:$typeSafeConfigVersion" implementation "org.apache.commons:commons-text:$commonsTextVersion" - implementation "org.assertj:assertj-core:$assertjVersion" + implementation libs.assertj.core implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:$kotlinCoroutinesVersion" - implementation "org.junit.jupiter:junit-jupiter-api:$junit5Version" + implementation libs.junit.api implementation "org.slf4j:slf4j-api:$slf4jVersion" implementation project(':components:flow:flow-rest-resource-service') diff --git a/testing/e2e-test-utilities/src/main/kotlin/net/corda/e2etest/utilities/ClusterBuilder.kt b/testing/e2e-test-utilities/src/main/kotlin/net/corda/e2etest/utilities/ClusterBuilder.kt index d581a0134e9..f3293f6bb40 100644 --- a/testing/e2e-test-utilities/src/main/kotlin/net/corda/e2etest/utilities/ClusterBuilder.kt +++ b/testing/e2e-test-utilities/src/main/kotlin/net/corda/e2etest/utilities/ClusterBuilder.kt @@ -298,13 +298,14 @@ class ClusterBuilder { private fun registerNotaryBody( notaryServiceName: String, customMetadata: Map, - isBackchainRequiredNotary: Boolean = true + isBackchainRequiredNotary: Boolean = true, + notaryPlugin: String = "nonvalidating" ): String { val context = (mapOf( "corda.key.scheme" to "CORDA.ECDSA.SECP256R1", "corda.roles.0" to "notary", "corda.notary.service.name" to "$notaryServiceName", - "corda.notary.service.flow.protocol.name" to "com.r3.corda.notary.plugin.nonvalidating", + "corda.notary.service.flow.protocol.name" to "com.r3.corda.notary.plugin.$notaryPlugin", "corda.notary.service.flow.protocol.version.0" to "1", "corda.notary.service.backchain.required" to "$isBackchainRequiredNotary" ) + customMetadata) @@ -448,13 +449,15 @@ class ClusterBuilder { holdingIdShortHash: String, notaryServiceName: String? = null, customMetadata: Map = emptyMap(), - isBackchainRequiredNotary: Boolean = true + isBackchainRequiredNotary: Boolean = true, + notaryPlugin: String = "nonvalidating" ) = register( holdingIdShortHash, if (notaryServiceName != null) registerNotaryBody( notaryServiceName, customMetadata, - isBackchainRequiredNotary + isBackchainRequiredNotary, + notaryPlugin ) else registerMemberBody( customMetadata ) diff --git a/testing/e2e-test-utilities/src/main/kotlin/net/corda/e2etest/utilities/MembershipUtils.kt b/testing/e2e-test-utilities/src/main/kotlin/net/corda/e2etest/utilities/MembershipUtils.kt index 7781e61e19f..4e2ee624dec 100644 --- a/testing/e2e-test-utilities/src/main/kotlin/net/corda/e2etest/utilities/MembershipUtils.kt +++ b/testing/e2e-test-utilities/src/main/kotlin/net/corda/e2etest/utilities/MembershipUtils.kt @@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.ObjectMapper import net.corda.e2etest.utilities.types.NetworkOnboardingMetadata import net.corda.e2etest.utilities.types.jsonToMemberList import net.corda.rest.ResponseCode +import net.corda.rest.annotations.RestApiVersion import net.corda.test.util.eventually import net.corda.utilities.minutes import net.corda.utilities.seconds @@ -156,7 +157,8 @@ fun ClusterInfo.onboardNotaryMember( getAdditionalContext: ((holdingId: String) -> Map)? = null, tlsCertificateUploadedCallback: (String) -> Unit = {}, notaryServiceName: String = DEFAULT_NOTARY_SERVICE, - isBackchainRequired: Boolean = true + isBackchainRequired: Boolean = true, + notaryPlugin: String = "nonvalidating" ) = onboardMember( resourceName, cpiName, @@ -170,12 +172,16 @@ fun ClusterInfo.onboardNotaryMember( mapOf( "corda.roles.0" to "notary", "corda.notary.service.name" to MemberX500Name.parse(notaryServiceName).toString(), - "corda.notary.service.backchain.required" to "$isBackchainRequired", - "corda.notary.service.flow.protocol.name" to "com.r3.corda.notary.plugin.nonvalidating", + "corda.notary.service.flow.protocol.name" to "com.r3.corda.notary.plugin.$notaryPlugin", "corda.notary.service.flow.protocol.version.0" to "1", "corda.notary.keys.0.id" to notaryKeyId, "corda.notary.keys.0.signature.spec" to DEFAULT_SIGNATURE_SPEC - ) + (getAdditionalContext?.let { it(holdingId) } ?: emptyMap()) + ) + (getAdditionalContext?.let { it(holdingId) } ?: emptyMap()) + ( + // Add the optional backchain property if version is >= 5.2 + if (restApiVersion != RestApiVersion.C5_0 && restApiVersion != RestApiVersion.C5_1) + mapOf("corda.notary.service.backchain.required" to "$isBackchainRequired") + else emptyMap() + ) }, tlsCertificateUploadedCallback = tlsCertificateUploadedCallback, useLedgerKey = false @@ -291,22 +297,38 @@ fun registerStaticMember( holdingIdentityShortHash: String, notaryServiceName: String? = null, customMetadata: Map = emptyMap(), - isBackchainRequired: Boolean = true -) = DEFAULT_CLUSTER.registerStaticMember(holdingIdentityShortHash, notaryServiceName, customMetadata, isBackchainRequired) + isBackchainRequired: Boolean = true, + notaryPlugin: String = "nonvalidating" +) = DEFAULT_CLUSTER.registerStaticMember( + holdingIdentityShortHash, + notaryServiceName, + customMetadata, + isBackchainRequired, + notaryPlugin +) val memberRegisterLock = ReentrantLock() fun ClusterInfo.registerStaticMember( holdingIdentityShortHash: String, notaryServiceName: String? = null, customMetadata: Map = emptyMap(), - isBackchainRequired: Boolean = true + isBackchainRequired: Boolean = true, + notaryPlugin: String = "nonvalidating" ) { cluster { memberRegisterLock.withLock { assertWithRetry { interval(1.seconds) timeout(10.seconds) - command { registerStaticMember(holdingIdentityShortHash, notaryServiceName, customMetadata, isBackchainRequired) } + command { + registerStaticMember( + holdingIdentityShortHash, + notaryServiceName, + customMetadata, + isBackchainRequired, + notaryPlugin + ) + } condition { it.code == ResponseCode.OK.statusCode && it.toJson()["registrationStatus"].textValue() == REGISTRATION_SUBMITTED diff --git a/testing/flow/external-events/build.gradle b/testing/flow/external-events/build.gradle index 8f7a3ce04d5..dfbddccffdb 100644 --- a/testing/flow/external-events/build.gradle +++ b/testing/flow/external-events/build.gradle @@ -14,15 +14,10 @@ dependencies { implementation 'net.corda:corda-base' implementation 'net.corda:corda-topic-schema' implementation 'org.jetbrains.kotlin:kotlin-osgi-bundle' - implementation "org.assertj:assertj-core:$assertjVersion" implementation project(':libs:configuration:configuration-core') implementation project(':libs:flows:external-event-responses') implementation project(':libs:lifecycle:lifecycle') implementation project(":libs:messaging:messaging") implementation project(':testing:test-utilities') - - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/testing/kryo-serialization-testkit/build.gradle b/testing/kryo-serialization-testkit/build.gradle index 97d8844bae5..a8d21eeaf6c 100644 --- a/testing/kryo-serialization-testkit/build.gradle +++ b/testing/kryo-serialization-testkit/build.gradle @@ -9,7 +9,7 @@ dependencies { implementation platform("net.corda:corda-api:$cordaApiVersion") implementation 'org.jetbrains.kotlin:kotlin-osgi-bundle' implementation "com.esotericsoftware:kryo:$kryoVersion" - implementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" + implementation libs.mockito.kotlin implementation project(":libs:serialization:serialization-kryo") implementation project(":libs:serialization:serialization-checkpoint-api") diff --git a/testing/ledger/ledger-common-base-test/build.gradle b/testing/ledger/ledger-common-base-test/build.gradle index 3293ad61efa..6f2bae08963 100644 --- a/testing/ledger/ledger-common-base-test/build.gradle +++ b/testing/ledger/ledger-common-base-test/build.gradle @@ -23,5 +23,5 @@ dependencies { implementation project(':libs:serialization:serialization-amqp') implementation project(':libs:serialization:serialization-internal') - implementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" + implementation libs.mockito.kotlin } \ No newline at end of file diff --git a/testing/ledger/ledger-consensual-base-test/build.gradle b/testing/ledger/ledger-consensual-base-test/build.gradle index 102facc9a69..6b08b99f72b 100644 --- a/testing/ledger/ledger-consensual-base-test/build.gradle +++ b/testing/ledger/ledger-consensual-base-test/build.gradle @@ -12,5 +12,5 @@ dependencies { implementation project(':components:ledger:ledger-consensual-flow') implementation project(":libs:serialization:json-validator") - implementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" + implementation libs.mockito.kotlin } \ No newline at end of file diff --git a/testing/ledger/ledger-utxo-base-test/build.gradle b/testing/ledger/ledger-utxo-base-test/build.gradle index c107d3fed3e..38c40b4cd01 100644 --- a/testing/ledger/ledger-utxo-base-test/build.gradle +++ b/testing/ledger/ledger-utxo-base-test/build.gradle @@ -14,5 +14,5 @@ dependencies { implementation project(':components:ledger:ledger-utxo-flow') implementation project(':libs:membership:membership-common') implementation project(':libs:flows:flow-api') - implementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" + implementation libs.mockito.kotlin } diff --git a/testing/ledger/ledger-utxo-base-test/src/main/kotlin/net/corda/ledger/utxo/test/UtxoLedgerTest.kt b/testing/ledger/ledger-utxo-base-test/src/main/kotlin/net/corda/ledger/utxo/test/UtxoLedgerTest.kt index 8c680f3caf5..ae037309e78 100644 --- a/testing/ledger/ledger-utxo-base-test/src/main/kotlin/net/corda/ledger/utxo/test/UtxoLedgerTest.kt +++ b/testing/ledger/ledger-utxo-base-test/src/main/kotlin/net/corda/ledger/utxo/test/UtxoLedgerTest.kt @@ -23,6 +23,7 @@ import net.corda.ledger.utxo.testkit.anotherNotaryX500Name import net.corda.ledger.utxo.testkit.getUtxoSignedTransactionExample import net.corda.ledger.utxo.testkit.notaryX500Name import net.corda.ledger.utxo.flow.impl.groupparameters.verifier.SignedGroupParametersVerifier +import net.corda.ledger.utxo.flow.impl.transaction.verifier.NotarySignatureVerificationServiceInternal import net.corda.sandboxgroupcontext.CurrentSandboxGroupContext import net.corda.v5.ledger.common.NotaryLookup import net.corda.v5.membership.NotaryInfo @@ -35,6 +36,7 @@ abstract class UtxoLedgerTest : CommonLedgerTest() { private val mockUtxoLedgerGroupParametersPersistenceService = mock() private val mockGroupParametersLookup = mockGroupParametersLookup() private val mockSignedGroupParametersVerifier = mock() + private val mockNotarySignatureVerificationService = mock() val mockUtxoLedgerStateQueryService = mock() val mockCurrentSandboxGroupContext = mock() @@ -82,7 +84,8 @@ abstract class UtxoLedgerTest : CommonLedgerTest() { mockUtxoLedgerTransactionVerificationService, mockUtxoLedgerGroupParametersPersistenceService, mockGroupParametersLookup, - mockSignedGroupParametersVerifier + mockSignedGroupParametersVerifier, + mockNotarySignatureVerificationService ) val utxoLedgerService = UtxoLedgerServiceImpl( utxoFilteredTransactionFactory, @@ -99,13 +102,15 @@ abstract class UtxoLedgerTest : CommonLedgerTest() { val utxoSignedTransactionKryoSerializer = UtxoSignedTransactionKryoSerializer( serializationServiceWithWireTx, fakeTransactionSignatureService(), - utxoLedgerTransactionFactory + utxoLedgerTransactionFactory, + mockNotarySignatureVerificationService ) val utxoSignedTransactionAMQPSerializer = UtxoSignedTransactionSerializer( serializationServiceNullCfg, fakeTransactionSignatureService(), - utxoLedgerTransactionFactory + utxoLedgerTransactionFactory, + mockNotarySignatureVerificationService ) val utxoSignedTransactionExample = getUtxoSignedTransactionExample( digestService, @@ -114,6 +119,7 @@ abstract class UtxoLedgerTest : CommonLedgerTest() { jsonMarshallingService, jsonValidator, fakeTransactionSignatureService(), + mockNotarySignatureVerificationService, utxoLedgerTransactionFactory ) diff --git a/testing/ledger/ledger-utxo-testkit/src/main/kotlin/net/corda/ledger/utxo/testkit/UtxoSignedTransactionExample.kt b/testing/ledger/ledger-utxo-testkit/src/main/kotlin/net/corda/ledger/utxo/testkit/UtxoSignedTransactionExample.kt index c857e2e354c..27778534d62 100644 --- a/testing/ledger/ledger-utxo-testkit/src/main/kotlin/net/corda/ledger/utxo/testkit/UtxoSignedTransactionExample.kt +++ b/testing/ledger/ledger-utxo-testkit/src/main/kotlin/net/corda/ledger/utxo/testkit/UtxoSignedTransactionExample.kt @@ -14,6 +14,7 @@ import net.corda.ledger.utxo.flow.impl.transaction.UtxoSignedTransactionImpl import net.corda.ledger.utxo.flow.impl.transaction.UtxoSignedTransactionInternal import net.corda.ledger.utxo.flow.impl.transaction.factory.UtxoLedgerTransactionFactory import net.corda.ledger.utxo.flow.impl.transaction.factory.UtxoSignedTransactionFactory +import net.corda.ledger.utxo.flow.impl.transaction.verifier.NotarySignatureVerificationServiceInternal import net.corda.v5.application.crypto.DigestService import net.corda.v5.application.marshalling.JsonMarshallingService import net.corda.v5.application.serialization.SerializationService @@ -45,6 +46,7 @@ fun getUtxoSignedTransactionExample( jsonMarshallingService: JsonMarshallingService, jsonValidator: JsonValidator, transactionSignatureService: TransactionSignatureServiceInternal, + notarySignatureVerificationService: NotarySignatureVerificationServiceInternal, utxoLedgerTransactionFactory: UtxoLedgerTransactionFactory, cpkPackageSeed: String? = null ): UtxoSignedTransaction { @@ -58,6 +60,7 @@ fun getUtxoSignedTransactionExample( return UtxoSignedTransactionImpl( serializationService, transactionSignatureService, + notarySignatureVerificationService, utxoLedgerTransactionFactory, wireTransaction, listOf(getSignatureWithMetadataExample()) diff --git a/testing/message-patterns/build.gradle b/testing/message-patterns/build.gradle index eea227f312c..23e5ab87623 100644 --- a/testing/message-patterns/build.gradle +++ b/testing/message-patterns/build.gradle @@ -42,8 +42,6 @@ dependencies { integrationTestImplementation 'net.corda:corda-topic-schema' integrationTestImplementation "com.typesafe:config:$typeSafeConfigVersion" - integrationTestImplementation "org.assertj:assertj-core:$assertjVersion" - integrationTestImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" integrationTestImplementation "org.osgi:org.osgi.test.junit5:$osgiTestJunit5Version" integrationTestImplementation "javax.persistence:javax.persistence-api" integrationTestImplementation "org.apache.servicemix.bundles:org.apache.servicemix.bundles.kafka-clients:$kafkaClientVersion" diff --git a/testing/p2p/inmemory-messaging-impl/build.gradle b/testing/p2p/inmemory-messaging-impl/build.gradle index c80d9b9aa5a..e15a9d8ec72 100644 --- a/testing/p2p/inmemory-messaging-impl/build.gradle +++ b/testing/p2p/inmemory-messaging-impl/build.gradle @@ -23,8 +23,5 @@ dependencies { implementation 'org.slf4j:slf4j-api' integrationTestApi project(":testing:test-utilities") - testImplementation "org.assertj:assertj-core:$assertjVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation project(":libs:lifecycle:lifecycle-impl") } diff --git a/testing/persistence-testkit/build.gradle b/testing/persistence-testkit/build.gradle index 42176cf0e61..7ac8eb3cabf 100644 --- a/testing/persistence-testkit/build.gradle +++ b/testing/persistence-testkit/build.gradle @@ -23,6 +23,6 @@ dependencies { implementation 'net.corda:corda-application' implementation 'net.corda:corda-db-schema' - implementation("org.mockito:mockito-core:$mockitoVersion") - implementation("org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion") + implementation libs.mockito.core + implementation libs.mockito.kotlin } diff --git a/testing/sandboxes/build.gradle b/testing/sandboxes/build.gradle index c84e028ad34..4d7c32616af 100644 --- a/testing/sandboxes/build.gradle +++ b/testing/sandboxes/build.gradle @@ -16,7 +16,7 @@ dependencies { api project(":libs:packaging:packaging") api project(':libs:packaging:packaging-core') api project(':libs:virtual-node:virtual-node-info') - api "org.junit.jupiter:junit-jupiter-api:$junit5Version" + api libs.junit.api implementation platform("net.corda:corda-api:$cordaApiVersion") implementation 'org.jetbrains.kotlin:kotlin-osgi-bundle' diff --git a/testing/security-manager-utilities/build.gradle b/testing/security-manager-utilities/build.gradle index 75013923563..428eeb4e769 100644 --- a/testing/security-manager-utilities/build.gradle +++ b/testing/security-manager-utilities/build.gradle @@ -10,7 +10,7 @@ dependencies { implementation platform("net.corda:corda-api:$cordaApiVersion") implementation 'org.jetbrains.kotlin:kotlin-osgi-bundle' - implementation "org.mockito:mockito-core:$mockitoVersion" + implementation libs.mockito.core implementation project(':components:security-manager') } diff --git a/testing/test-serialization/build.gradle b/testing/test-serialization/build.gradle index c86c6b4f47f..70945ad68a8 100644 --- a/testing/test-serialization/build.gradle +++ b/testing/test-serialization/build.gradle @@ -20,6 +20,6 @@ dependencies { implementation project(':components:membership:membership-group-read') implementation project(":libs:virtual-node:sandbox-group-context") - implementation "org.mockito:mockito-core:$mockitoVersion" - implementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" + implementation libs.mockito.core + implementation libs.mockito.kotlin } diff --git a/testing/test-utilities/build.gradle b/testing/test-utilities/build.gradle index 88c86012189..25d3fb6e616 100644 --- a/testing/test-utilities/build.gradle +++ b/testing/test-utilities/build.gradle @@ -12,8 +12,8 @@ dependencies { api project(':libs:metrics') api project(':libs:utilities') implementation 'org.jetbrains.kotlin:kotlin-osgi-bundle' - implementation "org.junit.jupiter:junit-jupiter-api:$junit5Version" - implementation "org.mockito:mockito-core:$mockitoVersion" + implementation libs.junit.api + implementation libs.mockito.core implementation project(":components:virtual-node:cpi-info-read-service") implementation project(":libs:virtual-node:virtual-node-info") implementation project(":libs:lifecycle:lifecycle") diff --git a/testing/uniqueness/backing-store-fake/build.gradle b/testing/uniqueness/backing-store-fake/build.gradle index c7acfb3b5d0..48eca8027e5 100644 --- a/testing/uniqueness/backing-store-fake/build.gradle +++ b/testing/uniqueness/backing-store-fake/build.gradle @@ -21,8 +21,4 @@ dependencies { implementation platform("net.corda:corda-api:$cordaApiVersion") implementation project(":components:uniqueness:backing-store") implementation project(":libs:uniqueness:common") - - testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlinVersion" - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" } diff --git a/testing/uniqueness/uniqueness-utilities/build.gradle b/testing/uniqueness/uniqueness-utilities/build.gradle index 67ee8dd85ab..d33a9093ef5 100644 --- a/testing/uniqueness/uniqueness-utilities/build.gradle +++ b/testing/uniqueness/uniqueness-utilities/build.gradle @@ -15,8 +15,8 @@ dependencies { implementation "net.corda:corda-application" implementation platform("net.corda:corda-api:$cordaApiVersion") - implementation "org.junit.jupiter:junit-jupiter-api:$junit5Version" - implementation "org.assertj:assertj-core:$assertjVersion" + implementation libs.assertj.core + implementation libs.junit.api implementation project(":libs:uniqueness:common") implementation project(":libs:utilities") diff --git a/tools/plugins/db-config/build.gradle b/tools/plugins/db-config/build.gradle index 27d453df2fc..b5c2922200e 100644 --- a/tools/plugins/db-config/build.gradle +++ b/tools/plugins/db-config/build.gradle @@ -39,8 +39,7 @@ dependencies { runtimeOnly "org.postgresql:postgresql:$postgresDriverVersion" testImplementation 'org.jetbrains.kotlin:kotlin-stdlib' - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" + testImplementation libs.bundles.test testImplementation "org.pf4j:pf4j:$pf4jVersion" testCompileOnly "net.corda.cli.host:api:$pluginHostVersion" } diff --git a/tools/plugins/initial-config/build.gradle b/tools/plugins/initial-config/build.gradle index 8997d456a45..ea7392bc99a 100644 --- a/tools/plugins/initial-config/build.gradle +++ b/tools/plugins/initial-config/build.gradle @@ -33,6 +33,7 @@ dependencies { implementation project(':libs:db:db-core') compileOnly "net.corda.cli.host:api:$pluginHostVersion" + testImplementation libs.bundles.test testImplementation 'org.jetbrains.kotlin:kotlin-stdlib' testImplementation "org.pf4j:pf4j:$pf4jVersion" testImplementation "com.github.stefanbirkner:system-lambda:$systemLambdaVersion" diff --git a/tools/plugins/network/build.gradle b/tools/plugins/network/build.gradle index 0348792f06d..192cf0a2105 100644 --- a/tools/plugins/network/build.gradle +++ b/tools/plugins/network/build.gradle @@ -41,9 +41,9 @@ dependencies { implementation project(':libs:configuration:configuration-endpoints') implementation project(':libs:membership:membership-common') + testImplementation libs.bundles.test testImplementation "net.corda.cli.host:api:$pluginHostVersion" testImplementation "org.pf4j:pf4j:${pf4jVersion}" - testImplementation "org.junit.jupiter:junit-jupiter:${junit5Version}" testImplementation "com.github.stefanbirkner:system-lambda:1.2.1" pluginSmokeTestImplementation project(':testing:e2e-test-utilities') diff --git a/tools/plugins/package/build.gradle b/tools/plugins/package/build.gradle index 55695d61d8c..b22030b3fd7 100644 --- a/tools/plugins/package/build.gradle +++ b/tools/plugins/package/build.gradle @@ -29,9 +29,9 @@ dependencies { implementation "org.pf4j:pf4j:${pf4jVersion}" kapt "org.pf4j:pf4j:${pf4jVersion}" + testImplementation libs.bundles.test testImplementation "net.corda.cli.host:api:$pluginHostVersion" testImplementation "org.pf4j:pf4j:${pf4jVersion}" - testImplementation "org.junit.jupiter:junit-jupiter:${junit5Version}" testImplementation project(":testing:test-utilities") testImplementation project(":testing:packaging-test-utilities") diff --git a/tools/plugins/preinstall/build.gradle b/tools/plugins/preinstall/build.gradle index fa387ae4c8f..aca67235725 100644 --- a/tools/plugins/preinstall/build.gradle +++ b/tools/plugins/preinstall/build.gradle @@ -16,11 +16,11 @@ dependencies { kapt "org.pf4j:pf4j:$pf4jVersion" kapt "info.picocli:picocli:$picocliVersion" + testImplementation libs.bundles.test testImplementation "org.pf4j:pf4j:$pf4jVersion" testCompileOnly "net.corda.cli.host:api:$pluginHostVersion" testImplementation "com.github.stefanbirkner:system-lambda:$systemLambdaVersion" testImplementation "info.picocli:picocli:$picocliVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" implementation "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:$jacksonVersion" implementation "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion" diff --git a/tools/plugins/secret-config/build.gradle b/tools/plugins/secret-config/build.gradle index 5edd1dc2061..a209244098f 100644 --- a/tools/plugins/secret-config/build.gradle +++ b/tools/plugins/secret-config/build.gradle @@ -23,9 +23,8 @@ dependencies { implementation project(":libs:configuration:configuration-core") - testImplementation 'org.jetbrains.kotlin:kotlin-stdlib' + testImplementation libs.bundles.test testImplementation "org.pf4j:pf4j:$pf4jVersion" - testImplementation "org.junit.jupiter:junit-jupiter-params:$junit5Version" testImplementation "com.github.stefanbirkner:system-lambda:$systemLambdaVersion" testImplementation "net.corda.cli.host:api:$pluginHostVersion" } diff --git a/tools/plugins/topic-config/build.gradle b/tools/plugins/topic-config/build.gradle index 24dc6feb25c..9d99f46cb5e 100644 --- a/tools/plugins/topic-config/build.gradle +++ b/tools/plugins/topic-config/build.gradle @@ -36,9 +36,8 @@ dependencies { } } + testImplementation libs.bundles.test testImplementation 'org.jetbrains.kotlin:kotlin-stdlib' - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" testImplementation "org.pf4j:pf4j:$pf4jVersion" testImplementation "net.corda.cli.host:api:$pluginHostVersion" testImplementation "com.fasterxml.jackson.module:jackson-module-kotlin:$jacksonVersion" diff --git a/tools/plugins/virtual-node/build.gradle b/tools/plugins/virtual-node/build.gradle index 1cddca00853..d7477f68e92 100644 --- a/tools/plugins/virtual-node/build.gradle +++ b/tools/plugins/virtual-node/build.gradle @@ -47,9 +47,7 @@ dependencies { // the Postgres drivers are packaged within the tool itself. runtimeOnly "org.postgresql:postgresql:$postgresDriverVersion" - testImplementation 'org.jetbrains.kotlin:kotlin-stdlib' - testImplementation "org.mockito:mockito-core:$mockitoVersion" - testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion" + testImplementation libs.bundles.test testImplementation "org.pf4j:pf4j:$pf4jVersion" testCompileOnly "net.corda.cli.host:api:$pluginHostVersion" }