diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 3f3b539ad8..40b3511c77 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -195,6 +195,8 @@ + + @@ -229,13 +231,15 @@ + + + + - - diff --git a/experimental/flow-worker/src/main/kotlin/net/corda/flowworker/FlowWorkerServiceHub.kt b/experimental/flow-worker/src/main/kotlin/net/corda/flowworker/FlowWorkerServiceHub.kt index 6045f1001e..e990d0dd9d 100644 --- a/experimental/flow-worker/src/main/kotlin/net/corda/flowworker/FlowWorkerServiceHub.kt +++ b/experimental/flow-worker/src/main/kotlin/net/corda/flowworker/FlowWorkerServiceHub.kt @@ -117,7 +117,7 @@ class FlowWorkerServiceHub(override val configuration: NodeConfiguration, overri private val metricRegistry = MetricRegistry() override val cacheFactory = EnterpriseNamedCacheFactory(configuration.enterpriseConfiguration.getTracingConfig()).bindWithConfig(configuration).bindWithMetrics(metricRegistry).tokenize() - override val schemaService = NodeSchemaService(cordappLoader.cordappSchemas, false).tokenize() + override val schemaService = NodeSchemaService(cordappLoader.cordappSchemas).tokenize() override val identityService = PersistentIdentityService(cacheFactory).tokenize() override val database: CordaPersistence = createCordaPersistence( configuration.database, diff --git a/experimental/rpc-worker/src/main/kotlin/net/corda/rpcWorker/RpcWorkerServiceHub.kt b/experimental/rpc-worker/src/main/kotlin/net/corda/rpcWorker/RpcWorkerServiceHub.kt index 71d1022555..f72fdc896d 100644 --- a/experimental/rpc-worker/src/main/kotlin/net/corda/rpcWorker/RpcWorkerServiceHub.kt +++ b/experimental/rpc-worker/src/main/kotlin/net/corda/rpcWorker/RpcWorkerServiceHub.kt @@ -75,7 +75,7 @@ class RpcWorkerServiceHub(override val configuration: NodeConfiguration, overrid private val metricRegistry = MetricRegistry() override val cacheFactory = EnterpriseNamedCacheFactory(configuration.enterpriseConfiguration.getTracingConfig()).bindWithConfig(configuration).bindWithMetrics(metricRegistry) - override val schemaService = NodeSchemaService(cordappLoader.cordappSchemas, false) + override val schemaService = NodeSchemaService(cordappLoader.cordappSchemas) override val identityService = PersistentIdentityService(cacheFactory) override val database: CordaPersistence = createCordaPersistence( configuration.database, diff --git a/node/build.gradle b/node/build.gradle index d69f58623f..3c7117c815 100644 --- a/node/build.gradle +++ b/node/build.gradle @@ -141,9 +141,6 @@ dependencies { // For H2 database support in persistence compile "com.h2database:h2:$h2_version" - // For the MySQLUniquenessProvider - compile group: 'mysql', name: 'mysql-connector-java', version: '6.0.6' - // SQL connection pooling library compile "com.zaxxer:HikariCP:${hikari_version}" diff --git a/node/src/main/kotlin/net/corda/node/internal/cordapp/JarScanningCordappLoader.kt b/node/src/main/kotlin/net/corda/node/internal/cordapp/JarScanningCordappLoader.kt index e47badd63e..187d050ca1 100644 --- a/node/src/main/kotlin/net/corda/node/internal/cordapp/JarScanningCordappLoader.kt +++ b/node/src/main/kotlin/net/corda/node/internal/cordapp/JarScanningCordappLoader.kt @@ -9,6 +9,7 @@ import net.corda.core.flows.* import net.corda.core.internal.* import net.corda.core.internal.cordapp.CordappImpl import net.corda.core.internal.cordapp.CordappInfoResolver +import net.corda.core.internal.notary.AsyncCFTNotaryService import net.corda.core.internal.notary.NotaryService import net.corda.core.internal.notary.TrustedAuthorityNotaryService import net.corda.core.node.services.CordaService @@ -133,7 +134,8 @@ class JarScanningCordappLoader private constructor(private val cordappJarPaths: // the scanner won't find subclasses deeper down the hierarchy if any intermediate class is not // present in the CorDapp. val result = scanResult.getClassesWithSuperclass(NotaryService::class) + - scanResult.getClassesWithSuperclass(TrustedAuthorityNotaryService::class) + scanResult.getClassesWithSuperclass(TrustedAuthorityNotaryService::class) + + scanResult.getClassesWithSuperclass(AsyncCFTNotaryService::class) logger.info("Found notary service CorDapp implementations: " + result.joinToString(", ")) return result.firstOrNull() } diff --git a/node/src/main/kotlin/net/corda/node/services/transactions/MySQLNotaryService.kt b/node/src/main/kotlin/net/corda/node/services/transactions/MySQLNotaryService.kt deleted file mode 100644 index 96f2d08ff5..0000000000 --- a/node/src/main/kotlin/net/corda/node/services/transactions/MySQLNotaryService.kt +++ /dev/null @@ -1,45 +0,0 @@ -package net.corda.node.services.transactions - -import net.corda.core.flows.FlowLogic -import net.corda.core.flows.FlowSession -import net.corda.core.internal.notary.AsyncCFTNotaryService -import net.corda.node.services.api.ServiceHubInternal -import net.corda.node.services.config.MySQLConfiguration -import java.security.PublicKey - -/** Notary service backed by a replicated MySQL database. */ -abstract class MySQLNotaryService( - final override val services: ServiceHubInternal, - override val notaryIdentityKey: PublicKey, - configuration: MySQLConfiguration, - /** Database table will be automatically created in dev mode */ - val devMode: Boolean) : AsyncCFTNotaryService() { - - override val asyncUniquenessProvider = MySQLUniquenessProvider( - services.monitoringService.metrics, - services.clock, - configuration - ) - - override fun start() { - if (devMode) asyncUniquenessProvider.createTable() - } - - override fun stop() { - asyncUniquenessProvider.stop() - } -} - -class MySQLNonValidatingNotaryService(services: ServiceHubInternal, - notaryIdentityKey: PublicKey, - configuration: MySQLConfiguration, - devMode: Boolean = false) : MySQLNotaryService(services, notaryIdentityKey, configuration, devMode) { - override fun createServiceFlow(otherPartySession: FlowSession): FlowLogic = NonValidatingNotaryFlow(otherPartySession, this) -} - -class MySQLValidatingNotaryService(services: ServiceHubInternal, - notaryIdentityKey: PublicKey, - configuration: MySQLConfiguration, - devMode: Boolean = false) : MySQLNotaryService(services, notaryIdentityKey, configuration, devMode) { - override fun createServiceFlow(otherPartySession: FlowSession): FlowLogic = ValidatingNotaryFlow(otherPartySession, this) -} \ No newline at end of file diff --git a/node/src/test/kotlin/net/corda/node/services/TimedFlowTests.kt b/node/src/test/kotlin/net/corda/node/services/TimedFlowTests.kt index 88ffd0711e..c3a1fef26d 100644 --- a/node/src/test/kotlin/net/corda/node/services/TimedFlowTests.kt +++ b/node/src/test/kotlin/net/corda/node/services/TimedFlowTests.kt @@ -66,7 +66,7 @@ class TimedFlowTestRule(val clusterSize: Int) : ExternalResource() { whenever(it.custom).thenReturn(true) whenever(it.isClusterConfig).thenReturn(true) whenever(it.validating).thenReturn(true) - whenever(it.className).thenReturn(TestNotaryService::class.java.name) + whenever(it.className).thenReturn(TimedFlowTests.TestNotaryService::class.java.name) } val notaryNodes = (0 until clusterSize).map { @@ -193,7 +193,7 @@ class TimedFlowTests { }.bufferUntilSubscribed().toBlocking().toFuture() } - private class TestNotaryService(override val services: ServiceHubInternal, override val notaryIdentityKey: PublicKey) : TrustedAuthorityNotaryService() { + class TestNotaryService(override val services: ServiceHubInternal, override val notaryIdentityKey: PublicKey) : TrustedAuthorityNotaryService() { override val uniquenessProvider = mock() override fun createServiceFlow(otherPartySession: FlowSession): FlowLogic = TestNotaryFlow(otherPartySession, this) override fun start() {} diff --git a/node/src/test/kotlin/net/corda/node/services/persistence/HibernateConfigurationTest.kt b/node/src/test/kotlin/net/corda/node/services/persistence/HibernateConfigurationTest.kt index ae4fea1eac..d147af3963 100644 --- a/node/src/test/kotlin/net/corda/node/services/persistence/HibernateConfigurationTest.kt +++ b/node/src/test/kotlin/net/corda/node/services/persistence/HibernateConfigurationTest.kt @@ -37,11 +37,11 @@ import net.corda.node.services.schema.NodeSchemaService import net.corda.node.services.schema.PersistentStateService import net.corda.node.services.vault.NodeVaultService import net.corda.node.services.vault.VaultSchemaV1 -import net.corda.node.utilities.TestingNamedCacheFactory import net.corda.nodeapi.internal.persistence.CordaPersistence import net.corda.nodeapi.internal.persistence.DatabaseConfig import net.corda.nodeapi.internal.persistence.HibernateConfiguration import net.corda.testing.core.* +import net.corda.testing.internal.TestingNamedCacheFactory import net.corda.testing.internal.rigorousMock import net.corda.testing.internal.vault.DummyDealStateSchemaV1 import net.corda.testing.internal.vault.DummyLinearStateSchemaV1 diff --git a/notary/mysql/build.gradle b/notary/mysql/build.gradle new file mode 100644 index 0000000000..15c206895d --- /dev/null +++ b/notary/mysql/build.gradle @@ -0,0 +1,29 @@ +apply plugin: 'kotlin' +apply plugin: 'idea' +apply plugin: 'net.corda.plugins.cordapp' +apply plugin: 'net.corda.plugins.publish-utils' +apply plugin: 'net.corda.plugins.quasar-utils' + +dependencies { + cordaCompile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" + + // Corda integration dependencies + cordaCompile project(':node') + + // For the MySQLUniquenessProvider + compile group: 'mysql', name: 'mysql-connector-java', version: '6.0.6' + + testCompile "junit:junit:$junit_version" + testCompile project(':node-driver') +} + +idea { + module { + downloadJavadoc = true // defaults to false + downloadSources = true + } +} + +publish { + name 'corda-notary-mysql' +} diff --git a/notary/mysql/src/main/kotlin/net/corda/notary/mysql/MySQLNotaryService.kt b/notary/mysql/src/main/kotlin/net/corda/notary/mysql/MySQLNotaryService.kt new file mode 100644 index 0000000000..765f79e3bd --- /dev/null +++ b/notary/mysql/src/main/kotlin/net/corda/notary/mysql/MySQLNotaryService.kt @@ -0,0 +1,46 @@ +package net.corda.notary.mysql + +import net.corda.core.flows.FlowSession +import net.corda.core.internal.notary.AsyncCFTNotaryService +import net.corda.core.internal.notary.NotaryServiceFlow +import net.corda.node.services.api.ServiceHubInternal +import net.corda.node.services.transactions.NonValidatingNotaryFlow +import net.corda.node.services.transactions.ValidatingNotaryFlow +import java.security.PublicKey + +/** Notary service backed by a replicated MySQL database. */ +class MySQLNotaryService( + override val services: ServiceHubInternal, + override val notaryIdentityKey: PublicKey) : AsyncCFTNotaryService() { + + /** Database table will be automatically created in dev mode */ + private val devMode = services.configuration.devMode + + private val notaryConfig = services.configuration.notary + ?: throw IllegalArgumentException("Failed to register ${this::class.java}: notary configuration not present") + + override val asyncUniquenessProvider = with(services) { + val mysqlConfig = notaryConfig.mysql + ?: throw IllegalArgumentException("Failed to register ${this::class.java}: raft configuration not present") + MySQLUniquenessProvider( + services.monitoringService.metrics, + services.clock, + mysqlConfig + ) + } + + override fun createServiceFlow(otherPartySession: FlowSession): NotaryServiceFlow { + return if (notaryConfig.validating) { + ValidatingNotaryFlow(otherPartySession, this) + } else NonValidatingNotaryFlow(otherPartySession, this) + } + + + override fun start() { + if (devMode) asyncUniquenessProvider.createTable() + } + + override fun stop() { + asyncUniquenessProvider.stop() + } +} \ No newline at end of file diff --git a/node/src/main/kotlin/net/corda/node/services/transactions/MySQLUniquenessProvider.kt b/notary/mysql/src/main/kotlin/net/corda/notary/mysql/MySQLUniquenessProvider.kt similarity index 99% rename from node/src/main/kotlin/net/corda/node/services/transactions/MySQLUniquenessProvider.kt rename to notary/mysql/src/main/kotlin/net/corda/notary/mysql/MySQLUniquenessProvider.kt index 149b7506e6..537d8d276a 100644 --- a/node/src/main/kotlin/net/corda/node/services/transactions/MySQLUniquenessProvider.kt +++ b/notary/mysql/src/main/kotlin/net/corda/notary/mysql/MySQLUniquenessProvider.kt @@ -1,4 +1,4 @@ -package net.corda.node.services.transactions +package net.corda.notary.mysql import com.codahale.metrics.Gauge import com.codahale.metrics.MetricRegistry diff --git a/node/src/integration-test/kotlin/net/corda/node/services/MySQLNotaryServiceTests.kt b/notary/mysql/src/test/kotlin/net/corda/notary/mysql/MySQLNotaryServiceTests.kt similarity index 97% rename from node/src/integration-test/kotlin/net/corda/node/services/MySQLNotaryServiceTests.kt rename to notary/mysql/src/test/kotlin/net/corda/notary/mysql/MySQLNotaryServiceTests.kt index e241b93bcd..39e2deaade 100644 --- a/node/src/integration-test/kotlin/net/corda/node/services/MySQLNotaryServiceTests.kt +++ b/notary/mysql/src/test/kotlin/net/corda/notary/mysql/MySQLNotaryServiceTests.kt @@ -1,4 +1,4 @@ -package net.corda.node.services +package net.corda.notary.mysql import co.paralleluniverse.fibers.Suspendable import com.nhaarman.mockito_kotlin.doReturn @@ -24,7 +24,6 @@ import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.seconds import net.corda.node.services.config.MySQLConfiguration import net.corda.node.services.config.NotaryConfig -import net.corda.node.services.transactions.MySQLNotaryService import net.corda.nodeapi.internal.DevIdentityGenerator import net.corda.nodeapi.internal.network.NetworkParametersCopier import net.corda.testing.common.internal.testNetworkParameters @@ -64,9 +63,9 @@ class MySQLNotaryServiceTests : IntegrationTest() { @Before fun before() { - mockNet = InternalMockNetwork(cordappsForAllNodes = cordappsForPackages("net.corda.testing.contracts"), threadPerNode = true) + mockNet = InternalMockNetwork(cordappsForAllNodes = cordappsForPackages("net.corda.testing.contracts", "net.corda.notary.mysql"), threadPerNode = true) notaryParty = DevIdentityGenerator.generateDistributedNotarySingularIdentity(listOf(mockNet.baseDirectory(mockNet.nextNodeId)), notaryName) - val networkParameters = NetworkParametersCopier(testNetworkParameters(listOf(NotaryInfo(notaryParty, false)))) + val networkParameters = NetworkParametersCopier(testNetworkParameters(listOf(NotaryInfo(notaryParty, true)))) val notaryNodeUnstarted = createNotaryNode() val nodeUnstarted = mockNet.createUnstartedNode() val startedNodes = listOf(notaryNodeUnstarted, nodeUnstarted).map { n -> @@ -256,8 +255,9 @@ class MySQLNotaryServiceTests : IntegrationTest() { entropyRoot = BigInteger.valueOf(60L), configOverrides = { val notaryConfig = NotaryConfig( - validating = false, - mysql = MySQLConfiguration(dataStoreProperties, maxBatchSize = 10, maxBatchInputStates = 100) + validating = true, + mysql = MySQLConfiguration(dataStoreProperties, maxBatchSize = 10, maxBatchInputStates = 100), + className = MySQLNotaryService::class.java.name ) doReturn(notaryConfig).whenever(it).notary } diff --git a/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/flows/TwoPartyTradeFlowTest.kt b/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/flows/TwoPartyTradeFlowTest.kt index 368e20b984..2c4ad21697 100644 --- a/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/flows/TwoPartyTradeFlowTest.kt +++ b/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/flows/TwoPartyTradeFlowTest.kt @@ -327,7 +327,7 @@ class TwoPartyTradeFlowTests(private val anonymous: Boolean) { private fun makeNodeWithTracking( name: CordaX500Name): TestStartedNode { // Create a node in the mock network ... - return mockNet.createNode(InternalMockNodeParameters(legalName = name), nodeFactory = { args, _ -> + return mockNet.createNode(InternalMockNodeParameters(legalName = name), nodeFactory = { args -> object : InternalMockNetwork.MockNode(args) { // That constructs a recording tx storage override fun makeTransactionStorage(transactionCacheSizeBytes: Long): WritableTransactionStorage { diff --git a/settings.gradle b/settings.gradle index a6f0f4b173..566c46db81 100644 --- a/settings.gradle +++ b/settings.gradle @@ -81,6 +81,7 @@ include 'node:dist' include 'tools:notary-healthcheck:contract' include 'tools:notary-healthcheck:cordapp' include 'tools:notary-healthcheck:client' +include 'notary:mysql' apply from: 'buildCacheSettings.gradle' diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/InternalMockNetwork.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/InternalMockNetwork.kt index 88b22b7f70..91a43b6ce8 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/InternalMockNetwork.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/InternalMockNetwork.kt @@ -33,10 +33,7 @@ import net.corda.node.internal.InitiatedFlowFactory import net.corda.node.services.api.FlowStarter import net.corda.node.services.api.ServiceHubInternal import net.corda.node.services.api.StartedNodeServices -import net.corda.node.services.config.FlowTimeoutConfiguration -import net.corda.node.services.config.NodeConfiguration -import net.corda.node.services.config.NotaryConfig -import net.corda.node.services.config.VerifierType +import net.corda.node.services.config.* import net.corda.node.services.identity.PersistentIdentityService import net.corda.node.services.keys.E2ETestKeyManagementService import net.corda.node.services.keys.KeyManagementServiceInternal diff --git a/tools/dbmigration/src/main/kotlin/com/r3/corda/dbmigration/Launcher.kt b/tools/dbmigration/src/main/kotlin/com/r3/corda/dbmigration/Launcher.kt index ee9917ff68..5d4f55ac77 100644 --- a/tools/dbmigration/src/main/kotlin/com/r3/corda/dbmigration/Launcher.kt +++ b/tools/dbmigration/src/main/kotlin/com/r3/corda/dbmigration/Launcher.kt @@ -153,7 +153,7 @@ private class DbManagementTool : CordaCliWrapper("database-manager", "The Corda val nodeConfig = ConfigHelper.loadConfig(baseDirectory, config).parseAs(UnknownConfigKeysPolicy.IGNORE::handle) val cordappLoader = JarScanningCordappLoader.fromDirectories(setOf(baseDirectory, baseDirectory / "cordapps")) - val schemaService = NodeSchemaService(extraSchemas = cordappLoader.cordappSchemas, includeNotarySchemas = nodeConfig.notary != null) + val schemaService = NodeSchemaService(extraSchemas = cordappLoader.cordappSchemas) handleCommand(baseDirectory, config, cmdLineOptions.mode, cordappLoader.appClassLoader, schemaService.schemaOptions.keys) } diff --git a/tools/notarytest/build.gradle b/tools/notarytest/build.gradle index 01559e96de..b3a111422c 100644 --- a/tools/notarytest/build.gradle +++ b/tools/notarytest/build.gradle @@ -15,6 +15,7 @@ dependencies { cordaCompile project(':core') cordaCompile project(':client:rpc') cordaCompile project(':node-driver') + compile project(':notary:mysql') compile project(':client:mock') compile group: 'mysql', name: 'mysql-connector-java', version: '6.0.6' compile group: 'io.dropwizard.metrics', name: 'metrics-graphite', version: '3.2.5' diff --git a/tools/notarytest/src/main/kotlin/net/corda/notarytest/service/JDBCNotaryService.kt b/tools/notarytest/src/main/kotlin/net/corda/notarytest/service/JDBCNotaryService.kt index b81ec0863a..6567514cae 100644 --- a/tools/notarytest/src/main/kotlin/net/corda/notarytest/service/JDBCNotaryService.kt +++ b/tools/notarytest/src/main/kotlin/net/corda/notarytest/service/JDBCNotaryService.kt @@ -13,9 +13,9 @@ import net.corda.core.node.services.CordaService import net.corda.core.utilities.NetworkHostAndPort import net.corda.node.services.config.ConfigHelper import net.corda.node.services.config.MySQLConfiguration -import net.corda.node.services.transactions.MySQLUniquenessProvider import net.corda.node.services.transactions.NonValidatingNotaryFlow import net.corda.nodeapi.internal.config.parseAs +import net.corda.notary.mysql.MySQLUniquenessProvider import net.corda.notarytest.flows.AsyncLoadTestFlow import java.net.InetAddress import java.net.InetSocketAddress