diff --git a/.ci/api-current.txt b/.ci/api-current.txt index 0b6a177fae..c5219e1920 100644 --- a/.ci/api-current.txt +++ b/.ci/api-current.txt @@ -1899,7 +1899,7 @@ public final class net.corda.core.node.services.TimeWindowChecker extends java.l @org.jetbrains.annotations.NotNull public final java.time.Clock getClock() public final boolean isValid(net.corda.core.contracts.TimeWindow) ## -@net.corda.core.DoNotImplement public interface net.corda.core.node.services.TransactionStorage +@net.corda.core.DoNotImplement public interface net.corda.core.node.services.TransactionStorage extends net.corda.core.node.StateLoader @org.jetbrains.annotations.Nullable public abstract net.corda.core.transactions.SignedTransaction getTransaction(net.corda.core.crypto.SecureHash) @org.jetbrains.annotations.NotNull public abstract rx.Observable getUpdates() @org.jetbrains.annotations.NotNull public abstract net.corda.core.messaging.DataFeed track() diff --git a/build.gradle b/build.gradle index 49b84f3566..8bad2e7344 100644 --- a/build.gradle +++ b/build.gradle @@ -47,7 +47,7 @@ buildscript { ext.dependency_checker_version = '3.0.1' ext.commons_collections_version = '4.1' ext.beanutils_version = '1.9.3' - ext.crash_version = 'faba68332800f21278c5b600bf14ad55cef5989e' + ext.crash_version = 'cce5a00f114343c1145c1d7756e1dd6df3ea984e' ext.jsr305_version = constants.getProperty("jsr305Version") ext.spring_jdbc_version ='5.0.0.RELEASE' diff --git a/client/jfx/src/integration-test/kotlin/net/corda/client/jfx/NodeMonitorModelTest.kt b/client/jfx/src/integration-test/kotlin/net/corda/client/jfx/NodeMonitorModelTest.kt index ff8a529994..c2cf8bb87b 100644 --- a/client/jfx/src/integration-test/kotlin/net/corda/client/jfx/NodeMonitorModelTest.kt +++ b/client/jfx/src/integration-test/kotlin/net/corda/client/jfx/NodeMonitorModelTest.kt @@ -28,7 +28,7 @@ import net.corda.finance.flows.CashIssueFlow import net.corda.finance.flows.CashPaymentFlow import net.corda.node.services.Permissions.Companion.invokeRpc import net.corda.node.services.Permissions.Companion.startFlow -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.* import net.corda.testing.driver.driver import org.junit.ClassRule diff --git a/client/rpc/src/integration-test/java/net/corda/client/rpc/CordaRPCJavaClientTest.java b/client/rpc/src/integration-test/java/net/corda/client/rpc/CordaRPCJavaClientTest.java index 60fbe117c9..04f8847e24 100644 --- a/client/rpc/src/integration-test/java/net/corda/client/rpc/CordaRPCJavaClientTest.java +++ b/client/rpc/src/integration-test/java/net/corda/client/rpc/CordaRPCJavaClientTest.java @@ -10,7 +10,7 @@ import net.corda.finance.flows.CashPaymentFlow; import net.corda.finance.schemas.CashSchemaV1; import net.corda.node.internal.Node; import net.corda.node.internal.StartedNode; -import net.corda.nodeapi.User; +import net.corda.nodeapi.internal.config.User; import net.corda.testing.CoreTestUtils; import net.corda.testing.IntegrationTestKt; import net.corda.testing.IntegrationTestSchemas; diff --git a/client/rpc/src/integration-test/kotlin/net/corda/client/rpc/CordaRPCClientTest.kt b/client/rpc/src/integration-test/kotlin/net/corda/client/rpc/CordaRPCClientTest.kt index 04ac286ead..35b827c4b8 100644 --- a/client/rpc/src/integration-test/kotlin/net/corda/client/rpc/CordaRPCClientTest.kt +++ b/client/rpc/src/integration-test/kotlin/net/corda/client/rpc/CordaRPCClientTest.kt @@ -20,7 +20,7 @@ import net.corda.node.internal.Node import net.corda.node.internal.StartedNode import net.corda.node.services.Permissions.Companion.invokeRpc import net.corda.node.services.Permissions.Companion.startFlow -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.* import net.corda.testing.internal.NodeBasedTest import org.apache.activemq.artemis.api.core.ActiveMQSecurityException diff --git a/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/RPCClient.kt b/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/RPCClient.kt index f7318b34b3..756f07216e 100644 --- a/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/RPCClient.kt +++ b/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/RPCClient.kt @@ -15,7 +15,7 @@ import net.corda.core.utilities.* import net.corda.nodeapi.ArtemisTcpTransport.Companion.tcpTransport import net.corda.nodeapi.ConnectionDirection import net.corda.nodeapi.RPCApi -import net.corda.nodeapi.config.SSLConfiguration +import net.corda.nodeapi.internal.config.SSLConfiguration import org.apache.activemq.artemis.api.core.SimpleString import org.apache.activemq.artemis.api.core.TransportConfiguration import org.apache.activemq.artemis.api.core.client.ActiveMQClient diff --git a/client/rpc/src/smoke-test/java/net/corda/java/rpc/StandaloneCordaRPCJavaClientTest.java b/client/rpc/src/smoke-test/java/net/corda/java/rpc/StandaloneCordaRPCJavaClientTest.java index 692cfe381c..d03f020d5b 100644 --- a/client/rpc/src/smoke-test/java/net/corda/java/rpc/StandaloneCordaRPCJavaClientTest.java +++ b/client/rpc/src/smoke-test/java/net/corda/java/rpc/StandaloneCordaRPCJavaClientTest.java @@ -9,7 +9,7 @@ import net.corda.core.messaging.FlowHandle; import net.corda.core.utilities.OpaqueBytes; import net.corda.finance.flows.AbstractCashFlow; import net.corda.finance.flows.CashIssueFlow; -import net.corda.nodeapi.User; +import net.corda.nodeapi.internal.config.User; import net.corda.smoketesting.NodeConfig; import net.corda.smoketesting.NodeProcess; import org.junit.After; diff --git a/client/rpc/src/smoke-test/kotlin/net/corda/kotlin/rpc/StandaloneCordaRPClientTest.kt b/client/rpc/src/smoke-test/kotlin/net/corda/kotlin/rpc/StandaloneCordaRPClientTest.kt index 23018f7bfb..09e739819a 100644 --- a/client/rpc/src/smoke-test/kotlin/net/corda/kotlin/rpc/StandaloneCordaRPClientTest.kt +++ b/client/rpc/src/smoke-test/kotlin/net/corda/kotlin/rpc/StandaloneCordaRPClientTest.kt @@ -21,7 +21,7 @@ import net.corda.finance.contracts.getCashBalance import net.corda.finance.contracts.getCashBalances import net.corda.finance.flows.CashIssueFlow import net.corda.finance.flows.CashPaymentFlow -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.smoketesting.NodeConfig import net.corda.smoketesting.NodeProcess import org.apache.commons.io.output.NullOutputStream diff --git a/client/rpc/src/test/kotlin/net/corda/client/rpc/AbstractRPCTest.kt b/client/rpc/src/test/kotlin/net/corda/client/rpc/AbstractRPCTest.kt index 0c552f8128..546415e247 100644 --- a/client/rpc/src/test/kotlin/net/corda/client/rpc/AbstractRPCTest.kt +++ b/client/rpc/src/test/kotlin/net/corda/client/rpc/AbstractRPCTest.kt @@ -5,7 +5,7 @@ import net.corda.core.internal.concurrent.flatMap import net.corda.core.internal.concurrent.map import net.corda.core.messaging.RPCOps import net.corda.node.services.messaging.RPCServerConfiguration -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.SerializationEnvironmentRule import net.corda.testing.internal.RPCDriverExposedDSLInterface import net.corda.testing.internal.rpcTestUser diff --git a/client/rpc/src/test/kotlin/net/corda/client/rpc/RPCPermissionsTests.kt b/client/rpc/src/test/kotlin/net/corda/client/rpc/RPCPermissionsTests.kt index 82f5c53afc..6e7de32087 100644 --- a/client/rpc/src/test/kotlin/net/corda/client/rpc/RPCPermissionsTests.kt +++ b/client/rpc/src/test/kotlin/net/corda/client/rpc/RPCPermissionsTests.kt @@ -4,7 +4,7 @@ import net.corda.core.messaging.CordaRPCOps import net.corda.core.messaging.RPCOps import net.corda.node.services.Permissions.Companion.invokeRpc import net.corda.node.services.messaging.rpcContext -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.internal.RPCDriverExposedDSLInterface import net.corda.testing.internal.rpcDriver import org.junit.Test diff --git a/core/src/main/kotlin/net/corda/core/internal/InternalUtils.kt b/core/src/main/kotlin/net/corda/core/internal/InternalUtils.kt index 33306a984a..36022463ff 100644 --- a/core/src/main/kotlin/net/corda/core/internal/InternalUtils.kt +++ b/core/src/main/kotlin/net/corda/core/internal/InternalUtils.kt @@ -2,9 +2,9 @@ package net.corda.core.internal +import net.corda.core.cordapp.CordappProvider import net.corda.core.crypto.SecureHash import net.corda.core.crypto.sha256 -import net.corda.core.node.ServiceHub import net.corda.core.node.ServicesForResolution import net.corda.core.serialization.SerializationContext import net.corda.core.transactions.TransactionBuilder @@ -295,15 +295,15 @@ fun Iterable>.toMultiMap(): Map> = this.groupBy({ i * Provide access to internal method for AttachmentClassLoaderTests * @suppress */ -fun TransactionBuilder.toWireTransaction(services: ServicesForResolution, serializationContext: SerializationContext): WireTransaction { - return toWireTransactionWithContext(services, serializationContext) +fun TransactionBuilder.toWireTransaction(cordappProvider: CordappProvider, serializationContext: SerializationContext): WireTransaction { + return toWireTransactionWithContext(cordappProvider, serializationContext) } /** * Provide access to internal method for AttachmentClassLoaderTests * @suppress */ -fun TransactionBuilder.toLedgerTransaction(services: ServiceHub, serializationContext: SerializationContext) = toLedgerTransactionWithContext(services, serializationContext) +fun TransactionBuilder.toLedgerTransaction(services: ServicesForResolution, serializationContext: SerializationContext) = toLedgerTransactionWithContext(services, serializationContext) /** Convenience method to get the package name of a class literal. */ val KClass<*>.packageName: String get() = java.`package`.name diff --git a/core/src/main/kotlin/net/corda/core/node/ServiceHub.kt b/core/src/main/kotlin/net/corda/core/node/ServiceHub.kt index 78f1704336..19fd97cec5 100644 --- a/core/src/main/kotlin/net/corda/core/node/ServiceHub.kt +++ b/core/src/main/kotlin/net/corda/core/node/ServiceHub.kt @@ -38,7 +38,9 @@ interface StateLoader { // TODO: future implementation to use a Vault state ref -> contract state BLOB table and perform single query bulk load // as the existing transaction store will become encrypted at some point @Throws(TransactionResolutionException::class) - fun loadStates(stateRefs: Set): Set> + fun loadStates(stateRefs: Set): Set> { + return stateRefs.map { StateAndRef(loadState(it), it) }.toSet() + } } /** diff --git a/core/src/main/kotlin/net/corda/core/node/services/TransactionStorage.kt b/core/src/main/kotlin/net/corda/core/node/services/TransactionStorage.kt index b04c96729f..21d0d1f650 100644 --- a/core/src/main/kotlin/net/corda/core/node/services/TransactionStorage.kt +++ b/core/src/main/kotlin/net/corda/core/node/services/TransactionStorage.kt @@ -1,9 +1,13 @@ package net.corda.core.node.services import net.corda.core.DoNotImplement +import net.corda.core.contracts.StateRef +import net.corda.core.contracts.TransactionResolutionException +import net.corda.core.contracts.TransactionState import net.corda.core.concurrent.CordaFuture import net.corda.core.crypto.SecureHash import net.corda.core.messaging.DataFeed +import net.corda.core.node.StateLoader import net.corda.core.transactions.SignedTransaction import rx.Observable @@ -11,12 +15,18 @@ import rx.Observable * Thread-safe storage of transactions. */ @DoNotImplement -interface TransactionStorage { +interface TransactionStorage : StateLoader { /** * Return the transaction with the given [id], or null if no such transaction exists. */ fun getTransaction(id: SecureHash): SignedTransaction? + @Throws(TransactionResolutionException::class) + override fun loadState(stateRef: StateRef): TransactionState<*> { + val stx = getTransaction(stateRef.txhash) ?: throw TransactionResolutionException(stateRef.txhash) + return stx.resolveBaseTransaction(this).outputs[stateRef.index] + } + /** * Get a synchronous Observable of updates. When observations are pushed to the Observer, the vault will already * incorporate the update. diff --git a/core/src/main/kotlin/net/corda/core/transactions/TransactionBuilder.kt b/core/src/main/kotlin/net/corda/core/transactions/TransactionBuilder.kt index b0149dce8d..231f563314 100644 --- a/core/src/main/kotlin/net/corda/core/transactions/TransactionBuilder.kt +++ b/core/src/main/kotlin/net/corda/core/transactions/TransactionBuilder.kt @@ -2,6 +2,7 @@ package net.corda.core.transactions import co.paralleluniverse.strands.Strand import net.corda.core.contracts.* +import net.corda.core.cordapp.CordappProvider import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SignableData import net.corda.core.crypto.SignatureMetadata @@ -82,16 +83,16 @@ open class TransactionBuilder( * @returns A new [WireTransaction] that will be unaffected by further changes to this [TransactionBuilder]. */ @Throws(MissingContractAttachments::class) - fun toWireTransaction(services: ServicesForResolution): WireTransaction = toWireTransactionWithContext(services) + fun toWireTransaction(services: ServicesForResolution): WireTransaction = toWireTransactionWithContext(services.cordappProvider) - internal fun toWireTransactionWithContext(services: ServicesForResolution, serializationContext: SerializationContext? = null): WireTransaction { + internal fun toWireTransactionWithContext(cordappProvider: CordappProvider, serializationContext: SerializationContext? = null): WireTransaction { // Resolves the AutomaticHashConstraints to HashAttachmentConstraints for convenience. The AutomaticHashConstraint // allows for less boiler plate when constructing transactions since for the typical case the named contract // will be available when building the transaction. In exceptional cases the TransactionStates must be created // with an explicit [AttachmentConstraint] val resolvedOutputs = outputs.map { state -> if (state.constraint is AutomaticHashConstraint) { - services.cordappProvider.getContractAttachmentID(state.contract)?.let { + cordappProvider.getContractAttachmentID(state.contract)?.let { state.copy(constraint = HashAttachmentConstraint(it)) } ?: throw MissingContractAttachments(listOf(state)) } else { @@ -106,8 +107,7 @@ open class TransactionBuilder( @Throws(AttachmentResolutionException::class, TransactionResolutionException::class) fun toLedgerTransaction(services: ServiceHub) = toWireTransaction(services).toLedgerTransaction(services) - internal fun toLedgerTransactionWithContext(services: ServiceHub, serializationContext: SerializationContext) = toWireTransactionWithContext(services, serializationContext).toLedgerTransaction(services) - + internal fun toLedgerTransactionWithContext(services: ServicesForResolution, serializationContext: SerializationContext) = toWireTransactionWithContext(services.cordappProvider, serializationContext).toLedgerTransaction(services) @Throws(AttachmentResolutionException::class, TransactionResolutionException::class, TransactionVerificationException::class) fun verify(services: ServiceHub) { toLedgerTransaction(services).verify() diff --git a/core/src/smoke-test/kotlin/net/corda/core/NodeVersioningTest.kt b/core/src/smoke-test/kotlin/net/corda/core/NodeVersioningTest.kt index f9844fbce0..f682bfcb75 100644 --- a/core/src/smoke-test/kotlin/net/corda/core/NodeVersioningTest.kt +++ b/core/src/smoke-test/kotlin/net/corda/core/NodeVersioningTest.kt @@ -7,7 +7,7 @@ import net.corda.core.identity.CordaX500Name import net.corda.core.internal.* import net.corda.core.messaging.startFlow import net.corda.core.utilities.getOrThrow -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.smoketesting.NodeConfig import net.corda.smoketesting.NodeProcess import net.corda.testing.common.internal.ProjectStructure diff --git a/core/src/smoke-test/kotlin/net/corda/core/cordapp/CordappSmokeTest.kt b/core/src/smoke-test/kotlin/net/corda/core/cordapp/CordappSmokeTest.kt index 44db07a4ed..e64e3d90df 100644 --- a/core/src/smoke-test/kotlin/net/corda/core/cordapp/CordappSmokeTest.kt +++ b/core/src/smoke-test/kotlin/net/corda/core/cordapp/CordappSmokeTest.kt @@ -11,7 +11,7 @@ import net.corda.core.internal.list import net.corda.core.messaging.startFlow import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.unwrap -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.smoketesting.NodeConfig import net.corda.smoketesting.NodeProcess import net.corda.smoketesting.NodeProcess.Companion.CORDAPPS_DIR_NAME diff --git a/core/src/test/kotlin/net/corda/core/flows/ContractUpgradeFlowTest.kt b/core/src/test/kotlin/net/corda/core/flows/ContractUpgradeFlowTest.kt index 3287e4f260..a072d9ec34 100644 --- a/core/src/test/kotlin/net/corda/core/flows/ContractUpgradeFlowTest.kt +++ b/core/src/test/kotlin/net/corda/core/flows/ContractUpgradeFlowTest.kt @@ -19,7 +19,7 @@ import net.corda.finance.flows.CashIssueFlow import net.corda.node.internal.SecureCordaRPCOps import net.corda.node.internal.StartedNode import net.corda.node.services.Permissions.Companion.startFlow -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.* import net.corda.testing.contracts.DummyContract import net.corda.testing.contracts.DummyContractV2 diff --git a/core/src/test/kotlin/net/corda/core/flows/ReceiveAllFlowTests.kt b/core/src/test/kotlin/net/corda/core/flows/ReceiveAllFlowTests.kt index dd2dbab17f..2fc6be8955 100644 --- a/core/src/test/kotlin/net/corda/core/flows/ReceiveAllFlowTests.kt +++ b/core/src/test/kotlin/net/corda/core/flows/ReceiveAllFlowTests.kt @@ -20,6 +20,42 @@ class ReceiveMultipleFlowTests { mockNet.stopNodes() } + @Test + fun showcase_flows_as_closures() { + + val answer = 10.0 + val message = "Hello Ivan" + + val counterParty = nodes[1].info.singleIdentity() + + val initiatingFlow = @InitiatingFlow object : FlowLogic() { + + @Suspendable + override fun call(): Any { + val session = initiateFlow(counterParty) + return session.sendAndReceive(message).unwrap { it } + } + } + + nodes[1].registerInitiatedFlow(initiatingFlow::class) { session -> + object : FlowLogic() { + @Suspendable + override fun call() { + // this is a closure, meaning you can access variables outside its scope e.g., `answer`. + val receivedMessage = session.receive().unwrap { it } + logger.info("Got message from counterParty: $receivedMessage.") + assertThat(receivedMessage).isEqualTo(message) + session.send(answer) + } + } as FlowLogic + } + + val flow = nodes[0].services.startFlow(initiatingFlow) + mockNet.runNetwork() + val receivedAnswer = flow.resultFuture.getOrThrow() + assertThat(receivedAnswer).isEqualTo(answer) + } + @Test fun `receive all messages in parallel using map style`() { val doubleValue = 5.0 diff --git a/docs/source/_static/css/custom.css b/docs/source/_static/css/custom.css index c7f2ab9999..ebf9a0e17d 100644 --- a/docs/source/_static/css/custom.css +++ b/docs/source/_static/css/custom.css @@ -71,7 +71,8 @@ a:visited { } .wy-nav-content { - background-color: #fff max-width: 1000px; + background-color: #fff; + max-width: none; } .wy-nav-side { diff --git a/docs/source/api-vault-query.rst b/docs/source/api-vault-query.rst index a525a8b413..b0f295268e 100644 --- a/docs/source/api-vault-query.rst +++ b/docs/source/api-vault-query.rst @@ -176,6 +176,17 @@ define a ``PageSpecification`` to correctly process results with efficient memor place to alert API users to the need for pagination where a single query returns more than 200 results and no ``PageSpecification`` has been supplied. +Here's a query that extracts every unconsumed ``ContractState`` from the vault in pages of size 200, starting from the +default page number (page one): + +.. container:: codeset + + .. sourcecode:: kotlin + + val vaultSnapshot = proxy.vaultQueryBy( + QueryCriteria.VaultQueryCriteria(Vault.StateStatus.UNCONSUMED), + PageSpecification(DEFAULT_PAGE_NUM, 200)) + .. note:: A pages maximum size ``MAX_PAGE_SIZE`` is defined as ``Int.MAX_VALUE`` and should be used with extreme caution as results returned may exceed your JVM's memory footprint. diff --git a/docs/source/deploying-a-node.rst b/docs/source/deploying-a-node.rst index 2b091fddf8..f2e1b11a3e 100644 --- a/docs/source/deploying-a-node.rst +++ b/docs/source/deploying-a-node.rst @@ -7,9 +7,9 @@ Deploying a node whether they have developed and tested a CorDapp following the instructions in :doc:`generating-a-node` or are deploying a third-party CorDapp. -Linux (systemd): Installing and running Corda as a systemd service ------------------------------------------------------------------- -We recommend creating systemd services to run a node and the optional webserver. This provides logging and service +Linux: Installing and running Corda as a system service +------------------------------------------------------- +We recommend creating system services to run a node and the optional webserver. This provides logging and service handling, and ensures the Corda service is run at boot. **Prerequisites**: @@ -27,10 +27,13 @@ handling, and ensures the Corda service is run at boot. 3. Download the `Corda jar `_ (under ``/VERSION_NUMBER/corda-VERSION_NUMBER.jar``) and place it in ``/opt/corda`` -3. Create a directory called ``plugins`` in ``/opt/corda`` and save your CorDapp jar file to it. Alternatively, download one of +4. (Optional) Download the `Corda webserver jar `_ + (under ``/VERSION_NUMBER/corda-VERSION_NUMBER.jar``) and place it in ``/opt/corda`` + +5. Create a directory called ``plugins`` in ``/opt/corda`` and save your CorDapp jar file to it. Alternatively, download one of our `sample CorDapps `_ to the ``plugins`` directory -4. Save the below as ``/opt/corda/node.conf``. See :doc:`corda-configuration-file` for a description of these options +6. Save the below as ``/opt/corda/node.conf``. See :doc:`corda-configuration-file` for a description of these options .. code-block:: json @@ -59,7 +62,7 @@ handling, and ensures the Corda service is run at boot. } ] -5. Make the following changes to ``/opt/corda/node.conf``: +7. Make the following changes to ``/opt/corda/node.conf``: * Change the ``p2pAddress`` and ``rpcAddress`` values to start with your server's hostname or external IP address. This is the address other nodes or RPC interfaces will use to communicate with your node @@ -74,7 +77,12 @@ handling, and ensures the Corda service is run at boot. * Country (``C=``) is the `ISO 3166-1 alpha-2 code `_ * Change the RPC username and password -6. Create a ``corda.service`` file based on the example below and save it in the ``/etc/systemd/system/`` directory +.. note:: Ubuntu 16.04 and most current Linux distributions use SystemD, so if you are running one of these + distributions follow the steps marked **SystemD**. + If you are running Ubuntu 14.04, follow the instructions for **Upstart**. + +8. **SystemD**: Create a ``corda.service`` file based on the example below and save it in the ``/etc/systemd/system/`` + directory .. code-block:: shell @@ -92,20 +100,41 @@ handling, and ensures the Corda service is run at boot. [Install] WantedBy=multi-user.target -7. Make the following changes to ``corda.service``: +8. **Upstart**: Create a ``corda.conf`` file based on the example below and save it in the ``/etc/init/`` directory + + .. code-block:: shell + + description "Corda Node - Bank of Breakfast Tea" + + start on runlevel [2345] + stop on runlevel [!2345] + + respawn + setuid corda + chdir /opt/corda + exec java -Xmx2048m -jar /opt/corda/corda.jar + +9. Make the following changes to ``corda.service`` or ``corda.conf``: * Make sure the service description is informative - particularly if you plan to run multiple nodes. - * Change the username to the user account you want to use to run Corda. **We recommend that this is not root** + * Change the username to the user account you want to use to run Corda. **We recommend that this user account is + not root** * Set the maximum amount of memory available to the Corda process by changing the ``-Xmx2048m`` parameter - * Make sure the ``corda.service`` file is owned by root with the correct permissions: + * **SystemD**: Make sure the ``corda.service`` file is owned by root with the correct permissions: + * ``sudo chown root:root /etc/systemd/system/corda.service`` * ``sudo chmod 644 /etc/systemd/system/corda.service`` + * **Upstart**: Make sure the ``corda.conf`` file is owned by root with the correct permissions: + + * ``sudo chown root:root /etc/init/corda.conf`` + * ``sudo chmod 644 /etc/init/corda.conf`` + .. note:: The Corda webserver provides a simple interface for interacting with your installed CorDapps in a browser. Running the webserver is optional. -8. Create a ``corda-webserver.service`` file based on the example below and save it in the ``/etc/systemd/system/`` - directory. +10. **SystemD**: Create a ``corda-webserver.service`` file based on the example below and save it in the ``/etc/systemd/system/`` + directory .. code-block:: shell @@ -115,7 +144,7 @@ handling, and ensures the Corda service is run at boot. [Service] Type=simple - User=username + User=corda WorkingDirectory=/opt/corda ExecStart=/usr/bin/java -jar /opt/corda/corda-webserver.jar Restart=on-failure @@ -123,17 +152,40 @@ handling, and ensures the Corda service is run at boot. [Install] WantedBy=multi-user.target -9. Provision the required certificates to your node. Contact the network permissioning service or see - :doc:`permissioning` +10. **Upstart**: Create a ``corda-webserver.conf`` file based on the example below and save it in the ``/etc/init/`` + directory -10. You can now start a node and its webserver by running the following ``systemctl`` commands: + .. code-block:: shell + + description "Webserver for Corda Node - Bank of Breakfast Tea" + + start on runlevel [2345] + stop on runlevel [!2345] + + respawn + setuid corda + chdir /opt/corda + exec java -jar /opt/corda/corda-webserver.jar + +11. Provision the required certificates to your node. Contact the network permissioning service or see + :doc:`permissioning` + +12. **SystemD**: You can now start a node and its webserver and set the services to start on boot by running the + following ``systemctl`` commands: * ``sudo systemctl daemon-reload`` - * ``sudo systemctl corda start`` - * ``sudo systemctl corda-webserver start`` + * ``sudo systemctl enable --now corda`` + * ``sudo systemctl enable --now corda-webserver`` + +12. **Upstart**: You can now start a node and its webserver by running the following commands: + + * ``sudo start corda`` + * ``sudo start corda-webserver`` + +The Upstart configuration files created above tell Upstart to start the Corda services on boot so there is no need to explicitly enable them. You can run multiple nodes by creating multiple directories and Corda services, modifying the ``node.conf`` and -``service`` files so they are unique. +SystemD or Upstart configuration files so they are unique. Windows: Installing and running Corda as a Windows service ---------------------------------------------------------- @@ -212,10 +264,11 @@ at boot, and means the Corda service stays running with no users connected to th nssm install cordanode1 C:\ProgramData\Oracle\Java\javapath\java.exe nssm set cordanode1 AppDirectory C:\Corda - nssm set cordanode1 AppParameters "-jar corda.jar -Xmx2048m --config-file=C:\corda\node.conf" + nssm set cordanode1 AppParameters "-Xmx2048m -jar corda.jar --config-file=C:\corda\node.conf" nssm set cordanode1 AppStdout C:\Corda\service.log nssm set cordanode1 AppStderr C:\Corda\service.log nssm set cordanode1 Description Corda Node - Bank of Breakfast Tea + nssm set cordanode1 Start SERVICE_AUTO_START sc start cordanode1 9. Modify the batch file: diff --git a/docs/source/example-code/src/integration-test/kotlin/net/corda/docs/IntegrationTestingTutorial.kt b/docs/source/example-code/src/integration-test/kotlin/net/corda/docs/IntegrationTestingTutorial.kt index 1cc97f86af..d7299a596c 100644 --- a/docs/source/example-code/src/integration-test/kotlin/net/corda/docs/IntegrationTestingTutorial.kt +++ b/docs/source/example-code/src/integration-test/kotlin/net/corda/docs/IntegrationTestingTutorial.kt @@ -13,7 +13,7 @@ import net.corda.finance.flows.CashIssueFlow import net.corda.finance.flows.CashPaymentFlow import net.corda.node.services.Permissions.Companion.invokeRpc import net.corda.node.services.Permissions.Companion.startFlow -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.* import net.corda.testing.driver.driver import org.junit.Test diff --git a/docs/source/example-code/src/main/kotlin/net/corda/docs/ClientRpcTutorial.kt b/docs/source/example-code/src/main/kotlin/net/corda/docs/ClientRpcTutorial.kt index f68bc82edd..954a67c239 100644 --- a/docs/source/example-code/src/main/kotlin/net/corda/docs/ClientRpcTutorial.kt +++ b/docs/source/example-code/src/main/kotlin/net/corda/docs/ClientRpcTutorial.kt @@ -17,7 +17,7 @@ import net.corda.finance.flows.CashIssueFlow import net.corda.finance.flows.CashPaymentFlow import net.corda.node.services.Permissions.Companion.invokeRpc import net.corda.node.services.Permissions.Companion.startFlow -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.ALICE import net.corda.testing.driver.driver import org.graphstream.graph.Edge diff --git a/docs/source/release-notes.rst b/docs/source/release-notes.rst index 14d9a494cc..36aeb6c6c5 100644 --- a/docs/source/release-notes.rst +++ b/docs/source/release-notes.rst @@ -6,6 +6,12 @@ Here are release notes for each snapshot release from M9 onwards. Unreleased ---------- +* **Enum Class Evolution** + With the addition of AMQP serialization Corda now supports enum constant evolution. + + That is the ability to alter an enum constant and, as long as certain rules are followed and the correct + annotations applied, have older and newer instances of that enumeration be understood. + Release 2.0 ---------- Following quickly on the heels of the release of Corda 1.0, Corda version 2.0 consolidates diff --git a/docs/source/running-a-node.rst b/docs/source/running-a-node.rst index b5c2ddf845..34fde7652b 100644 --- a/docs/source/running-a-node.rst +++ b/docs/source/running-a-node.rst @@ -22,6 +22,12 @@ Start the nodes with ``runnodes`` by running the following command from the root .. warn:: On macOS, do not click/change focus until all the node terminal windows have opened, or some processes may fail to start. +If you receive an ``OutOfMemoryError`` exception when interacting with the nodes, you need to increase the amount of +Java heap memory available to them, which you can do when running them individually. See +:ref:`starting-an-individual-corda-node`. + +.. _starting-an-individual-corda-node: + Starting an individual Corda node --------------------------------- Run the node by opening a terminal window in the node's folder and running: @@ -30,9 +36,18 @@ Run the node by opening a terminal window in the node's folder and running: java -jar corda.jar -.. warning:: By default, the node will look for a configuration file called ``node.conf`` and a CorDapps folder called - ``cordapps`` in the current working directory. You can override the configuration file and workspace paths on the - command line (e.g. ``./corda.jar --config-file=test.conf --base-directory=/opt/r3corda/nodes/test``). +By default, the node will look for a configuration file called ``node.conf`` and a CorDapps folder called ``cordapps`` +in the current working directory. You can override the configuration file and workspace paths on the command line (e.g. +``./corda.jar --config-file=test.conf --base-directory=/opt/corda/nodes/test``). + +You can increase the amount of Java heap memory available to the node using the ``-Xmx`` command line argument. For +example, the following would run the node with a heap size of 2048MB: + +.. code-block:: shell + + java -Xmx2048m -jar corda.jar + +You should do this if you receive an ``OutOfMemoryError`` exception when interacting with the node. Optionally run the node's webserver as well by opening a terminal window in the node's folder and running: diff --git a/finance/src/test/kotlin/net/corda/finance/contracts/CommercialPaperTests.kt b/finance/src/test/kotlin/net/corda/finance/contracts/CommercialPaperTests.kt index 0684675724..25d65f3dab 100644 --- a/finance/src/test/kotlin/net/corda/finance/contracts/CommercialPaperTests.kt +++ b/finance/src/test/kotlin/net/corda/finance/contracts/CommercialPaperTests.kt @@ -16,6 +16,7 @@ import net.corda.testing.* import net.corda.testing.contracts.VaultFiller import net.corda.testing.node.MockServices import net.corda.testing.node.MockServices.Companion.makeTestDatabaseAndMockServices +import net.corda.testing.node.makeTestIdentityService import org.junit.Ignore import org.junit.Rule import org.junit.Test @@ -232,7 +233,10 @@ class CommercialPaperTestsGeneric { // @Test @Ignore fun `issue move and then redeem`() = withTestSerialization { - val aliceDatabaseAndServices = makeTestDatabaseAndMockServices(keys = listOf(ALICE_KEY)) + val aliceDatabaseAndServices = makeTestDatabaseAndMockServices( + listOf(ALICE_KEY), + makeTestIdentityService(listOf(MEGA_CORP_IDENTITY, MINI_CORP_IDENTITY, DUMMY_CASH_ISSUER_IDENTITY, DUMMY_NOTARY_IDENTITY)), + initialIdentityName = MEGA_CORP.name) val databaseAlice = aliceDatabaseAndServices.first aliceServices = aliceDatabaseAndServices.second aliceVaultService = aliceServices.vaultService @@ -241,8 +245,10 @@ class CommercialPaperTestsGeneric { alicesVault = VaultFiller(aliceServices, DUMMY_NOTARY, DUMMY_NOTARY_KEY, rngFactory = ::Random).fillWithSomeTestCash(9000.DOLLARS, issuerServices, 1, DUMMY_CASH_ISSUER) aliceVaultService = aliceServices.vaultService } - - val bigCorpDatabaseAndServices = makeTestDatabaseAndMockServices(keys = listOf(BIG_CORP_KEY)) + val bigCorpDatabaseAndServices = makeTestDatabaseAndMockServices( + listOf(BIG_CORP_KEY), + makeTestIdentityService(listOf(MEGA_CORP_IDENTITY, MINI_CORP_IDENTITY, DUMMY_CASH_ISSUER_IDENTITY, DUMMY_NOTARY_IDENTITY)), + initialIdentityName = MEGA_CORP.name) val databaseBigCorp = bigCorpDatabaseAndServices.first bigCorpServices = bigCorpDatabaseAndServices.second bigCorpVaultService = bigCorpServices.vaultService diff --git a/finance/src/test/kotlin/net/corda/finance/contracts/asset/CashTests.kt b/finance/src/test/kotlin/net/corda/finance/contracts/asset/CashTests.kt index faa9665f63..bfec19b57d 100644 --- a/finance/src/test/kotlin/net/corda/finance/contracts/asset/CashTests.kt +++ b/finance/src/test/kotlin/net/corda/finance/contracts/asset/CashTests.kt @@ -25,6 +25,7 @@ import net.corda.testing.contracts.DummyState import net.corda.testing.contracts.VaultFiller import net.corda.testing.node.MockServices import net.corda.testing.node.MockServices.Companion.makeTestDatabaseAndMockServices +import net.corda.testing.node.makeTestIdentityService import org.junit.After import org.junit.Before import org.junit.Rule @@ -70,9 +71,10 @@ class CashTests { miniCorpServices = MockServices(listOf("net.corda.finance.contracts.asset"), MINI_CORP.name, MINI_CORP_KEY) val notaryServices = MockServices(listOf("net.corda.finance.contracts.asset"), DUMMY_NOTARY.name, DUMMY_NOTARY_KEY) val databaseAndServices = makeTestDatabaseAndMockServices( - cordappPackages = listOf("net.corda.finance.contracts.asset"), - initialIdentityName = CordaX500Name(organisation = "Me", locality = "London", country = "GB"), - keys = listOf(generateKeyPair())) + listOf(generateKeyPair()), + makeTestIdentityService(listOf(MEGA_CORP_IDENTITY, MINI_CORP_IDENTITY, DUMMY_CASH_ISSUER_IDENTITY, DUMMY_NOTARY_IDENTITY)), + listOf("net.corda.finance.contracts.asset"), + CordaX500Name("Me", "London", "GB")) database = databaseAndServices.first ourServices = databaseAndServices.second diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/ArtemisTcpTransport.kt b/node-api/src/main/kotlin/net/corda/nodeapi/ArtemisTcpTransport.kt index 947560c257..ab1720934a 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/ArtemisTcpTransport.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/ArtemisTcpTransport.kt @@ -3,7 +3,8 @@ package net.corda.nodeapi import net.corda.core.identity.CordaX500Name import net.corda.core.serialization.internal.nodeSerializationEnv import net.corda.core.utilities.NetworkHostAndPort -import net.corda.nodeapi.config.SSLConfiguration +import net.corda.nodeapi.internal.config.SSLConfiguration +import net.corda.nodeapi.internal.requireOnDefaultFileSystem import org.apache.activemq.artemis.api.core.TransportConfiguration import org.apache.activemq.artemis.core.remoting.impl.netty.NettyConnectorFactory import org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/ArtemisUtils.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/ArtemisUtils.kt similarity index 92% rename from node-api/src/main/kotlin/net/corda/nodeapi/ArtemisUtils.kt rename to node-api/src/main/kotlin/net/corda/nodeapi/internal/ArtemisUtils.kt index 644fdb363a..3f1e887fa8 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/ArtemisUtils.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/ArtemisUtils.kt @@ -1,6 +1,6 @@ @file:JvmName("ArtemisUtils") -package net.corda.nodeapi +package net.corda.nodeapi.internal import java.nio.file.FileSystems import java.nio.file.Path diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/config/ConfigUtilities.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/config/ConfigUtilities.kt similarity index 99% rename from node-api/src/main/kotlin/net/corda/nodeapi/config/ConfigUtilities.kt rename to node-api/src/main/kotlin/net/corda/nodeapi/internal/config/ConfigUtilities.kt index 19987de81c..33a5e237ff 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/config/ConfigUtilities.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/config/ConfigUtilities.kt @@ -1,6 +1,6 @@ @file:JvmName("ConfigUtilities") -package net.corda.nodeapi.config +package net.corda.nodeapi.internal.config import com.typesafe.config.Config import com.typesafe.config.ConfigFactory @@ -200,4 +200,4 @@ private fun Iterable<*>.toConfigIterable(field: Field): Iterable { } } -private val logger = LoggerFactory.getLogger("net.corda.nodeapi.config") +private val logger = LoggerFactory.getLogger("net.corda.nodeapi.internal.config") diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/config/SSLConfiguration.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/config/SSLConfiguration.kt similarity index 93% rename from node-api/src/main/kotlin/net/corda/nodeapi/config/SSLConfiguration.kt rename to node-api/src/main/kotlin/net/corda/nodeapi/internal/config/SSLConfiguration.kt index 6fb82e508f..90544e92a6 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/config/SSLConfiguration.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/config/SSLConfiguration.kt @@ -1,4 +1,4 @@ -package net.corda.nodeapi.config +package net.corda.nodeapi.internal.config import net.corda.core.internal.div import java.nio.file.Path diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/User.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/config/User.kt similarity index 77% rename from node-api/src/main/kotlin/net/corda/nodeapi/User.kt rename to node-api/src/main/kotlin/net/corda/nodeapi/internal/config/User.kt index aa86e64414..13ca193f4b 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/User.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/config/User.kt @@ -1,7 +1,4 @@ -package net.corda.nodeapi - -import net.corda.nodeapi.config.OldConfig -import net.corda.nodeapi.config.toConfig +package net.corda.nodeapi.internal.config data class User( @OldConfig("user") diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/AMQPSerializer.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/AMQPSerializer.kt index d4596c5ec0..e70b55d8fc 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/AMQPSerializer.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/AMQPSerializer.kt @@ -35,5 +35,5 @@ interface AMQPSerializer { /** * Read the given object from the input. The envelope is provided in case the schema is required. */ - fun readObject(obj: Any, schema: SerializationSchemas, input: DeserializationInput): T + fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput): T } \ No newline at end of file diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/EnumEvolutionSerializer.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/EnumEvolutionSerializer.kt new file mode 100644 index 0000000000..ec8a61c793 --- /dev/null +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/EnumEvolutionSerializer.kt @@ -0,0 +1,136 @@ +package net.corda.nodeapi.internal.serialization.amqp + +import net.corda.core.internal.uncheckedCast +import org.apache.qpid.proton.amqp.Symbol +import org.apache.qpid.proton.codec.Data +import java.io.NotSerializableException +import java.lang.UnsupportedOperationException +import java.lang.reflect.Type +import java.util.* + +/** + * Used whenever a deserialized enums fingerprint doesn't match the fingerprint of the generated + * serializer object. I.e. the deserializing code has a different version of the code either newer or + * older). The changes will have been documented using the transformation annotations, a copy of which + * are encoded as part of the AMQP envelope. + * + * This function ascertains which version of the enumeration is newer by comparing the length of the + * transformations list. Since transformation annotations should only ever be added, never removed even + * when seemingly unneeded (such as repeated renaming of a single constant), the longer list will dictate + * which is more up to date. + * + * The list of transforms come from two places, the class as it exists on the current class path and the + * class as it exists as it was serialized. In the case of the former we can build the list by using + * reflection on the class. In the case of the latter the transforms are retrieved from the AMQP envelope. + * + * With a set of transforms chosen we calculate the set of all possible constants, then using the + * transformation rules we create a mapping between those values and the values that exist on the + * current class + * + * @property clazz The enum as it exists now, not as it did when it was serialized (either in the past + * or future). + * @property factory the [SerializerFactory] that is building this serialization object. + * @property conversions A mapping between all potential enum constants that could've been assigned to + * an instance of the enum as it existed at time of serialisation and those that exist now + * @property ordinals Convenience mapping of constant to ordinality + */ +class EnumEvolutionSerializer( + override val type: Type, + factory: SerializerFactory, + private val conversions: Map, + private val ordinals: Map) : AMQPSerializer { + override val typeDescriptor = Symbol.valueOf("$DESCRIPTOR_DOMAIN:${fingerprintForType(type, factory)}")!! + + companion object { + private fun MutableMap.mapInPlace(f: (String) -> String) { + val i = iterator() + while (i.hasNext()) { + val curr = i.next() + curr.setValue(f(curr.value)) + } + } + + /** + * Builds an Enum Evolver serializer. + * + * @param old The description of the enum as it existed at the time of serialisation taken from the + * received AMQP header + * @param new The Serializer object we built based on the current state of the enum class on our classpath + * @param factory the [SerializerFactory] that is building this serialization object. + * @param transformsFromBlob the transforms attached to the class in the AMQP header, i.e. the transforms + * known at serialization time + */ + fun make(old: RestrictedType, + new: AMQPSerializer, + factory: SerializerFactory, + schemas: SerializationSchemas): AMQPSerializer { + val wireTransforms = schemas.transforms.types[old.name] ?: EnumMap>(TransformTypes::class.java) + val localTransforms = TransformsSchema.get(old.name, factory) + + // remember, the longer the list the newer we're assuming the transform set it as we assume + // evolution annotations are never removed, only added to + val transforms = if (wireTransforms.size > localTransforms.size) wireTransforms else localTransforms + + // if either of these isn't of the cast type then something has gone terribly wrong + // elsewhere in the code + val defaultRules: List? = uncheckedCast(transforms[TransformTypes.EnumDefault]) + val renameRules: List? = uncheckedCast(transforms[TransformTypes.Rename]) + + // What values exist on the enum as it exists on the class path + val localValues = new.type.asClass()!!.enumConstants.map { it.toString() } + + val conversions: MutableMap = localValues + .union(defaultRules?.map { it.new }?.toSet() ?: emptySet()) + .union(renameRules?.map { it.to } ?: emptySet()) + .associateBy({ it }, { it }) + .toMutableMap() + + val rules: MutableMap = mutableMapOf() + rules.putAll(defaultRules?.associateBy({ it.new }, { it.old }) ?: emptyMap()) + val renameRulesMap = renameRules?.associateBy({ it.to }, { it.from }) ?: emptyMap() + rules.putAll(renameRulesMap) + + // take out set of all possible constants and build a map from those to the + // existing constants applying the rename and defaulting rules as defined + // in the schema + while (conversions.filterNot { it.value in localValues }.isNotEmpty()) { + conversions.mapInPlace { rules[it] ?: it } + } + + // you'd think this was overkill to get access to the ordinal values for each constant but it's actually + // rather tricky when you don't have access to the actual type, so this is a nice way to be able + // to precompute and pass to the actual object + val ordinals = localValues.mapIndexed { i, s -> Pair(s, i) }.toMap() + + // create a mapping between the ordinal value and the name as it was serialised converted + // to the name as it exists. We want to test any new constants have been added to the end + // of the enum class + val serialisedOrds = ((schemas.schema.types.find { it.name == old.name } as RestrictedType).choices + .associateBy ({ it.value.toInt() }, { conversions[it.name] })) + + if (ordinals.filterNot { serialisedOrds[it.value] == it.key }.isNotEmpty()) { + throw NotSerializableException("Constants have been reordered, additions must be appended to the end") + } + + return EnumEvolutionSerializer(new.type, factory, conversions, ordinals) + } + } + + override fun readObject(obj: Any, schemas: SerializationSchemas, input: DeserializationInput): Any { + val enumName = (obj as List<*>)[0] as String + + if (enumName !in conversions) { + throw NotSerializableException("No rule to evolve enum constant $type::$enumName") + } + + return type.asClass()!!.enumConstants[ordinals[conversions[enumName]]!!] + } + + override fun writeClassInfo(output: SerializationOutput) { + throw UnsupportedOperationException("It should be impossible to write an evolution serializer") + } + + override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput) { + throw UnsupportedOperationException("It should be impossible to write an evolution serializer") + } +} \ No newline at end of file diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/EvolutionSerializer.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/EvolutionSerializer.kt index 59f22598a0..411e405aad 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/EvolutionSerializer.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/EvolutionSerializer.kt @@ -109,7 +109,7 @@ class EvolutionSerializer( } override fun writeObject(obj: Any, data: Data, type: Type, output: SerializationOutput) { - throw IllegalAccessException("It should be impossible to write an evolution serializer") + throw UnsupportedOperationException("It should be impossible to write an evolution serializer") } /** diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/SerializerFactory.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/SerializerFactory.kt index d310f5a6bb..39abcc58f5 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/SerializerFactory.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/SerializerFactory.kt @@ -46,11 +46,11 @@ open class SerializerFactory(val whitelist: ClassWhitelist, cl: ClassLoader) { private fun getEvolutionSerializer( typeNotation: TypeNotation, newSerializer: AMQPSerializer, - transforms: TransformsSchema): AMQPSerializer { + schemas: SerializationSchemas): AMQPSerializer { return serializersByDescriptor.computeIfAbsent(typeNotation.descriptor.name!!) { when (typeNotation) { is CompositeType -> EvolutionSerializer.make(typeNotation, newSerializer as ObjectSerializer, this) - is RestrictedType -> throw NotSerializableException("Enum evolution is not currently supported") + is RestrictedType -> EnumEvolutionSerializer.make(typeNotation, newSerializer, this, schemas) } } } @@ -210,7 +210,7 @@ open class SerializerFactory(val whitelist: ClassWhitelist, cl: ClassLoader) { // doesn't match that of the serialised object then we are dealing with different // instance of the class, as such we need to build an EvolutionSerialiser if (serialiser.typeDescriptor != typeNotation.descriptor.name) { - getEvolutionSerializer(typeNotation, serialiser, schemaAndDescriptor.schemas.transforms) + getEvolutionSerializer(typeNotation, serialiser, schemaAndDescriptor.schemas) } } catch (e: ClassNotFoundException) { if (sentinel) throw e diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/TansformTypes.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/TansformTypes.kt index 5bb6fc05d5..0003a48ba2 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/TansformTypes.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/TansformTypes.kt @@ -1,5 +1,6 @@ package net.corda.nodeapi.internal.serialization.amqp +import net.corda.core.internal.uncheckedCast import net.corda.core.serialization.CordaSerializationTransformEnumDefault import net.corda.core.serialization.CordaSerializationTransformEnumDefaults import net.corda.core.serialization.CordaSerializationTransformRename @@ -27,14 +28,72 @@ enum class TransformTypes(val build: (Annotation) -> Transform) : DescribedType Unknown({ UnknownTransform() }) { override fun getDescriptor(): Any = DESCRIPTOR override fun getDescribed(): Any = ordinal + override fun validate(l : List, constants: Map) { } }, EnumDefault({ a -> EnumDefaultSchemaTransform((a as CordaSerializationTransformEnumDefault).old, a.new) }) { override fun getDescriptor(): Any = DESCRIPTOR override fun getDescribed(): Any = ordinal + + /** + * Validates a list of constant additions to an enumerated type. To be valid a default (the value + * that should be used when we cannot use the new value) must refer to a constant that exists in the + * enum class as it exists now and it cannot refer to itself. + * + * @param l The list of transforms representing new constants and the mapping from that constant to an + * existing value + * @param constants The list of enum constants on the type the transforms are being applied to + */ + override fun validate(list : List, constants: Map) { + uncheckedCast, List>(list).forEach { + if (!constants.contains(it.new)) { + throw NotSerializableException("Unknown enum constant ${it.new}") + } + + if (!constants.contains(it.old)) { + throw NotSerializableException( + "Enum extension defaults must be to a valid constant: ${it.new} -> ${it.old}. ${it.old} " + + "doesn't exist in constant set $constants") + } + + if (it.old == it.new) { + throw NotSerializableException("Enum extension ${it.new} cannot default to itself") + } + + if (constants[it.old]!! >= constants[it.new]!!) { + throw NotSerializableException( + "Enum extensions must default to older constants. ${it.new}[${constants[it.new]}] " + + "defaults to ${it.old}[${constants[it.old]}] which is greater") + } + } + } }, Rename({ a -> RenameSchemaTransform((a as CordaSerializationTransformRename).from, a.to) }) { override fun getDescriptor(): Any = DESCRIPTOR override fun getDescribed(): Any = ordinal + + /** + * Validates a list of rename transforms is valid. Such a list isn't valid if we detect a cyclic chain, + * that is a constant is renamed to something that used to exist in the enum. We do this for both + * the same constant (i.e. C -> D -> C) and multiple constants (C->D, B->C) + * + * @param l The list of transforms representing the renamed constants and the mapping between their new + * and old values + * @param constants The list of enum constants on the type the transforms are being applied to + */ + override fun validate(l : List, constants: Map) { + object : Any() { + val from : MutableSet = mutableSetOf() + val to : MutableSet = mutableSetOf() }.apply { + @Suppress("UNCHECKED_CAST") (l as List).forEach { rename -> + if (rename.to in this.to || rename.from in this.from) { + throw NotSerializableException("Cyclic renames are not allowed (${rename.to})") + } + + this.to.add(rename.from) + this.from.add(rename.to) + } + } + } } // Transform used to test the unknown handler, leave this at as the final constant, uncomment // when regenerating test cases - if Java had a pre-processor this would be much neater @@ -45,6 +104,8 @@ enum class TransformTypes(val build: (Annotation) -> Transform) : DescribedType //} ; + abstract fun validate(l: List, constants: Map) + companion object : DescribedTypeConstructor { val DESCRIPTOR = AMQPDescriptorRegistry.TRANSFORM_ELEMENT_KEY.amqpDescriptor diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/TransformsSchema.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/TransformsSchema.kt index 974de134b1..378675b84e 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/TransformsSchema.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/TransformsSchema.kt @@ -146,8 +146,8 @@ class EnumDefaultSchemaTransform(val old: String, val new: String) : Transform() /** * Transform applied to either a class or enum where a property is renamed * - * @property from the name at time of change of the property - * @property to the new name of the property + * @property from the name of the property or constant prior to being changed, i.e. what it was + * @property to the new name of the property or constant after the change has been made, i.e. what it is now */ class RenameSchemaTransform(val from: String, val to: String) : Transform() { companion object : DescribedTypeConstructor { @@ -192,6 +192,61 @@ data class TransformsSchema(val types: Map { val DESCRIPTOR = AMQPDescriptorRegistry.TRANSFORM_SCHEMA.amqpDescriptor + /** + * Takes a class name and either returns a cached instance of the TransformSet for it or, on a cache miss, + * instantiates the transform set before inserting into the cache and returning it. + * + * @param name fully qualified class name to lookup transforms for + * @param sf the [SerializerFactory] building this transform set. Needed as each can define it's own + * class loader and this dictates which classes we can and cannot see + */ + fun get(name: String, sf: SerializerFactory) = sf.transformsCache.computeIfAbsent(name) { + val transforms = EnumMap>(TransformTypes::class.java) + try { + val clazz = sf.classloader.loadClass(name) + + supportedTransforms.forEach { transform -> + clazz.getAnnotation(transform.type)?.let { list -> + transform.getAnnotations(list).forEach { annotation -> + val t = transform.enum.build(annotation) + + // we're explicitly rejecting repeated annotations, whilst it's fine and we'd just + // ignore them it feels like a good thing to alert the user to since this is + // more than likely a typo in their code so best make it an actual error + if (transforms.computeIfAbsent(transform.enum) { mutableListOf() } + .filter { t == it } + .isNotEmpty()) { + throw NotSerializableException( + "Repeated unique transformation annotation of type ${t.name}") + } + + transforms[transform.enum]!!.add(t) + } + + transform.enum.validate( + transforms[transform.enum] ?: emptyList(), + clazz.enumConstants.mapIndexed { i, s -> Pair(s.toString(), i) }.toMap()) + } + } + } catch (_: ClassNotFoundException) { + // if we can't load the class we'll end up caching an empty list which is fine as that + // list, on lookup, won't be included in the schema because it's empty + } + + transforms + } + + private fun getAndAdd( + type: String, + sf: SerializerFactory, + map: MutableMap>>) { + get(type, sf).apply { + if (isNotEmpty()) { + map[type] = this + } + } + } + /** * Prepare a schema for encoding, takes all of the types being transmitted and inspects each * one for any transform annotations. If there are any build up a set that can be @@ -200,48 +255,10 @@ data class TransformsSchema(val types: Map>>() - - schema.types.forEach { type -> - sf.transformsCache.computeIfAbsent(type.name) { - val transforms = EnumMap>(TransformTypes::class.java) - try { - val clazz = sf.classloader.loadClass(type.name) - - supportedTransforms.forEach { transform -> - clazz.getAnnotation(transform.type)?.let { list -> - transform.getAnnotations(list).forEach { annotation -> - val t = transform.enum.build(annotation) - - // we're explicitly rejecting repeated annotations, whilst it's fine and we'd just - // ignore them it feels like a good thing to alert the user to since this is - // more than likely a typo in their code so best make it an actual error - if (transforms.computeIfAbsent(transform.enum) { mutableListOf() } - .filter { t == it }.isNotEmpty()) { - throw NotSerializableException( - "Repeated unique transformation annotation of type ${t.name}") - } - - transforms[transform.enum]!!.add(t) - } - } - } - } catch (_: ClassNotFoundException) { - // if we can't load the class we'll end up caching an empty list which is fine as that - // list, on lookup, won't be included in the schema because it's empty - } - - transforms - }.apply { - if (isNotEmpty()) { - rtn[type.name] = this - } - } - } - - return TransformsSchema(rtn) - } + fun build(schema: Schema, sf: SerializerFactory) = TransformsSchema( + mutableMapOf>>().apply { + schema.types.forEach { type -> getAndAdd(type.name, sf, this) } + }) override fun getTypeClass(): Class<*> = TransformsSchema::class.java @@ -286,6 +303,7 @@ data class TransformsSchema(val types: Map().also { + doReturn(CordappProviderImpl(CordappLoader.createWithTestPackages(listOf("net.corda.nodeapi.internal")), MockAttachmentStorage())).whenever(it).cordappProvider } @Test diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/AttachmentsClassLoaderTests.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/AttachmentsClassLoaderTests.kt index a6ab0c6ecc..4f98293c53 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/AttachmentsClassLoaderTests.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/AttachmentsClassLoaderTests.kt @@ -19,10 +19,8 @@ import net.corda.nodeapi.internal.serialization.attachmentsClassLoaderEnabledPro import net.corda.nodeapi.internal.serialization.withTokenContext import net.corda.testing.* import net.corda.testing.node.MockAttachmentStorage -import net.corda.testing.node.MockServices import org.apache.commons.io.IOUtils import org.junit.Assert.* -import org.junit.Before import org.junit.Rule import org.junit.Test import java.io.ByteArrayInputStream @@ -52,14 +50,13 @@ class AttachmentsClassLoaderTests { @Rule @JvmField val testSerialization = SerializationEnvironmentRule() - private lateinit var serviceHub: DummyServiceHub - - class DummyServiceHub : MockServices() { - override val cordappProvider: CordappProviderImpl - = CordappProviderImpl(CordappLoader.createDevMode(listOf(ISOLATED_CONTRACTS_JAR_PATH)), attachments) - private val cordapp get() = cordappProvider.cordapps.first() - val attachmentId get() = cordappProvider.getCordappAttachmentId(cordapp)!! - val appContext get() = cordappProvider.getAppContext(cordapp) + private val attachments = MockAttachmentStorage() + private val cordappProvider = CordappProviderImpl(CordappLoader.createDevMode(listOf(ISOLATED_CONTRACTS_JAR_PATH)), attachments) + private val cordapp get() = cordappProvider.cordapps.first() + private val attachmentId get() = cordappProvider.getCordappAttachmentId(cordapp)!! + private val appContext get() = cordappProvider.getAppContext(cordapp) + private val serviceHub = rigorousMock().also { + doReturn(attachments).whenever(it).attachments } // These ClassLoaders work together to load 'AnotherDummyContract' in a disposable way, such that even though @@ -77,12 +74,6 @@ class AttachmentsClassLoaderTests { } class ClassLoaderForTests : URLClassLoader(arrayOf(ISOLATED_CONTRACTS_JAR_PATH), FilteringClassLoader) - - @Before - fun `create service hub`() { - serviceHub = DummyServiceHub() - } - @Test fun `dynamically load AnotherDummyContract from isolated contracts jar`() { ClassLoaderForTests().use { child -> @@ -112,8 +103,8 @@ class AttachmentsClassLoaderTests { @Test fun `test MockAttachmentStorage open as jar`() { - val storage = serviceHub.attachments - val key = serviceHub.attachmentId + val storage = attachments + val key = attachmentId val attachment = storage.openAttachment(key)!! val jar = attachment.openAsJAR() @@ -123,9 +114,8 @@ class AttachmentsClassLoaderTests { @Test fun `test overlapping file exception`() { - val storage = serviceHub.attachments - - val att0 = serviceHub.attachmentId + val storage = attachments + val att0 = attachmentId val att1 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file.txt", "some data"))) val att2 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file.txt", "some other data"))) @@ -136,9 +126,8 @@ class AttachmentsClassLoaderTests { @Test fun `basic`() { - val storage = serviceHub.attachments - - val att0 = serviceHub.attachmentId + val storage = attachments + val att0 = attachmentId val att1 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file1.txt", "some data"))) val att2 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file2.txt", "some other data"))) @@ -169,9 +158,8 @@ class AttachmentsClassLoaderTests { @Test fun `loading class AnotherDummyContract`() { - val storage = serviceHub.attachments - - val att0 = serviceHub.attachmentId + val storage = attachments + val att0 = attachmentId val att1 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file1.txt", "some data"))) val att2 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file2.txt", "some other data"))) @@ -194,10 +182,8 @@ class AttachmentsClassLoaderTests { val contract = createContract2Cash() val bytes = contract.serialize() - - val storage = serviceHub.attachments - - val att0 = serviceHub.attachmentId + val storage = attachments + val att0 = attachmentId val att1 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file1.txt", "some data"))) val att2 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file2.txt", "some other data"))) @@ -222,10 +208,8 @@ class AttachmentsClassLoaderTests { val context2 = SerializationFactory.defaultFactory.defaultContext.withWhitelisted(data.contract.javaClass) val bytes = data.serialize(context = context2) - - val storage = serviceHub.attachments - - val att0 = serviceHub.attachmentId + val storage = attachments + val att0 = attachmentId val att1 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file1.txt", "some data"))) val att2 = storage.importAttachment(ByteArrayInputStream(fakeAttachment("file2.txt", "some other data"))) @@ -276,7 +260,7 @@ class AttachmentsClassLoaderTests { @Test fun `test serialization of WireTransaction with dynamically loaded contract`() { - val child = serviceHub.appContext.classLoader + val child = appContext.classLoader val contractClass = Class.forName(ISOLATED_CONTRACT_CLASS_NAME, true, child) val contract = contractClass.newInstance() as DummyContractBackdoor val tx = contract.generateInitial(MEGA_CORP.ref(0), 42, DUMMY_NOTARY) @@ -288,7 +272,7 @@ class AttachmentsClassLoaderTests { .withClassLoader(child) val bytes = run { - val wireTransaction = tx.toWireTransaction(serviceHub, context) + val wireTransaction = tx.toWireTransaction(cordappProvider, context) wireTransaction.serialize(context = context) } val copiedWireTransaction = bytes.deserialize(context = context) @@ -307,13 +291,12 @@ class AttachmentsClassLoaderTests { val contractClass = Class.forName(ISOLATED_CONTRACT_CLASS_NAME, true, child) val contract = contractClass.newInstance() as DummyContractBackdoor val tx = contract.generateInitial(MEGA_CORP.ref(0), 42, DUMMY_NOTARY) - - val attachmentRef = serviceHub.attachmentId + val attachmentRef = attachmentId val bytes = run { val outboundContext = SerializationFactory.defaultFactory.defaultContext .withServiceHub(serviceHub) .withClassLoader(child) - val wireTransaction = tx.toWireTransaction(serviceHub, outboundContext) + val wireTransaction = tx.toWireTransaction(cordappProvider, outboundContext) wireTransaction.serialize(context = outboundContext) } // use empty attachmentStorage @@ -340,7 +323,7 @@ class AttachmentsClassLoaderTests { val contractClass = Class.forName(ISOLATED_CONTRACT_CLASS_NAME, true, child) val contract = contractClass.newInstance() as DummyContractBackdoor val outboundContext = SerializationFactory.defaultFactory.defaultContext.withClassLoader(child) - val attachmentRef = serviceHub.attachmentId + val attachmentRef = attachmentId // We currently ignore annotations in attachments, so manually whitelist. val inboundContext = SerializationFactory .defaultFactory diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/config/ConfigParsingTest.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/config/ConfigParsingTest.kt similarity index 99% rename from node-api/src/test/kotlin/net/corda/nodeapi/config/ConfigParsingTest.kt rename to node-api/src/test/kotlin/net/corda/nodeapi/internal/config/ConfigParsingTest.kt index 5efdeaf439..a6fa2ca169 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/config/ConfigParsingTest.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/config/ConfigParsingTest.kt @@ -1,4 +1,4 @@ -package net.corda.nodeapi.config +package net.corda.nodeapi.internal.config import com.typesafe.config.Config import com.typesafe.config.ConfigFactory.empty diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/EnumEvolvabilityTests.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/EnumEvolvabilityTests.kt index 6626f558b9..969db89a54 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/EnumEvolvabilityTests.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/EnumEvolvabilityTests.kt @@ -1,6 +1,7 @@ package net.corda.nodeapi.internal.serialization.amqp import net.corda.core.serialization.* +import net.corda.testing.common.internal.ProjectStructure.projectRootDir import org.assertj.core.api.Assertions import org.junit.Test import java.io.File @@ -10,8 +11,9 @@ import kotlin.test.assertEquals import kotlin.test.assertTrue class EnumEvolvabilityTests { - var localPath = "file:///home/katelyn/srcs/corda/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp" - + @Suppress("UNUSED") + var localPath = projectRootDir.toUri().resolve( + "node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp") companion object { val VERBOSE = false @@ -21,11 +23,6 @@ class EnumEvolvabilityTests { A, B, C, D } - @CordaSerializationTransformEnumDefaults() - enum class MissingDefaults { - A, B, C, D - } - @CordaSerializationTransformRenames() enum class MissingRenames { A, B, C, D @@ -48,13 +45,6 @@ class EnumEvolvabilityTests { A, B, C, E } - @CordaSerializationTransformRenames( - CordaSerializationTransformRename("E", "C"), - CordaSerializationTransformRename("F", "D")) - enum class RenameEnumTwice { - A, B, E, F - } - @Test fun noAnnotation() { data class C (val n: NotAnnotated) @@ -66,6 +56,11 @@ class EnumEvolvabilityTests { assertEquals(0, bAndS.transformsSchema.types.size) } + @CordaSerializationTransformEnumDefaults() + enum class MissingDefaults { + A, B, C, D + } + @Test fun missingDefaults() { data class C (val m: MissingDefaults) @@ -228,6 +223,13 @@ class EnumEvolvabilityTests { assertEquals("E", (deserialisedSchema[TransformTypes.Rename]!![0] as RenameSchemaTransform).to) } + @CordaSerializationTransformRenames( + CordaSerializationTransformRename("E", "C"), + CordaSerializationTransformRename("F", "D")) + enum class RenameEnumTwice { + A, B, E, F + } + @Test fun doubleRenameAnnotationIsAdded() { data class C (val annotatedEnum: RenameEnumTwice) @@ -433,4 +435,98 @@ class EnumEvolvabilityTests { assertTrue(envelope.transformsSchema.types.containsKey(WithUnknownTest::class.java.name)) assertTrue(envelope.transformsSchema.types[WithUnknownTest::class.java.name]!!.containsKey(TransformTypes.Unknown)) } + + // + // In this example we will have attempted to rename D back to C + // + // The life cycle of the class would've looked like this + // + // 1. enum class RejectCyclicRename { A, B, C } + // 2. enum class RejectCyclicRename { A, B, D } + // 3. enum class RejectCyclicRename { A, B, C } + // + // And we're not at 3. However, we ban this rename + // + @CordaSerializationTransformRenames ( + CordaSerializationTransformRename("D", "C"), + CordaSerializationTransformRename("C", "D") + ) + enum class RejectCyclicRename { A, B, C } + + @Test + fun rejectCyclicRename() { + data class C (val e: RejectCyclicRename) + + val sf = testDefaultFactory() + Assertions.assertThatThrownBy { + SerializationOutput(sf).serialize(C(RejectCyclicRename.A)) + }.isInstanceOf(NotSerializableException::class.java) + } + + // + // In this test, like the above, we're looking to ensure repeated renames are rejected as + // unserailzble. However, in this case, it isn't a struct cycle, rather one element + // is renamed to match what a different element used to be called + // + @CordaSerializationTransformRenames ( + CordaSerializationTransformRename(from = "B", to = "C"), + CordaSerializationTransformRename(from = "C", to = "D") + ) + enum class RejectCyclicRenameAlt { A, C, D } + + @Test + fun rejectCyclicRenameAlt() { + data class C (val e: RejectCyclicRenameAlt) + + val sf = testDefaultFactory() + Assertions.assertThatThrownBy { + SerializationOutput(sf).serialize(C(RejectCyclicRenameAlt.A)) + }.isInstanceOf(NotSerializableException::class.java) + } + + @CordaSerializationTransformRenames ( + CordaSerializationTransformRename("G", "C"), + CordaSerializationTransformRename("F", "G"), + CordaSerializationTransformRename("E", "F"), + CordaSerializationTransformRename("D", "E"), + CordaSerializationTransformRename("C", "D") + ) + enum class RejectCyclicRenameRedux { A, B, C } + + @Test + fun rejectCyclicRenameRedux() { + data class C (val e: RejectCyclicRenameRedux) + + val sf = testDefaultFactory() + Assertions.assertThatThrownBy { + SerializationOutput(sf).serialize(C(RejectCyclicRenameRedux.A)) + }.isInstanceOf(NotSerializableException::class.java) + } + + @CordaSerializationTransformEnumDefault (new = "D", old = "X") + enum class RejectBadDefault { A, B, C, D } + + @Test + fun rejectBadDefault() { + data class C (val e: RejectBadDefault) + + val sf = testDefaultFactory() + Assertions.assertThatThrownBy { + SerializationOutput(sf).serialize(C(RejectBadDefault.D)) + }.isInstanceOf(NotSerializableException::class.java) + } + + @CordaSerializationTransformEnumDefault (new = "D", old = "D") + enum class RejectBadDefaultToSelf { A, B, C, D } + + @Test + fun rejectBadDefaultToSelf() { + data class C (val e: RejectBadDefaultToSelf) + + val sf = testDefaultFactory() + Assertions.assertThatThrownBy { + SerializationOutput(sf).serialize(C(RejectBadDefaultToSelf.D)) + }.isInstanceOf(NotSerializableException::class.java) + } + } diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.kt index 265f4b9a0c..b2939d7fa9 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.kt @@ -1,18 +1,19 @@ package net.corda.nodeapi.internal.serialization.amqp -import net.corda.core.serialization.CordaSerializationTransformEnumDefault -import net.corda.core.serialization.SerializedBytes +import net.corda.core.serialization.* import net.corda.testing.common.internal.ProjectStructure.projectRootDir import org.assertj.core.api.Assertions import org.junit.Test import java.io.File import java.io.NotSerializableException import java.net.URI +import kotlin.test.assertEquals // NOTE: To recreate the test files used by these tests uncomment the original test classes and comment // the new ones out, then change each test to write out the serialized bytes rather than read // the file. class EnumEvolveTests { + @Suppress("UNUSED") var localPath = projectRootDir.toUri().resolve( "node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp") @@ -26,7 +27,7 @@ class EnumEvolveTests { @Test fun deserialiseNewerSetToUnknown() { - val resource = "${this.javaClass.simpleName}.${testName()}" + val resource = "${javaClass.simpleName}.${testName()}" val sf = testDefaultFactory() data class C (val e : DeserializeNewerSetToUnknown) @@ -35,9 +36,379 @@ class EnumEvolveTests { // File(URI("$localPath/$resource")).writeBytes( // SerializationOutput(sf).serialize(C(DeserializeNewerSetToUnknown.D)).bytes) + val path = EvolvabilityTests::class.java.getResource(resource) + + val obj = DeserializationInput(sf).deserialize(SerializedBytes(File(path.toURI()).readBytes())) + + assertEquals (DeserializeNewerSetToUnknown.C, obj.e) + } + + // Version of the class as it was serialised + // + // @CordaSerializationTransformEnumDefaults ( + // CordaSerializationTransformEnumDefault("D", "C"), + // CordaSerializationTransformEnumDefault("E", "D")) + // enum class DeserializeNewerSetToUnknown2 { A, B, C, D, E } + // + // Version of the class as it's used in the test + enum class DeserializeNewerSetToUnknown2 { A, B, C } + + @Test + fun deserialiseNewerSetToUnknown2() { + val resource = "${javaClass.simpleName}.${testName()}" + val sf = testDefaultFactory() + + data class C(val e: DeserializeNewerSetToUnknown2) + + // Uncomment to re-generate test files + // val so = SerializationOutput(sf) + // File(URI("$localPath/$resource.C")).writeBytes(so.serialize(C(DeserializeNewerSetToUnknown2.C)).bytes) + // File(URI("$localPath/$resource.D")).writeBytes(so.serialize(C(DeserializeNewerSetToUnknown2.D)).bytes) + // File(URI("$localPath/$resource.E")).writeBytes(so.serialize(C(DeserializeNewerSetToUnknown2.E)).bytes) + + val path1 = EvolvabilityTests::class.java.getResource("$resource.C") + val path2 = EvolvabilityTests::class.java.getResource("$resource.D") + val path3 = EvolvabilityTests::class.java.getResource("$resource.E") + + // C will just work + val obj1 = DeserializationInput(sf).deserialize(SerializedBytes(File(path1.toURI()).readBytes())) + // D will transform directly to C + val obj2 = DeserializationInput(sf).deserialize(SerializedBytes(File(path2.toURI()).readBytes())) + // E will have to transform from E -> D -> C to work, so this should exercise that part + // of the evolution code + val obj3 = DeserializationInput(sf).deserialize(SerializedBytes(File(path3.toURI()).readBytes())) + + assertEquals (DeserializeNewerSetToUnknown2.C, obj1.e) + assertEquals (DeserializeNewerSetToUnknown2.C, obj2.e) + assertEquals (DeserializeNewerSetToUnknown2.C, obj3.e) + } + + + // Version of the class as it was serialised, evolve rule purposfuly not included to + // test failure conditions + // + // enum class DeserializeNewerWithNoRule { A, B, C, D } + // + // Class as it exists for the test + enum class DeserializeNewerWithNoRule { A, B, C } + + // Lets test to see if they forgot to provide an upgrade rule + @Test + fun deserialiseNewerWithNoRule() { + val resource = "${javaClass.simpleName}.${testName()}" + val sf = testDefaultFactory() + + data class C(val e: DeserializeNewerWithNoRule) + + // Uncomment to re-generate test files + // val so = SerializationOutput(sf) + // File(URI("$localPath/$resource")).writeBytes(so.serialize(C(DeserializeNewerWithNoRule.D)).bytes) + + val path = EvolvabilityTests::class.java.getResource(resource) + + Assertions.assertThatThrownBy { + DeserializationInput(sf).deserialize(SerializedBytes(File(path.toURI()).readBytes())) + }.isInstanceOf(NotSerializableException::class.java) + } + + // Version of class as it was serialized, at some point in the "future" several + // values have been renamed + // + // First Change + // A -> AA + // @CordaSerializationTransformRenames ( + // CordaSerializationTransformRename(from ="A", to = "AA") + // ) + // enum class DeserializeWithRename { AA, B, C } + // + // Second Change + // B -> BB + // @CordaSerializationTransformRenames ( + // CordaSerializationTransformRename(from = "B", to = "BB"), + // CordaSerializationTransformRename(from = "A", to = "AA") + // ) + // enum class DeserializeWithRename { AA, BB, C } + // + // Third Change + // BB -> XX + // @CordaSerializationTransformRenames ( + // CordaSerializationTransformRename(from = "B", to = "BB"), + // CordaSerializationTransformRename(from = "BB", to = "XX"), + // CordaSerializationTransformRename(from = "A", to = "AA") + // ) + // enum class DeserializeWithRename { AA, XX, C } + // + // Finally, the version we're using to test with + enum class DeserializeWithRename { A, B, C } + + @Test + fun deserializeWithRename() { + val resource = "${javaClass.simpleName}.${testName()}" + val sf = testDefaultFactory() + + data class C(val e: DeserializeWithRename) + + // Uncomment to re-generate test files, needs to be done in three stages + val so = SerializationOutput(sf) + // First change + // File(URI("$localPath/$resource.1.AA")).writeBytes(so.serialize(C(DeserializeWithRename.AA)).bytes) + // File(URI("$localPath/$resource.1.B")).writeBytes(so.serialize(C(DeserializeWithRename.B)).bytes) + // File(URI("$localPath/$resource.1.C")).writeBytes(so.serialize(C(DeserializeWithRename.C)).bytes) + // Second change + // File(URI("$localPath/$resource.2.AA")).writeBytes(so.serialize(C(DeserializeWithRename.AA)).bytes) + // File(URI("$localPath/$resource.2.BB")).writeBytes(so.serialize(C(DeserializeWithRename.BB)).bytes) + // File(URI("$localPath/$resource.2.C")).writeBytes(so.serialize(C(DeserializeWithRename.C)).bytes) + // Third change + // File(URI("$localPath/$resource.3.AA")).writeBytes(so.serialize(C(DeserializeWithRename.AA)).bytes) + // File(URI("$localPath/$resource.3.XX")).writeBytes(so.serialize(C(DeserializeWithRename.XX)).bytes) + // File(URI("$localPath/$resource.3.C")).writeBytes(so.serialize(C(DeserializeWithRename.C)).bytes) + + // + // Test we can deserialize instances of the class after its first transformation + // + val path1_AA = EvolvabilityTests::class.java.getResource("$resource.1.AA") + val path1_B = EvolvabilityTests::class.java.getResource("$resource.1.B") + val path1_C = EvolvabilityTests::class.java.getResource("$resource.1.C") + + val obj1_AA = DeserializationInput(sf).deserialize(SerializedBytes(File(path1_AA.toURI()).readBytes())) + val obj1_B = DeserializationInput(sf).deserialize(SerializedBytes(File(path1_B.toURI()).readBytes())) + val obj1_C = DeserializationInput(sf).deserialize(SerializedBytes(File(path1_C.toURI()).readBytes())) + + assertEquals(DeserializeWithRename.A, obj1_AA.e) + assertEquals(DeserializeWithRename.B, obj1_B.e) + assertEquals(DeserializeWithRename.C, obj1_C.e) + + // + // Test we can deserialize instances of the class after its second transformation + // + val path2_AA = EvolvabilityTests::class.java.getResource("$resource.2.AA") + val path2_BB = EvolvabilityTests::class.java.getResource("$resource.2.BB") + val path2_C = EvolvabilityTests::class.java.getResource("$resource.2.C") + + val obj2_AA = DeserializationInput(sf).deserialize(SerializedBytes(File(path2_AA.toURI()).readBytes())) + val obj2_BB = DeserializationInput(sf).deserialize(SerializedBytes(File(path2_BB.toURI()).readBytes())) + val obj2_C = DeserializationInput(sf).deserialize(SerializedBytes(File(path2_C.toURI()).readBytes())) + + assertEquals(DeserializeWithRename.A, obj2_AA.e) + assertEquals(DeserializeWithRename.B, obj2_BB.e) + assertEquals(DeserializeWithRename.C, obj2_C.e) + + // + // Test we can deserialize instances of the class after its third transformation + // + val path3_AA = EvolvabilityTests::class.java.getResource("$resource.3.AA") + val path3_XX = EvolvabilityTests::class.java.getResource("$resource.3.XX") + val path3_C = EvolvabilityTests::class.java.getResource("$resource.3.C") + + val obj3_AA = DeserializationInput(sf).deserialize(SerializedBytes(File(path3_AA.toURI()).readBytes())) + val obj3_XX = DeserializationInput(sf).deserialize(SerializedBytes(File(path3_XX.toURI()).readBytes())) + val obj3_C = DeserializationInput(sf).deserialize(SerializedBytes(File(path3_C.toURI()).readBytes())) + + assertEquals(DeserializeWithRename.A, obj3_AA.e) + assertEquals(DeserializeWithRename.B, obj3_XX.e) + assertEquals(DeserializeWithRename.C, obj3_C.e) + } + + // The origional version of the enum, what we'll be eventually deserialising into + // enum class MultiOperations { A, B, C } + // + // First alteration, add D + // @CordaSerializationTransformEnumDefault(old = "C", new = "D") + // enum class MultiOperations { A, B, C, D } + // + // Second, add E + // @CordaSerializationTransformEnumDefaults( + // CordaSerializationTransformEnumDefault(old = "C", new = "D"), + // CordaSerializationTransformEnumDefault(old = "D", new = "E") + // ) + // enum class MultiOperations { A, B, C, D, E } + // + // Third, Rename E to BOB + // @CordaSerializationTransformEnumDefaults( + // CordaSerializationTransformEnumDefault(old = "C", new = "D"), + // CordaSerializationTransformEnumDefault(old = "D", new = "E") + // ) + // @CordaSerializationTransformRename(to = "BOB", from = "E") + // enum class MultiOperations { A, B, C, D, BOB } + // + // Fourth, Rename C to CAT, ADD F and G + // @CordaSerializationTransformEnumDefaults( + // CordaSerializationTransformEnumDefault(old = "F", new = "G"), + // CordaSerializationTransformEnumDefault(old = "BOB", new = "F"), + // CordaSerializationTransformEnumDefault(old = "D", new = "E"), + // CordaSerializationTransformEnumDefault(old = "C", new = "D") + // ) + // @CordaSerializationTransformRenames ( + // CordaSerializationTransformRename(to = "CAT", from = "C"), + // CordaSerializationTransformRename(to = "BOB", from = "E") + // ) + // enum class MultiOperations { A, B, CAT, D, BOB, F, G} + // + // Fifth, Rename F to FLUMP, Rename BOB to BBB, Rename A to APPLE + // @CordaSerializationTransformEnumDefaults( + // CordaSerializationTransformEnumDefault(old = "F", new = "G"), + // CordaSerializationTransformEnumDefault(old = "BOB", new = "F"), + // CordaSerializationTransformEnumDefault(old = "D", new = "E"), + // CordaSerializationTransformEnumDefault(old = "C", new = "D") + // ) + // @CordaSerializationTransformRenames ( + // CordaSerializationTransformRename(to = "APPLE", from = "A"), + // CordaSerializationTransformRename(to = "BBB", from = "BOB"), + // CordaSerializationTransformRename(to = "FLUMP", from = "F"), + // CordaSerializationTransformRename(to = "CAT", from = "C"), + // CordaSerializationTransformRename(to = "BOB", from = "E") + // ) + // enum class MultiOperations { APPLE, B, CAT, D, BBB, FLUMP, G} + // + // Finally, the original version of teh class that we're going to be testing with + enum class MultiOperations { A, B, C } + + @Test + fun multiOperations() { + val resource = "${javaClass.simpleName}.${testName()}" + val sf = testDefaultFactory() + + data class C(val e: MultiOperations) + + // Uncomment to re-generate test files, needs to be done in three stages + val so = SerializationOutput(sf) + // First change + // File(URI("$localPath/$resource.1.A")).writeBytes(so.serialize(C(MultiOperations.A)).bytes) + // File(URI("$localPath/$resource.1.B")).writeBytes(so.serialize(C(MultiOperations.B)).bytes) + // File(URI("$localPath/$resource.1.C")).writeBytes(so.serialize(C(MultiOperations.C)).bytes) + // File(URI("$localPath/$resource.1.D")).writeBytes(so.serialize(C(MultiOperations.D)).bytes) + // Second change + // File(URI("$localPath/$resource.2.A")).writeBytes(so.serialize(C(MultiOperations.A)).bytes) + // File(URI("$localPath/$resource.2.B")).writeBytes(so.serialize(C(MultiOperations.B)).bytes) + // File(URI("$localPath/$resource.2.C")).writeBytes(so.serialize(C(MultiOperations.C)).bytes) + // File(URI("$localPath/$resource.2.D")).writeBytes(so.serialize(C(MultiOperations.D)).bytes) + // File(URI("$localPath/$resource.2.E")).writeBytes(so.serialize(C(MultiOperations.E)).bytes) + // Third change + // File(URI("$localPath/$resource.3.A")).writeBytes(so.serialize(C(MultiOperations.A)).bytes) + // File(URI("$localPath/$resource.3.B")).writeBytes(so.serialize(C(MultiOperations.B)).bytes) + // File(URI("$localPath/$resource.3.C")).writeBytes(so.serialize(C(MultiOperations.C)).bytes) + // File(URI("$localPath/$resource.3.D")).writeBytes(so.serialize(C(MultiOperations.D)).bytes) + // File(URI("$localPath/$resource.3.BOB")).writeBytes(so.serialize(C(MultiOperations.BOB)).bytes) + // Fourth change + // File(URI("$localPath/$resource.4.A")).writeBytes(so.serialize(C(MultiOperations.A)).bytes) + // File(URI("$localPath/$resource.4.B")).writeBytes(so.serialize(C(MultiOperations.B)).bytes) + // File(URI("$localPath/$resource.4.CAT")).writeBytes(so.serialize(C(MultiOperations.CAT)).bytes) + // File(URI("$localPath/$resource.4.D")).writeBytes(so.serialize(C(MultiOperations.D)).bytes) + // File(URI("$localPath/$resource.4.BOB")).writeBytes(so.serialize(C(MultiOperations.BOB)).bytes) + // File(URI("$localPath/$resource.4.F")).writeBytes(so.serialize(C(MultiOperations.F)).bytes) + // File(URI("$localPath/$resource.4.G")).writeBytes(so.serialize(C(MultiOperations.G)).bytes) + // Fifth change - { APPLE, B, CAT, D, BBB, FLUMP, G} + // File(URI("$localPath/$resource.5.APPLE")).writeBytes(so.serialize(C(MultiOperations.APPLE)).bytes) + // File(URI("$localPath/$resource.5.B")).writeBytes(so.serialize(C(MultiOperations.B)).bytes) + // File(URI("$localPath/$resource.5.CAT")).writeBytes(so.serialize(C(MultiOperations.CAT)).bytes) + // File(URI("$localPath/$resource.5.D")).writeBytes(so.serialize(C(MultiOperations.D)).bytes) + // File(URI("$localPath/$resource.5.BBB")).writeBytes(so.serialize(C(MultiOperations.BBB)).bytes) + // File(URI("$localPath/$resource.5.FLUMP")).writeBytes(so.serialize(C(MultiOperations.FLUMP)).bytes) + // File(URI("$localPath/$resource.5.G")).writeBytes(so.serialize(C(MultiOperations.G)).bytes) + + val stage1Resources = listOf( + Pair("$resource.1.A", MultiOperations.A), + Pair("$resource.1.B", MultiOperations.B), + Pair("$resource.1.C", MultiOperations.C), + Pair("$resource.1.D", MultiOperations.C)) + + val stage2Resources = listOf( + Pair("$resource.2.A", MultiOperations.A), + Pair("$resource.2.B", MultiOperations.B), + Pair("$resource.2.C", MultiOperations.C), + Pair("$resource.2.D", MultiOperations.C), + Pair("$resource.2.E", MultiOperations.C)) + + val stage3Resources = listOf( + Pair("$resource.3.A", MultiOperations.A), + Pair("$resource.3.B", MultiOperations.B), + Pair("$resource.3.C", MultiOperations.C), + Pair("$resource.3.D", MultiOperations.C), + Pair("$resource.3.BOB", MultiOperations.C)) + + val stage4Resources = listOf( + Pair("$resource.4.A", MultiOperations.A), + Pair("$resource.4.B", MultiOperations.B), + Pair("$resource.4.CAT", MultiOperations.C), + Pair("$resource.4.D", MultiOperations.C), + Pair("$resource.4.BOB", MultiOperations.C), + Pair("$resource.4.F", MultiOperations.C), + Pair("$resource.4.G", MultiOperations.C)) + + val stage5Resources = listOf( + Pair("$resource.5.APPLE", MultiOperations.A), + Pair("$resource.5.B", MultiOperations.B), + Pair("$resource.5.CAT", MultiOperations.C), + Pair("$resource.5.D", MultiOperations.C), + Pair("$resource.5.BBB", MultiOperations.C), + Pair("$resource.5.FLUMP", MultiOperations.C), + Pair("$resource.5.G", MultiOperations.C)) + + fun load(l: List>) = l.map { + Pair (DeserializationInput(sf).deserialize(SerializedBytes( + File(EvolvabilityTests::class.java.getResource(it.first).toURI()).readBytes())), it.second) + } + + load (stage1Resources).forEach { assertEquals(it.second, it.first.e) } + load (stage2Resources).forEach { assertEquals(it.second, it.first.e) } + load (stage3Resources).forEach { assertEquals(it.second, it.first.e) } + load (stage4Resources).forEach { assertEquals(it.second, it.first.e) } + load (stage5Resources).forEach { assertEquals(it.second, it.first.e) } + } + + @CordaSerializationTransformEnumDefault(old = "A", new = "F") + enum class BadNewValue { A, B, C, D } + + @Test + fun badNewValue() { + val sf = testDefaultFactory() + + data class C (val e : BadNewValue) + + Assertions.assertThatThrownBy { + SerializationOutput(sf).serialize(C(BadNewValue.A)) + }.isInstanceOf(NotSerializableException::class.java) + } + + @CordaSerializationTransformEnumDefaults( + CordaSerializationTransformEnumDefault(new = "D", old = "E"), + CordaSerializationTransformEnumDefault(new = "E", old = "A") + ) + enum class OutOfOrder { A, B, C, D, E} + + @Test + fun outOfOrder() { + val sf = testDefaultFactory() + + data class C (val e : OutOfOrder) + + Assertions.assertThatThrownBy { + SerializationOutput(sf).serialize(C(OutOfOrder.A)) + }.isInstanceOf(NotSerializableException::class.java) + } + + // class as it existed as it was serialized + // + // enum class ChangedOrdinality { A, B, C } + // + // class as it exists for the tests + @CordaSerializationTransformEnumDefault("D", "A") + enum class ChangedOrdinality { A, B, D, C } + + @Test + fun changedOrdinality() { + val resource = "${javaClass.simpleName}.${testName()}" + val sf = testDefaultFactory() + + data class C(val e: ChangedOrdinality) + + // Uncomment to re-generate test files, needs to be done in three stages + // File(URI("$localPath/$resource")).writeBytes( + // SerializationOutput(sf).serialize(C(ChangedOrdinality.A)).bytes) + Assertions.assertThatThrownBy { DeserializationInput(sf).deserialize(SerializedBytes( File(EvolvabilityTests::class.java.getResource(resource).toURI()).readBytes())) }.isInstanceOf(NotSerializableException::class.java) } -} \ No newline at end of file +} diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/EvolvabilityTests.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/EvolvabilityTests.kt index 69a5316a5e..f092be08a0 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/EvolvabilityTests.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/EvolvabilityTests.kt @@ -2,6 +2,7 @@ package net.corda.nodeapi.internal.serialization.amqp import net.corda.core.serialization.DeprecatedConstructorForDeserialization import net.corda.core.serialization.SerializedBytes +import net.corda.testing.common.internal.ProjectStructure.projectRootDir import org.junit.Test import java.io.File import java.io.NotSerializableException @@ -18,7 +19,8 @@ import kotlin.test.assertEquals // 5. Comment back out the generation code and uncomment the actual test class EvolvabilityTests { // When regenerating the test files this needs to be set to the file system location of the resource files - var localPath = "file://////corda/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp" + var localPath = projectRootDir.toUri().resolve( + "node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp") @Test fun simpleOrderSwapSameType() { diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.changedOrdinality b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.changedOrdinality new file mode 100644 index 0000000000..af084de97a Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.changedOrdinality differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserialiseNewerSetToUnknown2.C b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserialiseNewerSetToUnknown2.C new file mode 100644 index 0000000000..cced4f8de7 Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserialiseNewerSetToUnknown2.C differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserialiseNewerSetToUnknown2.D b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserialiseNewerSetToUnknown2.D new file mode 100644 index 0000000000..998ec49f9a Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserialiseNewerSetToUnknown2.D differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserialiseNewerSetToUnknown2.E b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserialiseNewerSetToUnknown2.E new file mode 100644 index 0000000000..cd62f21adb Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserialiseNewerSetToUnknown2.E differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserialiseNewerWithNoRule b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserialiseNewerWithNoRule new file mode 100644 index 0000000000..58cf98b4ad Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserialiseNewerWithNoRule differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserializeWithRename.1.AA b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserializeWithRename.1.AA new file mode 100644 index 0000000000..16b9b723f8 Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserializeWithRename.1.AA differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserializeWithRename.1.B b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserializeWithRename.1.B new file mode 100644 index 0000000000..fb59df3314 Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserializeWithRename.1.B differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserializeWithRename.1.C b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserializeWithRename.1.C new file mode 100644 index 0000000000..33425ddb68 Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserializeWithRename.1.C differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserializeWithRename.2.AA b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserializeWithRename.2.AA new file mode 100644 index 0000000000..4f75773756 Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserializeWithRename.2.AA differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserializeWithRename.2.BB b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserializeWithRename.2.BB new file mode 100644 index 0000000000..521bf9ec2f Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserializeWithRename.2.BB differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserializeWithRename.2.C b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserializeWithRename.2.C new file mode 100644 index 0000000000..62448e369e Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserializeWithRename.2.C differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserializeWithRename.3.AA b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserializeWithRename.3.AA new file mode 100644 index 0000000000..c597affc7b Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserializeWithRename.3.AA differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserializeWithRename.3.C b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserializeWithRename.3.C new file mode 100644 index 0000000000..5e90893cb4 Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserializeWithRename.3.C differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserializeWithRename.3.XX b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserializeWithRename.3.XX new file mode 100644 index 0000000000..86d9a16721 Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.deserializeWithRename.3.XX differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.1.A b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.1.A new file mode 100644 index 0000000000..c28d480977 Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.1.A differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.1.B b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.1.B new file mode 100644 index 0000000000..4f5e9ab81c Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.1.B differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.1.C b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.1.C new file mode 100644 index 0000000000..6fd1917beb Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.1.C differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.1.D b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.1.D new file mode 100644 index 0000000000..2ca115091f Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.1.D differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.2.A b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.2.A new file mode 100644 index 0000000000..434b43c42a Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.2.A differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.2.B b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.2.B new file mode 100644 index 0000000000..f216584cdf Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.2.B differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.2.C b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.2.C new file mode 100644 index 0000000000..864da60e34 Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.2.C differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.2.D b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.2.D new file mode 100644 index 0000000000..71b890bdef Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.2.D differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.2.E b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.2.E new file mode 100644 index 0000000000..cf15290a05 Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.2.E differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.3.A b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.3.A new file mode 100644 index 0000000000..26cbcc8f4e Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.3.A differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.3.B b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.3.B new file mode 100644 index 0000000000..8478191ec9 Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.3.B differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.3.BOB b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.3.BOB new file mode 100644 index 0000000000..87a4636599 Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.3.BOB differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.3.C b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.3.C new file mode 100644 index 0000000000..d66d774640 Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.3.C differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.3.D b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.3.D new file mode 100644 index 0000000000..0bc8084e62 Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.3.D differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.4.A b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.4.A new file mode 100644 index 0000000000..40f7c037d2 Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.4.A differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.4.B b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.4.B new file mode 100644 index 0000000000..5d996bfe14 Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.4.B differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.4.BOB b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.4.BOB new file mode 100644 index 0000000000..b741fceac9 Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.4.BOB differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.4.CAT b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.4.CAT new file mode 100644 index 0000000000..bb229ddc82 Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.4.CAT differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.4.D b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.4.D new file mode 100644 index 0000000000..becaee5fa6 Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.4.D differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.4.F b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.4.F new file mode 100644 index 0000000000..b9bedc2502 Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.4.F differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.4.G b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.4.G new file mode 100644 index 0000000000..bd93f918dc Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.4.G differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.5.APPLE b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.5.APPLE new file mode 100644 index 0000000000..95b55e36de Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.5.APPLE differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.5.B b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.5.B new file mode 100644 index 0000000000..f6aaf7d2ff Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.5.B differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.5.BBB b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.5.BBB new file mode 100644 index 0000000000..cd181d1b7c Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.5.BBB differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.5.CAT b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.5.CAT new file mode 100644 index 0000000000..27d9d766f7 Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.5.CAT differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.5.D b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.5.D new file mode 100644 index 0000000000..54420c13fb Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.5.D differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.5.FLUMP b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.5.FLUMP new file mode 100644 index 0000000000..86b4ed8e6a Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.5.FLUMP differ diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.5.G b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.5.G new file mode 100644 index 0000000000..92ed95c4d8 Binary files /dev/null and b/node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp/EnumEvolveTests.multiOperations.5.G differ diff --git a/node/src/integration-test/kotlin/net/corda/node/BootTests.kt b/node/src/integration-test/kotlin/net/corda/node/BootTests.kt index 4bc031400d..af08160cab 100644 --- a/node/src/integration-test/kotlin/net/corda/node/BootTests.kt +++ b/node/src/integration-test/kotlin/net/corda/node/BootTests.kt @@ -8,7 +8,8 @@ import net.corda.core.messaging.startFlow import net.corda.core.utilities.getOrThrow import net.corda.node.internal.NodeStartup import net.corda.node.services.Permissions.Companion.startFlow -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User +import net.corda.testing.ALICE import net.corda.testing.* import net.corda.testing.common.internal.ProjectStructure.projectRootDir import net.corda.testing.driver.driver diff --git a/node/src/integration-test/kotlin/net/corda/node/CordappScanningDriverTest.kt b/node/src/integration-test/kotlin/net/corda/node/CordappScanningDriverTest.kt index 57583b893a..b9a0a86535 100644 --- a/node/src/integration-test/kotlin/net/corda/node/CordappScanningDriverTest.kt +++ b/node/src/integration-test/kotlin/net/corda/node/CordappScanningDriverTest.kt @@ -8,7 +8,10 @@ import net.corda.core.messaging.startFlow import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.unwrap import net.corda.node.services.Permissions.Companion.startFlow -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User +import net.corda.testing.ALICE +import net.corda.testing.BOB +import net.corda.testing.chooseIdentity import net.corda.testing.* import net.corda.testing.driver.driver import org.assertj.core.api.Assertions.assertThat diff --git a/node/src/integration-test/kotlin/net/corda/node/NodePerformanceTests.kt b/node/src/integration-test/kotlin/net/corda/node/NodePerformanceTests.kt index 56f4e79845..9f212fe55d 100644 --- a/node/src/integration-test/kotlin/net/corda/node/NodePerformanceTests.kt +++ b/node/src/integration-test/kotlin/net/corda/node/NodePerformanceTests.kt @@ -13,7 +13,8 @@ import net.corda.finance.DOLLARS import net.corda.finance.flows.CashIssueFlow import net.corda.finance.flows.CashPaymentFlow import net.corda.node.services.Permissions.Companion.startFlow -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User +import net.corda.testing.DUMMY_NOTARY import net.corda.testing.* import net.corda.testing.driver.NodeHandle import net.corda.testing.driver.driver diff --git a/node/src/integration-test/kotlin/net/corda/node/SSHServerTest.kt b/node/src/integration-test/kotlin/net/corda/node/SSHServerTest.kt index a9e436400c..1b0f596928 100644 --- a/node/src/integration-test/kotlin/net/corda/node/SSHServerTest.kt +++ b/node/src/integration-test/kotlin/net/corda/node/SSHServerTest.kt @@ -10,7 +10,8 @@ import net.corda.core.utilities.ProgressTracker import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.toHex import net.corda.core.utilities.unwrap -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User +import net.corda.testing.ALICE import net.corda.testing.driver.driver import org.bouncycastle.util.io.Streams import org.junit.Test @@ -33,7 +34,7 @@ class SSHServerTest : IntegrationTest() { fun `ssh server does not start be default`() { val user = User("u", "p", setOf()) // The driver will automatically pick up the annotated flows below - driver { + driver() { val node = startNode(providedName = ALICE.name, rpcUsers = listOf(user)) node.getOrThrow() diff --git a/node/src/integration-test/kotlin/net/corda/node/services/AttachmentLoadingTests.kt b/node/src/integration-test/kotlin/net/corda/node/services/AttachmentLoadingTests.kt index 1e36145857..327cc9175a 100644 --- a/node/src/integration-test/kotlin/net/corda/node/services/AttachmentLoadingTests.kt +++ b/node/src/integration-test/kotlin/net/corda/node/services/AttachmentLoadingTests.kt @@ -1,8 +1,9 @@ package net.corda.node.services +import com.nhaarman.mockito_kotlin.doReturn +import com.nhaarman.mockito_kotlin.whenever import net.corda.core.contracts.Contract import net.corda.core.contracts.PartyAndReference -import net.corda.core.cordapp.CordappProvider import net.corda.core.flows.FlowLogic import net.corda.core.flows.UnexpectedFlowEndException import net.corda.core.identity.CordaX500Name @@ -11,6 +12,8 @@ import net.corda.core.internal.concurrent.transpose import net.corda.core.internal.createDirectories import net.corda.core.internal.div import net.corda.core.internal.toLedgerTransaction +import net.corda.core.node.ServicesForResolution +import net.corda.core.node.services.IdentityService import net.corda.core.serialization.SerializationFactory import net.corda.core.transactions.TransactionBuilder import net.corda.core.utilities.contextLogger @@ -24,9 +27,8 @@ import net.corda.testing.IntegrationTest import net.corda.testing.driver.DriverDSLExposedInterface import net.corda.testing.driver.NodeHandle import net.corda.testing.driver.driver -import net.corda.testing.node.MockServices +import net.corda.testing.node.MockAttachmentStorage import org.junit.Assert.assertEquals -import org.junit.Before import org.junit.ClassRule import org.junit.Test import java.net.URLClassLoader @@ -34,14 +36,11 @@ import java.nio.file.Files import kotlin.test.assertFailsWith class AttachmentLoadingTests : IntegrationTest() { - - private class Services : MockServices() { - private val provider = CordappProviderImpl(CordappLoader.createDevMode(listOf(isolatedJAR)), attachments) - private val cordapp get() = provider.cordapps.first() - val attachmentId get() = provider.getCordappAttachmentId(cordapp)!! - val appContext get() = provider.getAppContext(cordapp) - override val cordappProvider: CordappProvider = provider - } + private val attachments = MockAttachmentStorage() + private val provider = CordappProviderImpl(CordappLoader.createDevMode(listOf(isolatedJAR)), attachments) + private val cordapp get() = provider.cordapps.first() + private val attachmentId get() = provider.getCordappAttachmentId(cordapp)!! + private val appContext get() = provider.getAppContext(cordapp) private companion object { @ClassRule @JvmField @@ -77,17 +76,17 @@ class AttachmentLoadingTests : IntegrationTest() { } } - private lateinit var services: Services - - @Before - fun setup() { - super.setUp() - services = Services() + private val services = rigorousMock().also { + doReturn(attachments).whenever(it).attachments + doReturn(provider).whenever(it).cordappProvider + doReturn(rigorousMock().also { + doReturn(null).whenever(it).partyFromKey(DUMMY_BANK_A.owningKey) + }).whenever(it).identityService } @Test fun `test a wire transaction has loaded the correct attachment`() = withTestSerialization { - val appClassLoader = services.appContext.classLoader + val appClassLoader = appContext.classLoader val contractClass = appClassLoader.loadClass(ISOLATED_CONTRACT_ID).asSubclass(Contract::class.java) val generateInitialMethod = contractClass.getDeclaredMethod("generateInitial", PartyAndReference::class.java, Integer.TYPE, Party::class.java) val contract = contractClass.newInstance() @@ -97,8 +96,7 @@ class AttachmentLoadingTests : IntegrationTest() { contract.verify(ledgerTx) val actual = ledgerTx.attachments.first() - val expected = services.attachments.openAttachment(services.attachmentId)!! - + val expected = attachments.openAttachment(attachmentId)!! assertEquals(expected, actual) } diff --git a/node/src/integration-test/kotlin/net/corda/node/services/DistributedServiceTests.kt b/node/src/integration-test/kotlin/net/corda/node/services/DistributedServiceTests.kt index 2e51acbcb4..595ecb0532 100644 --- a/node/src/integration-test/kotlin/net/corda/node/services/DistributedServiceTests.kt +++ b/node/src/integration-test/kotlin/net/corda/node/services/DistributedServiceTests.kt @@ -14,7 +14,7 @@ import net.corda.finance.flows.CashPaymentFlow import net.corda.node.services.Permissions.Companion.invokeRpc import net.corda.node.services.Permissions.Companion.startFlow import net.corda.node.services.transactions.RaftValidatingNotaryService -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.* import net.corda.testing.driver.NodeHandle import net.corda.testing.driver.driver diff --git a/node/src/integration-test/kotlin/net/corda/node/services/network/NodeInfoWatcherTest.kt b/node/src/integration-test/kotlin/net/corda/node/services/network/NodeInfoWatcherTest.kt index 1a0be3d57f..32716708de 100644 --- a/node/src/integration-test/kotlin/net/corda/node/services/network/NodeInfoWatcherTest.kt +++ b/node/src/integration-test/kotlin/net/corda/node/services/network/NodeInfoWatcherTest.kt @@ -13,6 +13,7 @@ import net.corda.node.services.identity.InMemoryIdentityService import net.corda.nodeapi.NodeInfoFilesCopier import net.corda.testing.* import net.corda.testing.node.MockKeyManagementService +import net.corda.testing.node.makeTestIdentityService import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.contentOf import org.junit.Before @@ -47,9 +48,9 @@ class NodeInfoWatcherTest { @Before fun start() { - val identityService = InMemoryIdentityService(trustRoot = DEV_TRUST_ROOT) + val identityService = makeTestIdentityService() keyManagementService = MockKeyManagementService(identityService, ALICE_KEY) - nodeInfoWatcher = NodeInfoWatcher(tempFolder.root.toPath(), scheduler = scheduler) + nodeInfoWatcher = NodeInfoWatcher(tempFolder.root.toPath(), scheduler) nodeInfoPath = tempFolder.root.toPath() / CordformNode.NODE_INFO_DIRECTORY } diff --git a/node/src/integration-test/kotlin/net/corda/node/services/statemachine/LargeTransactionsTest.kt b/node/src/integration-test/kotlin/net/corda/node/services/statemachine/LargeTransactionsTest.kt index d2fbc59913..da2c989a96 100644 --- a/node/src/integration-test/kotlin/net/corda/node/services/statemachine/LargeTransactionsTest.kt +++ b/node/src/integration-test/kotlin/net/corda/node/services/statemachine/LargeTransactionsTest.kt @@ -8,7 +8,7 @@ import net.corda.core.internal.concurrent.transpose import net.corda.core.messaging.startFlow import net.corda.core.transactions.TransactionBuilder import net.corda.core.utilities.getOrThrow -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.* import net.corda.testing.contracts.DummyContract import net.corda.testing.contracts.DummyState diff --git a/node/src/integration-test/kotlin/net/corda/services/messaging/MQSecurityAsNodeTest.kt b/node/src/integration-test/kotlin/net/corda/services/messaging/MQSecurityAsNodeTest.kt index bd579f4f17..671c352b44 100644 --- a/node/src/integration-test/kotlin/net/corda/services/messaging/MQSecurityAsNodeTest.kt +++ b/node/src/integration-test/kotlin/net/corda/services/messaging/MQSecurityAsNodeTest.kt @@ -5,7 +5,7 @@ import net.corda.core.internal.* import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.NODE_USER import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.PEER_USER import net.corda.nodeapi.RPCApi -import net.corda.nodeapi.config.SSLConfiguration +import net.corda.nodeapi.internal.config.SSLConfiguration import net.corda.nodeapi.internal.crypto.* import net.corda.testing.MEGA_CORP import net.corda.testing.MINI_CORP diff --git a/node/src/integration-test/kotlin/net/corda/services/messaging/MQSecurityAsRPCTest.kt b/node/src/integration-test/kotlin/net/corda/services/messaging/MQSecurityAsRPCTest.kt index cbb75daedd..d4cd7ca4e4 100644 --- a/node/src/integration-test/kotlin/net/corda/services/messaging/MQSecurityAsRPCTest.kt +++ b/node/src/integration-test/kotlin/net/corda/services/messaging/MQSecurityAsRPCTest.kt @@ -1,6 +1,6 @@ package net.corda.services.messaging -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.messaging.SimpleMQClient import org.junit.Test diff --git a/node/src/integration-test/kotlin/net/corda/services/messaging/MQSecurityTest.kt b/node/src/integration-test/kotlin/net/corda/services/messaging/MQSecurityTest.kt index 17c3b36d90..82f2ff5485 100644 --- a/node/src/integration-test/kotlin/net/corda/services/messaging/MQSecurityTest.kt +++ b/node/src/integration-test/kotlin/net/corda/services/messaging/MQSecurityTest.kt @@ -22,8 +22,8 @@ import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.NOTIFICATI import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.P2P_QUEUE import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.PEERS_PREFIX import net.corda.nodeapi.RPCApi -import net.corda.nodeapi.User -import net.corda.nodeapi.config.SSLConfiguration +import net.corda.nodeapi.internal.config.User +import net.corda.nodeapi.internal.config.SSLConfiguration import net.corda.testing.* import net.corda.testing.internal.NodeBasedTest import net.corda.testing.messaging.SimpleMQClient diff --git a/node/src/integration-test/kotlin/net/corda/test/node/NodeStatePersistenceTests.kt b/node/src/integration-test/kotlin/net/corda/test/node/NodeStatePersistenceTests.kt index 5ecf515807..64a8e10dc7 100644 --- a/node/src/integration-test/kotlin/net/corda/test/node/NodeStatePersistenceTests.kt +++ b/node/src/integration-test/kotlin/net/corda/test/node/NodeStatePersistenceTests.kt @@ -19,7 +19,8 @@ import net.corda.core.utilities.ProgressTracker import net.corda.core.utilities.getOrThrow import net.corda.node.services.Permissions.Companion.invokeRpc import net.corda.node.services.Permissions.Companion.startFlow -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User +import net.corda.testing.chooseIdentity import net.corda.testing.* import net.corda.testing.driver.driver import org.junit.Assume.assumeFalse diff --git a/node/src/main/kotlin/net/corda/node/Corda.kt b/node/src/main/kotlin/net/corda/node/Corda.kt index 610cb3ff1f..e72a747572 100644 --- a/node/src/main/kotlin/net/corda/node/Corda.kt +++ b/node/src/main/kotlin/net/corda/node/Corda.kt @@ -3,11 +3,12 @@ package net.corda.node +import kotlin.system.exitProcess import net.corda.node.internal.EnterpriseNode fun main(args: Array) { // Pass the arguments to the Node factory. In the Enterprise edition, this line is modified to point to a subclass. // It will exit the process in case of startup failure and is not intended to be used by embedders. If you want // to embed Node in your own container, instantiate it directly and set up the configuration objects yourself. - EnterpriseNode.Startup(args).run() -} + exitProcess(if (EnterpriseNode.Startup(args).run()) 0 else 1) +} \ No newline at end of file diff --git a/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt b/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt index 1045807798..dfc206b118 100644 --- a/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt +++ b/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt @@ -69,6 +69,7 @@ import org.apache.activemq.artemis.utils.ReusableLatch import org.hibernate.type.descriptor.java.JavaTypeDescriptorRegistry import org.slf4j.Logger import rx.Observable +import rx.Scheduler import java.io.IOException import java.lang.management.ManagementFactory import java.lang.reflect.InvocationTargetException @@ -193,8 +194,7 @@ abstract class AbstractNode(val configuration: NodeConfiguration, val (startedImpl, schedulerService) = initialiseDatabasePersistence(schemaService, identityService) { database -> identityService.loadIdentities(info.legalIdentitiesAndCerts) val transactionStorage = makeTransactionStorage(database) - val stateLoader = StateLoaderImpl(transactionStorage) - val nodeServices = makeServices(keyPairs, schemaService, transactionStorage, stateLoader, database, info, identityService) + val nodeServices = makeServices(keyPairs, schemaService, transactionStorage, database, info, identityService) val mutualExclusionConfiguration = configuration.enterpriseConfiguration.mutualExclusionConfiguration if (mutualExclusionConfiguration.on) { RunOnceService(database, mutualExclusionConfiguration.machineName, @@ -208,7 +208,7 @@ abstract class AbstractNode(val configuration: NodeConfiguration, platformClock, database, flowStarter, - stateLoader, + transactionStorage, unfinishedSchedules = busyNodeLatch, serverThread = serverThread) if (serverThread is ExecutorService) { @@ -233,7 +233,7 @@ abstract class AbstractNode(val configuration: NodeConfiguration, } val networkMapUpdater = NetworkMapUpdater(services.networkMapCache, - NodeInfoWatcher(configuration.baseDirectory, Duration.ofMillis(configuration.additionalNodeInfoPollingFrequencyMsec)), + NodeInfoWatcher(configuration.baseDirectory, getRxIoScheduler(), Duration.ofMillis(configuration.additionalNodeInfoPollingFrequencyMsec)), networkMapClient) runOnStop += networkMapUpdater::close @@ -259,6 +259,12 @@ abstract class AbstractNode(val configuration: NodeConfiguration, } } + /** + * Should be [rx.schedulers.Schedulers.io] for production, + * or [rx.internal.schedulers.CachedThreadScheduler] (with shutdown registered with [runOnStop]) for shared-JVM testing. + */ + protected abstract fun getRxIoScheduler(): Scheduler + open fun startShell(rpcOps: CordaRPCOps) { InteractiveShell.startShell(configuration, rpcOps, userService, _services.identityService, _services.database) } @@ -500,7 +506,7 @@ abstract class AbstractNode(val configuration: NodeConfiguration, * Builds node internal, advertised, and plugin services. * Returns a list of tokenizable services to be added to the serialisation context. */ - private fun makeServices(keyPairs: Set, schemaService: SchemaService, transactionStorage: WritableTransactionStorage, stateLoader: StateLoader, database: CordaPersistence, info: NodeInfo, identityService: IdentityService): MutableList { + private fun makeServices(keyPairs: Set, schemaService: SchemaService, transactionStorage: WritableTransactionStorage, database: CordaPersistence, info: NodeInfo, identityService: IdentityService): MutableList { checkpointStorage = DBCheckpointStorage() val metrics = MetricRegistry() attachments = NodeAttachmentService(metrics) @@ -511,7 +517,6 @@ abstract class AbstractNode(val configuration: NodeConfiguration, keyManagementService, schemaService, transactionStorage, - stateLoader, MonitoringService(metrics), cordappProvider, database, @@ -724,18 +729,17 @@ abstract class AbstractNode(val configuration: NodeConfiguration, override val keyManagementService: KeyManagementService, override val schemaService: SchemaService, override val validatedTransactions: WritableTransactionStorage, - private val stateLoader: StateLoader, override val monitoringService: MonitoringService, override val cordappProvider: CordappProviderInternal, override val database: CordaPersistence, override val myInfo: NodeInfo - ) : SingletonSerializeAsToken(), ServiceHubInternal, StateLoader by stateLoader { + ) : SingletonSerializeAsToken(), ServiceHubInternal, StateLoader by validatedTransactions { override val rpcFlows = ArrayList>>() override val stateMachineRecordedTransactionMapping = DBTransactionMappingStorage() override val auditService = DummyAuditService() override val transactionVerifierService by lazy { makeTransactionVerifierService() } override val networkMapCache by lazy { NetworkMapCacheImpl(PersistentNetworkMapCache(database), identityService) } - override val vaultService by lazy { makeVaultService(keyManagementService, stateLoader, database.hibernateConfig) } + override val vaultService by lazy { makeVaultService(keyManagementService, validatedTransactions, database.hibernateConfig) } override val contractUpgradeService by lazy { ContractUpgradeServiceImpl() } override val attachments: AttachmentStorage get() = this@AbstractNode.attachments override val networkService: MessagingService get() = network diff --git a/node/src/main/kotlin/net/corda/node/internal/Node.kt b/node/src/main/kotlin/net/corda/node/internal/Node.kt index cbfd81abbe..15682453b8 100644 --- a/node/src/main/kotlin/net/corda/node/internal/Node.kt +++ b/node/src/main/kotlin/net/corda/node/internal/Node.kt @@ -33,6 +33,7 @@ import net.corda.nodeapi.internal.serialization.* import net.corda.nodeapi.internal.serialization.amqp.AMQPServerSerializationScheme import org.slf4j.Logger import org.slf4j.LoggerFactory +import rx.schedulers.Schedulers import java.time.Clock import java.util.concurrent.atomic.AtomicInteger import javax.management.ObjectName @@ -46,7 +47,7 @@ import kotlin.system.exitProcess */ open class Node(configuration: NodeConfiguration, versionInfo: VersionInfo, - val initialiseSerialization: Boolean = true, + private val initialiseSerialization: Boolean = true, cordappLoader: CordappLoader = makeCordappLoader(configuration) ) : AbstractNode(configuration, createClock(configuration), versionInfo, cordappLoader) { companion object { @@ -297,6 +298,7 @@ open class Node(configuration: NodeConfiguration, return started } + override fun getRxIoScheduler() = Schedulers.io()!! private fun initialiseSerialization() { val classloader = cordappLoader.appClassLoader nodeSerializationEnv = SerializationEnvironmentImpl( diff --git a/node/src/main/kotlin/net/corda/node/internal/NodeStartup.kt b/node/src/main/kotlin/net/corda/node/internal/NodeStartup.kt index 2947700025..ebb245c955 100644 --- a/node/src/main/kotlin/net/corda/node/internal/NodeStartup.kt +++ b/node/src/main/kotlin/net/corda/node/internal/NodeStartup.kt @@ -34,68 +34,79 @@ open class NodeStartup(val args: Array) { val LOGS_CAN_BE_FOUND_IN_STRING = "Logs can be found in" } - open fun run() { - val startTime = System.currentTimeMillis() - assertCanNormalizeEmptyPath() - val (argsParser, cmdlineOptions) = parseArguments() - - // We do the single node check before we initialise logging so that in case of a double-node start it - // doesn't mess with the running node's logs. - enforceSingleNodeIsRunning(cmdlineOptions.baseDirectory) - - initLogging(cmdlineOptions) - - val versionInfo = getVersionInfo() - - if (cmdlineOptions.isVersion) { - println("${versionInfo.vendor} ${versionInfo.releaseVersion}") - println("Revision ${versionInfo.revision}") - println("Platform Version ${versionInfo.platformVersion}") - exitProcess(0) - } - - // Maybe render command line help. - if (cmdlineOptions.help) { - argsParser.printHelp(System.out) - exitProcess(0) - } - - drawBanner(versionInfo) - Node.printBasicNodeInfo(LOGS_CAN_BE_FOUND_IN_STRING, System.getProperty("log-path")) - val conf0 = loadConfigFile(cmdlineOptions) - - val conf = if (cmdlineOptions.bootstrapRaftCluster) { - if (conf0 is NodeConfigurationImpl) { - println("Bootstrapping raft cluster (starting up as seed node).") - // Ignore the configured clusterAddresses to make the node bootstrap a cluster instead of joining. - conf0.copy(notary = conf0.notary?.copy(raft = conf0.notary?.raft?.copy(clusterAddresses = emptyList()))) - } else { - println("bootstrap-raft-notaries flag not recognized, exiting...") - exitProcess(1) - } - } else { - conf0 - } - - banJavaSerialisation(conf) - preNetworkRegistration(conf) - maybeRegisterWithNetworkAndExit(cmdlineOptions, conf) - logStartupInfo(versionInfo, cmdlineOptions, conf) - + /** + * @return true if the node startup was successful. This value is intended to be the exit code of the process. + */ + open fun run(): Boolean { try { - cmdlineOptions.baseDirectory.createDirectories() - startNode(conf, versionInfo, startTime, cmdlineOptions) - } catch (e: Exception) { - if (e.message?.startsWith("Unknown named curve:") == true) { - logger.error("Exception during node startup - ${e.message}. " + - "This is a known OpenJDK issue on some Linux distributions, please use OpenJDK from zulu.org or Oracle JDK.") - } else - logger.error("Exception during node startup", e) - exitProcess(1) - } + val startTime = System.currentTimeMillis() + assertCanNormalizeEmptyPath() + val (argsParser, cmdlineOptions) = parseArguments() - logger.info("Node exiting successfully") - exitProcess(0) + // We do the single node check before we initialise logging so that in case of a double-node start it + // doesn't mess with the running node's logs. + enforceSingleNodeIsRunning(cmdlineOptions.baseDirectory) + + initLogging(cmdlineOptions) + + val versionInfo = getVersionInfo() + + if (cmdlineOptions.isVersion) { + println("${versionInfo.vendor} ${versionInfo.releaseVersion}") + println("Revision ${versionInfo.revision}") + println("Platform Version ${versionInfo.platformVersion}") + return true + } + + // Maybe render command line help. + if (cmdlineOptions.help) { + argsParser.printHelp(System.out) + return true + } + + drawBanner(versionInfo) + Node.printBasicNodeInfo(LOGS_CAN_BE_FOUND_IN_STRING, System.getProperty("log-path")) + val conf0 = loadConfigFile(cmdlineOptions) + + val conf = if (cmdlineOptions.bootstrapRaftCluster) { + if (conf0 is NodeConfigurationImpl) { + println("Bootstrapping raft cluster (starting up as seed node).") + // Ignore the configured clusterAddresses to make the node bootstrap a cluster instead of joining. + conf0.copy(notary = conf0.notary?.copy(raft = conf0.notary?.raft?.copy(clusterAddresses = emptyList()))) + } else { + println("bootstrap-raft-notaries flag not recognized, exiting...") + return false + } + } else { + conf0 + } + + banJavaSerialisation(conf) + preNetworkRegistration(conf) + if (shouldRegisterWithNetwork(cmdlineOptions, conf)) { + registerWithNetwork(cmdlineOptions, conf) + return true + } + logStartupInfo(versionInfo, cmdlineOptions, conf) + + try { + cmdlineOptions.baseDirectory.createDirectories() + startNode(conf, versionInfo, startTime, cmdlineOptions) + } catch (e: Exception) { + if (e.message?.startsWith("Unknown named curve:") == true) { + logger.error("Exception during node startup - ${e.message}. " + + "This is a known OpenJDK issue on some Linux distributions, please use OpenJDK from zulu.org or Oracle JDK.") + } else { + logger.error("Exception during node startup", e) + } + return false + } + + logger.info("Node exiting successfully") + return true + } catch (e: Exception) { + return false + } } open protected fun preNetworkRegistration(conf: NodeConfiguration) = Unit @@ -155,9 +166,13 @@ open class NodeStartup(val args: Array) { logger.info("Starting as node on ${conf.p2pAddress}") } - open protected fun maybeRegisterWithNetworkAndExit(cmdlineOptions: CmdLineOptions, conf: NodeConfiguration) { + private fun shouldRegisterWithNetwork(cmdlineOptions: CmdLineOptions, conf: NodeConfiguration): Boolean { val compatibilityZoneURL = conf.compatibilityZoneURL - if (!cmdlineOptions.isRegistration || compatibilityZoneURL == null) return + return !(!cmdlineOptions.isRegistration || compatibilityZoneURL == null) + } + + open protected fun registerWithNetwork(cmdlineOptions: CmdLineOptions, conf: NodeConfiguration) { + val compatibilityZoneURL = conf.compatibilityZoneURL!! println() println("******************************************************************") println("* *") @@ -165,15 +180,14 @@ open class NodeStartup(val args: Array) { println("* *") println("******************************************************************") NetworkRegistrationHelper(conf, HTTPNetworkRegistrationService(compatibilityZoneURL)).buildKeystore() - exitProcess(0) } open protected fun loadConfigFile(cmdlineOptions: CmdLineOptions): NodeConfiguration { try { return cmdlineOptions.loadConfig() - } catch (e: ConfigException) { - println("Unable to load the configuration file: ${e.rootCause.message}") - exitProcess(2) + } catch (configException: ConfigException) { + println("Unable to load the configuration file: ${configException.rootCause.message}") + throw configException } } diff --git a/node/src/main/kotlin/net/corda/node/internal/StartedNode.kt b/node/src/main/kotlin/net/corda/node/internal/StartedNode.kt index e660d6e719..0980fa60de 100644 --- a/node/src/main/kotlin/net/corda/node/internal/StartedNode.kt +++ b/node/src/main/kotlin/net/corda/node/internal/StartedNode.kt @@ -1,13 +1,10 @@ package net.corda.node.internal -import net.corda.core.contracts.* import net.corda.core.flows.FlowLogic import net.corda.core.flows.InitiatedBy import net.corda.core.internal.VisibleForTesting import net.corda.core.messaging.CordaRPCOps import net.corda.core.node.NodeInfo -import net.corda.core.node.StateLoader -import net.corda.core.node.services.CordaService import net.corda.core.node.services.NotaryService import net.corda.core.node.services.TransactionStorage import net.corda.core.serialization.SerializeAsToken @@ -46,17 +43,3 @@ interface StartedNode { return internals.internalRegisterFlowFactory(smm, initiatingFlowClass, flowFactory, initiatedFlowClass, track) } } - -class StateLoaderImpl(private val validatedTransactions: TransactionStorage) : StateLoader { - @Throws(TransactionResolutionException::class) - override fun loadState(stateRef: StateRef): TransactionState<*> { - val stx = validatedTransactions.getTransaction(stateRef.txhash) ?: throw TransactionResolutionException(stateRef.txhash) - return stx.resolveBaseTransaction(this).outputs[stateRef.index] - } - - @Throws(TransactionResolutionException::class) - // TODO: future implementation to retrieve contract states from a Vault BLOB store - override fun loadStates(stateRefs: Set): Set> { - return (stateRefs.map { StateAndRef(loadState(it), it) }).toSet() - } -} diff --git a/node/src/main/kotlin/net/corda/node/services/RPCUserService.kt b/node/src/main/kotlin/net/corda/node/services/RPCUserService.kt index e852e764b1..3a7bbdcb9f 100644 --- a/node/src/main/kotlin/net/corda/node/services/RPCUserService.kt +++ b/node/src/main/kotlin/net/corda/node/services/RPCUserService.kt @@ -1,7 +1,7 @@ package net.corda.node.services import net.corda.core.context.AuthServiceId -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User /** * Service for retrieving [User] objects representing RPC users who are authorised to use the RPC system. A [User] diff --git a/node/src/main/kotlin/net/corda/node/services/config/ConfigUtilities.kt b/node/src/main/kotlin/net/corda/node/services/config/ConfigUtilities.kt index 5df2fe84e6..eb47c8cb19 100644 --- a/node/src/main/kotlin/net/corda/node/services/config/ConfigUtilities.kt +++ b/node/src/main/kotlin/net/corda/node/services/config/ConfigUtilities.kt @@ -5,9 +5,9 @@ import net.corda.core.crypto.Crypto import net.corda.core.crypto.SignatureScheme import net.corda.core.identity.CordaX500Name import net.corda.core.internal.* -import net.corda.nodeapi.config.SSLConfiguration +import net.corda.nodeapi.internal.config.SSLConfiguration +import net.corda.nodeapi.internal.config.toProperties import net.corda.nodeapi.internal.crypto.* -import net.corda.nodeapi.config.toProperties import org.bouncycastle.asn1.x509.GeneralName import org.bouncycastle.asn1.x509.GeneralSubtree import org.bouncycastle.asn1.x509.NameConstraints diff --git a/node/src/main/kotlin/net/corda/node/services/config/NodeConfiguration.kt b/node/src/main/kotlin/net/corda/node/services/config/NodeConfiguration.kt index a40937ccfa..b84b3e781b 100644 --- a/node/src/main/kotlin/net/corda/node/services/config/NodeConfiguration.kt +++ b/node/src/main/kotlin/net/corda/node/services/config/NodeConfiguration.kt @@ -6,9 +6,9 @@ import net.corda.core.utilities.NetworkHostAndPort import net.corda.core.utilities.seconds import net.corda.node.services.messaging.CertificateChainCheckPolicy import net.corda.nodeapi.internal.persistence.DatabaseConfig -import net.corda.nodeapi.User -import net.corda.nodeapi.config.NodeSSLConfiguration -import net.corda.nodeapi.config.parseAs +import net.corda.nodeapi.internal.config.User +import net.corda.nodeapi.internal.config.NodeSSLConfiguration +import net.corda.nodeapi.internal.config.parseAs import java.net.URL import java.nio.file.Path import java.util.* diff --git a/node/src/main/kotlin/net/corda/node/services/identity/InMemoryIdentityService.kt b/node/src/main/kotlin/net/corda/node/services/identity/InMemoryIdentityService.kt index 7fbbd810b8..97e1c03adc 100644 --- a/node/src/main/kotlin/net/corda/node/services/identity/InMemoryIdentityService.kt +++ b/node/src/main/kotlin/net/corda/node/services/identity/InMemoryIdentityService.kt @@ -24,14 +24,8 @@ import javax.annotation.concurrent.ThreadSafe * @param identities initial set of identities for the service, typically only used for unit tests. */ @ThreadSafe -class InMemoryIdentityService(identities: Iterable = emptySet(), - confidentialIdentities: Iterable = emptySet(), - override val trustRoot: X509Certificate, - vararg caCertificates: X509Certificate) : SingletonSerializeAsToken(), IdentityService { - constructor(wellKnownIdentities: Iterable = emptySet(), - confidentialIdentities: Iterable = emptySet(), - trustRoot: X509CertificateHolder) : this(wellKnownIdentities, confidentialIdentities, trustRoot.cert) - +class InMemoryIdentityService(identities: Iterable, + trustRoot: X509CertificateHolder) : SingletonSerializeAsToken(), IdentityService { companion object { private val log = contextLogger() } @@ -40,18 +34,15 @@ class InMemoryIdentityService(identities: Iterable = emptyS * Certificate store for certificate authority and intermediary certificates. */ override val caCertStore: CertStore - override val trustAnchor: TrustAnchor = TrustAnchor(trustRoot, null) + override val trustRoot = trustRoot.cert + override val trustAnchor: TrustAnchor = TrustAnchor(this.trustRoot, null) private val keyToParties = ConcurrentHashMap() private val principalToParties = ConcurrentHashMap() init { - val caCertificatesWithRoot: Set = caCertificates.toSet() + trustRoot - caCertStore = CertStore.getInstance("Collection", CollectionCertStoreParameters(caCertificatesWithRoot)) + caCertStore = CertStore.getInstance("Collection", CollectionCertStoreParameters(setOf(this.trustRoot))) keyToParties.putAll(identities.associateBy { it.owningKey }) principalToParties.putAll(identities.associateBy { it.name }) - confidentialIdentities.forEach { identity -> - principalToParties.computeIfAbsent(identity.name) { identity } - } } // TODO: Check the certificate validation logic diff --git a/node/src/main/kotlin/net/corda/node/services/messaging/ArtemisMessagingClient.kt b/node/src/main/kotlin/net/corda/node/services/messaging/ArtemisMessagingClient.kt index f377087b90..fd36dc9ba7 100644 --- a/node/src/main/kotlin/net/corda/node/services/messaging/ArtemisMessagingClient.kt +++ b/node/src/main/kotlin/net/corda/node/services/messaging/ArtemisMessagingClient.kt @@ -6,7 +6,7 @@ import net.corda.core.utilities.loggerFor import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.NODE_USER import net.corda.nodeapi.ArtemisTcpTransport import net.corda.nodeapi.ConnectionDirection -import net.corda.nodeapi.config.SSLConfiguration +import net.corda.nodeapi.internal.config.SSLConfiguration import org.apache.activemq.artemis.api.core.client.* import org.apache.activemq.artemis.api.core.client.ActiveMQClient.DEFAULT_ACK_BATCH_SIZE diff --git a/node/src/main/kotlin/net/corda/node/services/messaging/ArtemisMessagingServer.kt b/node/src/main/kotlin/net/corda/node/services/messaging/ArtemisMessagingServer.kt index b87ac5f582..2b7e496b32 100644 --- a/node/src/main/kotlin/net/corda/node/services/messaging/ArtemisMessagingServer.kt +++ b/node/src/main/kotlin/net/corda/node/services/messaging/ArtemisMessagingServer.kt @@ -33,6 +33,7 @@ import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.PEERS_PREF import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.PEER_USER import net.corda.nodeapi.internal.ArtemisMessagingComponent.ArtemisPeerAddress import net.corda.nodeapi.internal.ArtemisMessagingComponent.NodeAddress +import net.corda.nodeapi.internal.requireOnDefaultFileSystem import org.apache.activemq.artemis.api.core.SimpleString import org.apache.activemq.artemis.api.core.management.ActiveMQServerControl import org.apache.activemq.artemis.core.config.BridgeConfiguration diff --git a/node/src/main/kotlin/net/corda/node/services/messaging/RPCMessagingClient.kt b/node/src/main/kotlin/net/corda/node/services/messaging/RPCMessagingClient.kt index aa9fea626c..0d7bd5a314 100644 --- a/node/src/main/kotlin/net/corda/node/services/messaging/RPCMessagingClient.kt +++ b/node/src/main/kotlin/net/corda/node/services/messaging/RPCMessagingClient.kt @@ -5,7 +5,7 @@ import net.corda.core.messaging.RPCOps import net.corda.core.serialization.SingletonSerializeAsToken import net.corda.core.utilities.NetworkHostAndPort import net.corda.node.services.RPCUserService -import net.corda.nodeapi.config.SSLConfiguration +import net.corda.nodeapi.internal.config.SSLConfiguration import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.NODE_USER import net.corda.nodeapi.internal.crypto.X509Utilities import net.corda.nodeapi.internal.crypto.getX509Certificate diff --git a/node/src/main/kotlin/net/corda/node/services/messaging/RPCServer.kt b/node/src/main/kotlin/net/corda/node/services/messaging/RPCServer.kt index 54526a76be..2fe7a4b13d 100644 --- a/node/src/main/kotlin/net/corda/node/services/messaging/RPCServer.kt +++ b/node/src/main/kotlin/net/corda/node/services/messaging/RPCServer.kt @@ -30,6 +30,7 @@ import net.corda.node.services.RPCUserService import net.corda.node.services.logging.pushToLoggingContext import net.corda.nodeapi.* import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.NODE_USER +import net.corda.nodeapi.internal.config.User import org.apache.activemq.artemis.api.core.Message import org.apache.activemq.artemis.api.core.SimpleString import org.apache.activemq.artemis.api.core.client.ActiveMQClient.DEFAULT_ACK_BATCH_SIZE diff --git a/node/src/main/kotlin/net/corda/node/services/messaging/VerifierMessagingClient.kt b/node/src/main/kotlin/net/corda/node/services/messaging/VerifierMessagingClient.kt index d916e63cc5..8216b6846b 100644 --- a/node/src/main/kotlin/net/corda/node/services/messaging/VerifierMessagingClient.kt +++ b/node/src/main/kotlin/net/corda/node/services/messaging/VerifierMessagingClient.kt @@ -11,7 +11,7 @@ import net.corda.node.utilities.* import net.corda.nodeapi.VerifierApi import net.corda.nodeapi.VerifierApi.VERIFICATION_REQUESTS_QUEUE_NAME import net.corda.nodeapi.VerifierApi.VERIFICATION_RESPONSES_QUEUE_NAME_PREFIX -import net.corda.nodeapi.config.SSLConfiguration +import net.corda.nodeapi.internal.config.SSLConfiguration import org.apache.activemq.artemis.api.core.RoutingType import org.apache.activemq.artemis.api.core.SimpleString import org.apache.activemq.artemis.api.core.client.* diff --git a/node/src/main/kotlin/net/corda/node/services/network/NodeInfoWatcher.kt b/node/src/main/kotlin/net/corda/node/services/network/NodeInfoWatcher.kt index 76fcf6c472..df583c4ffe 100644 --- a/node/src/main/kotlin/net/corda/node/services/network/NodeInfoWatcher.kt +++ b/node/src/main/kotlin/net/corda/node/services/network/NodeInfoWatcher.kt @@ -12,7 +12,6 @@ import net.corda.core.utilities.seconds import net.corda.nodeapi.NodeInfoFilesCopier import rx.Observable import rx.Scheduler -import rx.schedulers.Schedulers import java.io.IOException import java.nio.file.Path import java.time.Duration @@ -31,9 +30,8 @@ import kotlin.streams.toList */ // TODO: Use NIO watch service instead? class NodeInfoWatcher(private val nodePath: Path, - private val pollInterval: Duration = 5.seconds, - private val scheduler: Scheduler = Schedulers.io()) { - + private val scheduler: Scheduler, + private val pollInterval: Duration = 5.seconds) { private val nodeInfoDirectory = nodePath / CordformNode.NODE_INFO_DIRECTORY private val processedNodeInfoFiles = mutableSetOf() private val _processedNodeInfoHashes = mutableSetOf() diff --git a/node/src/main/kotlin/net/corda/node/services/persistence/InMemoryStateMachineRecordedTransactionMappingStorage.kt b/node/src/main/kotlin/net/corda/node/services/persistence/InMemoryStateMachineRecordedTransactionMappingStorage.kt deleted file mode 100644 index 84dd4974dd..0000000000 --- a/node/src/main/kotlin/net/corda/node/services/persistence/InMemoryStateMachineRecordedTransactionMappingStorage.kt +++ /dev/null @@ -1,48 +0,0 @@ -package net.corda.node.services.persistence - -import net.corda.core.internal.ThreadBox -import net.corda.core.internal.bufferUntilSubscribed -import net.corda.core.crypto.SecureHash -import net.corda.core.flows.StateMachineRunId -import net.corda.core.messaging.DataFeed -import net.corda.core.messaging.StateMachineTransactionMapping -import net.corda.node.services.api.StateMachineRecordedTransactionMappingStorage -import rx.subjects.PublishSubject -import java.util.* -import javax.annotation.concurrent.ThreadSafe - -/** - * This is a temporary in-memory storage of a state machine id -> txhash mapping - * - * TODO persist this instead - */ -@ThreadSafe -class InMemoryStateMachineRecordedTransactionMappingStorage : StateMachineRecordedTransactionMappingStorage { - private class InnerState { - val stateMachineTransactionMap = HashMap>() - val updates = PublishSubject.create()!! - } - - private val mutex = ThreadBox(InnerState()) - - override fun addMapping(stateMachineRunId: StateMachineRunId, transactionId: SecureHash) { - mutex.locked { - stateMachineTransactionMap.getOrPut(stateMachineRunId) { HashSet() }.add(transactionId) - updates.onNext(StateMachineTransactionMapping(stateMachineRunId, transactionId)) - } - } - - override fun track(): - DataFeed, StateMachineTransactionMapping> { - mutex.locked { - return DataFeed( - stateMachineTransactionMap.flatMap { entry -> - entry.value.map { - StateMachineTransactionMapping(entry.key, it) - } - }, - updates.bufferUntilSubscribed() - ) - } - } -} diff --git a/node/src/main/kotlin/net/corda/node/services/transactions/RaftUniquenessProvider.kt b/node/src/main/kotlin/net/corda/node/services/transactions/RaftUniquenessProvider.kt index 53e7c19fbe..3b7b78a374 100644 --- a/node/src/main/kotlin/net/corda/node/services/transactions/RaftUniquenessProvider.kt +++ b/node/src/main/kotlin/net/corda/node/services/transactions/RaftUniquenessProvider.kt @@ -29,8 +29,8 @@ import net.corda.core.serialization.serialize import net.corda.core.utilities.contextLogger import net.corda.node.services.config.RaftConfig import net.corda.node.utilities.AppendOnlyPersistentMap -import net.corda.nodeapi.config.NodeSSLConfiguration -import net.corda.nodeapi.config.SSLConfiguration +import net.corda.nodeapi.internal.config.NodeSSLConfiguration +import net.corda.nodeapi.internal.config.SSLConfiguration import net.corda.nodeapi.internal.persistence.CordaPersistence import net.corda.nodeapi.internal.persistence.NODE_DATABASE_PREFIX import java.nio.file.Path diff --git a/node/src/main/kotlin/net/corda/node/utilities/registration/NetworkRegistrationHelper.kt b/node/src/main/kotlin/net/corda/node/utilities/registration/NetworkRegistrationHelper.kt index c350c3dd97..d9a22e30bc 100644 --- a/node/src/main/kotlin/net/corda/node/utilities/registration/NetworkRegistrationHelper.kt +++ b/node/src/main/kotlin/net/corda/node/utilities/registration/NetworkRegistrationHelper.kt @@ -15,7 +15,6 @@ import java.io.StringWriter import java.security.KeyPair import java.security.KeyStore import java.security.cert.Certificate -import kotlin.system.exitProcess /** * Helper for managing the node registration process, which checks for any existing certificates and requests them if @@ -33,16 +32,16 @@ class NetworkRegistrationHelper(private val config: NodeConfiguration, private v private val privateKeyPassword = config.keyStorePassword /** - * Ensure the initial keystore for a node is set up; note that this function may cause the process to exit under - * some circumstances. + * Ensure the initial keystore for a node is set up. * * This checks the "config.certificatesDirectory" field for certificates required to connect to a Corda network. * If the certificates are not found, a PKCS #10 certification request will be submitted to the * Corda network permissioning server via [NetworkRegistrationService]. This process will enter a polling loop until * the request has been approved, and then the certificate chain will be downloaded and stored in [KeyStore] reside in * the certificates directory. + * + * @throws CertificateRequestException if the certificate retrieved by doorman is invalid. */ - // TODO: Stop killing the calling process from within a called function. fun buildKeystore() { config.certificatesDirectory.createDirectories() val caKeyStore = loadOrCreateKeyStore(config.nodeKeystore, keystorePassword) @@ -62,12 +61,12 @@ class NetworkRegistrationHelper(private val config: NodeConfiguration, private v val certificates = try { pollServerForCertificates(requestId) - } catch (e: CertificateRequestException) { - System.err.println(e.message) - println("Please make sure the details in configuration file are correct and try again.") - println("Corda node will now terminate.") + } catch (certificateRequestException: CertificateRequestException) { + System.err.println(certificateRequestException.message) + System.err.println("Please make sure the details in configuration file are correct and try again.") + System.err.println("Corda node will now terminate.") requestIdStore.deleteIfExists() - exitProcess(1) + throw certificateRequestException } println("Certificate signing request approved, storing private key with the certificate chain.") diff --git a/node/src/test/java/net/corda/node/services/vault/VaultQueryJavaTests.java b/node/src/test/java/net/corda/node/services/vault/VaultQueryJavaTests.java index c1f2a539eb..838370c38c 100644 --- a/node/src/test/java/net/corda/node/services/vault/VaultQueryJavaTests.java +++ b/node/src/test/java/net/corda/node/services/vault/VaultQueryJavaTests.java @@ -19,7 +19,6 @@ import net.corda.core.utilities.OpaqueBytes; import net.corda.finance.contracts.DealState; import net.corda.finance.contracts.asset.Cash; import net.corda.finance.schemas.CashSchemaV1; -import net.corda.node.services.identity.InMemoryIdentityService; import net.corda.nodeapi.internal.persistence.CordaPersistence; import net.corda.nodeapi.internal.persistence.DatabaseTransaction; import net.corda.testing.SerializationEnvironmentRule; @@ -48,6 +47,7 @@ import static net.corda.finance.contracts.asset.CashUtilities.*; import static net.corda.testing.CoreTestUtils.*; import static net.corda.testing.TestConstants.*; import static net.corda.testing.node.MockServices.makeTestDatabaseAndMockServices; +import static net.corda.testing.node.MockServicesKt.makeTestIdentityService; import static org.assertj.core.api.Assertions.assertThat; public class VaultQueryJavaTests { @@ -61,14 +61,12 @@ public class VaultQueryJavaTests { @Before public void setUp() throws CertificateException, InvalidAlgorithmParameterException { List cordappPackages = Arrays.asList("net.corda.testing.contracts", "net.corda.finance.contracts.asset", CashSchemaV1.class.getPackage().getName()); - IdentityService identitySvc = new InMemoryIdentityService( - Arrays.asList(getMEGA_CORP_IDENTITY(), getDUMMY_CASH_ISSUER_IDENTITY(), getDUMMY_NOTARY_IDENTITY()), - Collections.emptySet(), - getDEV_TRUST_ROOT()); + IdentityService identitySvc = makeTestIdentityService(Arrays.asList(getMEGA_CORP_IDENTITY(), getDUMMY_CASH_ISSUER_IDENTITY(), getDUMMY_NOTARY_IDENTITY())); Pair databaseAndServices = makeTestDatabaseAndMockServices( Arrays.asList(getMEGA_CORP_KEY(), getDUMMY_NOTARY_KEY()), identitySvc, - cordappPackages); + cordappPackages, + getMEGA_CORP().getName()); issuerServices = new MockServices(cordappPackages, getDUMMY_CASH_ISSUER_NAME(), getDUMMY_CASH_ISSUER_KEY(), getBOC_KEY()); database = databaseAndServices.getFirst(); MockServices services = databaseAndServices.getSecond(); diff --git a/node/src/test/kotlin/net/corda/node/InteractiveShellTest.kt b/node/src/test/kotlin/net/corda/node/InteractiveShellTest.kt index 3f0a7d40c1..242536a172 100644 --- a/node/src/test/kotlin/net/corda/node/InteractiveShellTest.kt +++ b/node/src/test/kotlin/net/corda/node/InteractiveShellTest.kt @@ -11,13 +11,12 @@ import net.corda.core.internal.concurrent.openFuture import net.corda.core.messaging.FlowProgressHandleImpl import net.corda.core.utilities.ProgressTracker import net.corda.nodeapi.internal.persistence.DatabaseConfig -import net.corda.node.services.identity.InMemoryIdentityService import net.corda.node.shell.InteractiveShell import net.corda.node.internal.configureDatabase -import net.corda.testing.DEV_TRUST_ROOT import net.corda.testing.MEGA_CORP import net.corda.testing.MEGA_CORP_IDENTITY import net.corda.testing.node.MockServices +import net.corda.testing.node.makeTestIdentityService import net.corda.testing.rigorousMock import org.junit.After import org.junit.Before @@ -49,7 +48,7 @@ class InteractiveShellTest { override fun call() = a } - private val ids = InMemoryIdentityService(listOf(MEGA_CORP_IDENTITY), trustRoot = DEV_TRUST_ROOT) + private val ids = makeTestIdentityService(listOf(MEGA_CORP_IDENTITY)) private val om = JacksonSupport.createInMemoryMapper(ids, YAMLFactory()) private fun check(input: String, expected: String) { diff --git a/node/src/test/kotlin/net/corda/node/services/RPCUserServiceTest.kt b/node/src/test/kotlin/net/corda/node/services/RPCUserServiceTest.kt index 88bdae5579..0f54c85d1c 100644 --- a/node/src/test/kotlin/net/corda/node/services/RPCUserServiceTest.kt +++ b/node/src/test/kotlin/net/corda/node/services/RPCUserServiceTest.kt @@ -1,7 +1,7 @@ package net.corda.node.services -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import org.assertj.core.api.Assertions.assertThatThrownBy import org.junit.Test diff --git a/node/src/test/kotlin/net/corda/node/services/config/ConfigOperatorTests.kt b/node/src/test/kotlin/net/corda/node/services/config/ConfigOperatorTests.kt index 92f7340b16..8178b88c48 100644 --- a/node/src/test/kotlin/net/corda/node/services/config/ConfigOperatorTests.kt +++ b/node/src/test/kotlin/net/corda/node/services/config/ConfigOperatorTests.kt @@ -1,7 +1,7 @@ package net.corda.node.services.config import com.typesafe.config.ConfigFactory -import net.corda.nodeapi.config.toProperties +import net.corda.nodeapi.internal.config.toProperties import org.junit.Test import kotlin.test.assertEquals diff --git a/node/src/test/kotlin/net/corda/node/services/events/NodeSchedulerServiceTest.kt b/node/src/test/kotlin/net/corda/node/services/events/NodeSchedulerServiceTest.kt index 1864d716e7..857f9ded5c 100644 --- a/node/src/test/kotlin/net/corda/node/services/events/NodeSchedulerServiceTest.kt +++ b/node/src/test/kotlin/net/corda/node/services/events/NodeSchedulerServiceTest.kt @@ -13,13 +13,10 @@ import net.corda.core.identity.CordaX500Name import net.corda.core.identity.Party import net.corda.core.node.NodeInfo import net.corda.core.node.ServiceHub -import net.corda.core.node.StatesToRecord import net.corda.core.serialization.SingletonSerializeAsToken -import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.TransactionBuilder import net.corda.core.utilities.days import net.corda.node.internal.FlowStarterImpl -import net.corda.node.internal.StateLoaderImpl import net.corda.node.internal.cordapp.CordappLoader import net.corda.node.internal.cordapp.CordappProviderImpl import net.corda.node.services.api.MonitoringService @@ -45,7 +42,6 @@ import org.junit.Before import org.junit.Rule import org.junit.Test import java.nio.file.Paths -import java.security.PublicKey import java.time.Clock import java.time.Instant import java.util.concurrent.CountDownLatch @@ -95,31 +91,26 @@ class NodeSchedulerServiceTest : SingletonSerializeAsToken() { calls = 0 val dataSourceProps = makeTestDataSourceProperties() database = configureDatabase(dataSourceProps, DatabaseConfig(), rigorousMock()) - val identityService = InMemoryIdentityService(trustRoot = DEV_TRUST_ROOT) + val identityService = makeTestIdentityService() kms = MockKeyManagementService(identityService, ALICE_KEY) val configuration = testNodeConfiguration(Paths.get("."), CordaX500Name("Alice", "London", "GB")) val validatedTransactions = MockTransactionStorage() - val stateLoader = StateLoaderImpl(validatedTransactions) database.transaction { services = rigorousMock().also { doReturn(configuration).whenever(it).configuration doReturn(MonitoringService(MetricRegistry())).whenever(it).monitoringService doReturn(validatedTransactions).whenever(it).validatedTransactions doReturn(NetworkMapCacheImpl(MockNetworkMapCache(database), identityService)).whenever(it).networkMapCache - doCallRealMethod().whenever(it).signInitialTransaction(any(), any()) doReturn(myInfo).whenever(it).myInfo doReturn(kms).whenever(it).keyManagementService doReturn(CordappProviderImpl(CordappLoader.createWithTestPackages(listOf("net.corda.testing.contracts")), MockAttachmentStorage())).whenever(it).cordappProvider - doCallRealMethod().whenever(it).recordTransactions(any(), any()) - doCallRealMethod().whenever(it).recordTransactions(any>()) - doCallRealMethod().whenever(it).recordTransactions(any(), anyVararg()) - doReturn(NodeVaultService(testClock, kms, stateLoader, database.hibernateConfig)).whenever(it).vaultService + doReturn(NodeVaultService(testClock, kms, validatedTransactions, database.hibernateConfig)).whenever(it).vaultService doReturn(this@NodeSchedulerServiceTest).whenever(it).testReference } smmExecutor = AffinityExecutor.ServiceAffinityExecutor("test", 1) mockSMM = StateMachineManagerImpl(services, DBCheckpointStorage(), smmExecutor, database, newSecureRandom()) - scheduler = NodeSchedulerService(testClock, database, FlowStarterImpl(smmExecutor, mockSMM), stateLoader, schedulerGatedExecutor, serverThread = smmExecutor) + scheduler = NodeSchedulerService(testClock, database, FlowStarterImpl(smmExecutor, mockSMM), validatedTransactions, schedulerGatedExecutor, serverThread = smmExecutor) mockSMM.changes.subscribe { change -> if (change is StateMachineManager.Change.Removed && mockSMM.allStateMachines.isEmpty()) { smmHasRemovedAllFlows.countDown() diff --git a/node/src/test/kotlin/net/corda/node/services/identity/InMemoryIdentityServiceTests.kt b/node/src/test/kotlin/net/corda/node/services/identity/InMemoryIdentityServiceTests.kt index 85857636dd..9ed1ed2a4a 100644 --- a/node/src/test/kotlin/net/corda/node/services/identity/InMemoryIdentityServiceTests.kt +++ b/node/src/test/kotlin/net/corda/node/services/identity/InMemoryIdentityServiceTests.kt @@ -23,9 +23,13 @@ import kotlin.test.assertNull * Tests for the in memory identity service. */ class InMemoryIdentityServiceTests { + companion object { + private fun createService(vararg identities: PartyAndCertificate) = InMemoryIdentityService(identities.toSet(), DEV_TRUST_ROOT) + } + @Test fun `get all identities`() { - val service = InMemoryIdentityService(trustRoot = DEV_TRUST_ROOT) + val service = createService() // Nothing registered, so empty set assertNull(service.getAllIdentities().firstOrNull()) @@ -43,7 +47,7 @@ class InMemoryIdentityServiceTests { @Test fun `get identity by key`() { - val service = InMemoryIdentityService(trustRoot = DEV_TRUST_ROOT) + val service = createService() assertNull(service.partyFromKey(ALICE_PUBKEY)) service.verifyAndRegisterIdentity(ALICE_IDENTITY) assertEquals(ALICE, service.partyFromKey(ALICE_PUBKEY)) @@ -52,13 +56,13 @@ class InMemoryIdentityServiceTests { @Test fun `get identity by name with no registered identities`() { - val service = InMemoryIdentityService(trustRoot = DEV_TRUST_ROOT) + val service = createService() assertNull(service.wellKnownPartyFromX500Name(ALICE.name)) } @Test fun `get identity by substring match`() { - val service = InMemoryIdentityService(trustRoot = DEV_TRUST_ROOT) + val service = createService() service.verifyAndRegisterIdentity(ALICE_IDENTITY) service.verifyAndRegisterIdentity(BOB_IDENTITY) val alicente = getTestPartyAndCertificate(CordaX500Name(organisation = "Alicente Worldwide", locality = "London", country = "GB"), generateKeyPair().public) @@ -70,7 +74,7 @@ class InMemoryIdentityServiceTests { @Test fun `get identity by name`() { - val service = InMemoryIdentityService(trustRoot = DEV_TRUST_ROOT) + val service = createService() val identities = listOf("Org A", "Org B", "Org C") .map { getTestPartyAndCertificate(CordaX500Name(organisation = it, locality = "London", country = "GB"), generateKeyPair().public) } assertNull(service.wellKnownPartyFromX500Name(identities.first().name)) @@ -87,7 +91,7 @@ class InMemoryIdentityServiceTests { val rootKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME) val rootCert = X509Utilities.createSelfSignedCACertificate(ALICE.name, rootKey) val txKey = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME) - val service = InMemoryIdentityService(trustRoot = DEV_TRUST_ROOT) + val service = createService() // TODO: Generate certificate with an EdDSA key rather than ECDSA val identity = Party(rootCert.cert) val txIdentity = AnonymousParty(txKey.public) @@ -108,7 +112,7 @@ class InMemoryIdentityServiceTests { val (_, bobTxIdentity) = createParty(ALICE.name, DEV_CA) // Now we have identities, construct the service and let it know about both - val service = InMemoryIdentityService(setOf(alice), emptySet(), DEV_TRUST_ROOT) + val service = createService(alice) service.verifyAndRegisterIdentity(aliceTxIdentity) var actual = service.certificateFromKey(aliceTxIdentity.party.owningKey) @@ -131,8 +135,7 @@ class InMemoryIdentityServiceTests { val (bob, anonymousBob) = createParty(BOB.name, DEV_CA) // Now we have identities, construct the service and let it know about both - val service = InMemoryIdentityService(setOf(alice, bob), emptySet(), DEV_TRUST_ROOT) - + val service = createService(alice, bob) service.verifyAndRegisterIdentity(anonymousAlice) service.verifyAndRegisterIdentity(anonymousBob) @@ -168,7 +171,7 @@ class InMemoryIdentityServiceTests { */ @Test fun `deanonymising a well known identity should return the identity`() { - val service = InMemoryIdentityService(trustRoot = DEV_TRUST_ROOT) + val service = createService() val expected = ALICE service.verifyAndRegisterIdentity(ALICE_IDENTITY) val actual = service.wellKnownPartyFromAnonymous(expected) @@ -180,7 +183,7 @@ class InMemoryIdentityServiceTests { */ @Test fun `deanonymising a false well known identity should return null`() { - val service = InMemoryIdentityService(trustRoot = DEV_TRUST_ROOT) + val service = createService() val notAlice = Party(ALICE.name, generateKeyPair().public) service.verifyAndRegisterIdentity(ALICE_IDENTITY) val actual = service.wellKnownPartyFromAnonymous(notAlice) diff --git a/node/src/test/kotlin/net/corda/node/services/identity/PersistentIdentityServiceTests.kt b/node/src/test/kotlin/net/corda/node/services/identity/PersistentIdentityServiceTests.kt index f3185b58eb..0650e74486 100644 --- a/node/src/test/kotlin/net/corda/node/services/identity/PersistentIdentityServiceTests.kt +++ b/node/src/test/kotlin/net/corda/node/services/identity/PersistentIdentityServiceTests.kt @@ -10,13 +10,16 @@ import net.corda.core.internal.cert import net.corda.core.internal.toX509CertHolder import net.corda.core.node.services.IdentityService import net.corda.core.node.services.UnknownAnonymousPartyException +import net.corda.node.internal.configureDatabase import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair import net.corda.nodeapi.internal.crypto.CertificateType import net.corda.nodeapi.internal.crypto.X509CertificateFactory import net.corda.nodeapi.internal.crypto.X509Utilities import net.corda.nodeapi.internal.persistence.CordaPersistence +import net.corda.nodeapi.internal.persistence.DatabaseConfig import net.corda.testing.* -import net.corda.testing.node.MockServices +import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties +import net.corda.testing.node.makeTestIdentityService import org.junit.After import org.junit.Before import org.junit.Test @@ -29,15 +32,12 @@ import kotlin.test.assertNull */ class PersistentIdentityServiceTests { private lateinit var database: CordaPersistence - private lateinit var services: MockServices private lateinit var identityService: IdentityService @Before fun setup() { - val databaseAndServices = MockServices.makeTestDatabaseAndMockServices(keys = emptyList(), identityService = PersistentIdentityService(DEV_TRUST_ROOT)) - database = databaseAndServices.first - services = databaseAndServices.second - identityService = services.identityService + identityService = PersistentIdentityService(DEV_TRUST_ROOT) + database = configureDatabase(makeTestDataSourceProperties(), DatabaseConfig(), identityService) } @After @@ -266,7 +266,7 @@ class PersistentIdentityServiceTests { */ @Test fun `deanonymising a well known identity should return the identity`() { - val service = InMemoryIdentityService(trustRoot = DEV_TRUST_ROOT) + val service = makeTestIdentityService() val expected = ALICE service.verifyAndRegisterIdentity(ALICE_IDENTITY) val actual = service.wellKnownPartyFromAnonymous(expected) @@ -278,7 +278,7 @@ class PersistentIdentityServiceTests { */ @Test fun `deanonymising a false well known identity should return null`() { - val service = InMemoryIdentityService(trustRoot = DEV_TRUST_ROOT) + val service = makeTestIdentityService() val notAlice = Party(ALICE.name, generateKeyPair().public) service.verifyAndRegisterIdentity(ALICE_IDENTITY) val actual = service.wellKnownPartyFromAnonymous(notAlice) diff --git a/node/src/test/kotlin/net/corda/node/services/network/NetworkMapUpdaterTest.kt b/node/src/test/kotlin/net/corda/node/services/network/NetworkMapUpdaterTest.kt index 3390d32968..f4c4e4ee41 100644 --- a/node/src/test/kotlin/net/corda/node/services/network/NetworkMapUpdaterTest.kt +++ b/node/src/test/kotlin/net/corda/node/services/network/NetworkMapUpdaterTest.kt @@ -51,7 +51,7 @@ class NetworkMapUpdaterTest { val networkMapClient = mock() val scheduler = TestScheduler() - val fileWatcher = NodeInfoWatcher(baseDir, scheduler = scheduler) + val fileWatcher = NodeInfoWatcher(baseDir, scheduler) val updater = NetworkMapUpdater(networkMapCache, fileWatcher, networkMapClient) // Publish node info for the first time. @@ -100,7 +100,7 @@ class NetworkMapUpdaterTest { } val scheduler = TestScheduler() - val fileWatcher = NodeInfoWatcher(baseDir, scheduler = scheduler) + val fileWatcher = NodeInfoWatcher(baseDir, scheduler) val updater = NetworkMapUpdater(networkMapCache, fileWatcher, networkMapClient) // Test adding new node. @@ -154,7 +154,7 @@ class NetworkMapUpdaterTest { } val scheduler = TestScheduler() - val fileWatcher = NodeInfoWatcher(baseDir, scheduler = scheduler) + val fileWatcher = NodeInfoWatcher(baseDir, scheduler) val updater = NetworkMapUpdater(networkMapCache, fileWatcher, networkMapClient) // Add all nodes. @@ -198,7 +198,7 @@ class NetworkMapUpdaterTest { val networkMapCache = getMockNetworkMapCache() val scheduler = TestScheduler() - val fileWatcher = NodeInfoWatcher(baseDir, scheduler = scheduler) + val fileWatcher = NodeInfoWatcher(baseDir, scheduler) val updater = NetworkMapUpdater(networkMapCache, fileWatcher, null) // Not subscribed yet. diff --git a/node/src/test/kotlin/net/corda/node/services/persistence/DBTransactionStorageTests.kt b/node/src/test/kotlin/net/corda/node/services/persistence/DBTransactionStorageTests.kt index f70118e16a..f955fd92d0 100644 --- a/node/src/test/kotlin/net/corda/node/services/persistence/DBTransactionStorageTests.kt +++ b/node/src/test/kotlin/net/corda/node/services/persistence/DBTransactionStorageTests.kt @@ -5,20 +5,14 @@ import net.corda.core.crypto.Crypto import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SignatureMetadata import net.corda.core.crypto.TransactionSignature -import net.corda.core.node.StatesToRecord import net.corda.core.toFuture import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.WireTransaction -import net.corda.node.services.api.VaultServiceInternal -import net.corda.node.services.schema.HibernateObserver -import net.corda.node.services.schema.NodeSchemaService import net.corda.node.services.transactions.PersistentUniquenessProvider -import net.corda.node.services.vault.NodeVaultService import net.corda.node.internal.configureDatabase import net.corda.nodeapi.internal.persistence.CordaPersistence import net.corda.nodeapi.internal.persistence.DatabaseConfig import net.corda.testing.* -import net.corda.testing.node.MockServices import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties import org.assertj.core.api.Assertions.assertThat import org.junit.After @@ -35,32 +29,11 @@ class DBTransactionStorageTests { private lateinit var database: CordaPersistence private lateinit var transactionStorage: DBTransactionStorage - private lateinit var services: MockServices - @Before fun setUp() { LogHelper.setLevel(PersistentUniquenessProvider::class) val dataSourceProps = makeTestDataSourceProperties() - val schemaService = NodeSchemaService() - database = configureDatabase(dataSourceProps, DatabaseConfig(), rigorousMock(), schemaService) - database.transaction { - services = object : MockServices(BOB_KEY) { - override val vaultService: VaultServiceInternal - get() { - val vaultService = NodeVaultService(clock, keyManagementService, stateLoader, database.hibernateConfig) - hibernatePersister = HibernateObserver.install(vaultService.rawUpdates, database.hibernateConfig, schemaService) - return vaultService - } - - override fun recordTransactions(txs: Iterable) { - for (stx in txs) { - validatedTransactions.addTransaction(stx) - } - // Refactored to use notifyAll() as we have no other unit test for that method with multiple transactions. - vaultService.notifyAll(StatesToRecord.ONLY_RELEVANT, txs.map { it.tx }) - } - } - } + database = configureDatabase(dataSourceProps, DatabaseConfig(), rigorousMock()) newTransactionStorage() } diff --git a/node/src/test/kotlin/net/corda/node/services/vault/NodeVaultServiceTest.kt b/node/src/test/kotlin/net/corda/node/services/vault/NodeVaultServiceTest.kt index e8dbd4be40..94fae003e2 100644 --- a/node/src/test/kotlin/net/corda/node/services/vault/NodeVaultServiceTest.kt +++ b/node/src/test/kotlin/net/corda/node/services/vault/NodeVaultServiceTest.kt @@ -38,6 +38,7 @@ import net.corda.nodeapi.internal.persistence.CordaPersistence import net.corda.testing.* import net.corda.testing.contracts.VaultFiller import net.corda.testing.node.MockServices +import net.corda.testing.node.makeTestIdentityService import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThatExceptionOfType import org.junit.After @@ -72,7 +73,11 @@ class NodeVaultServiceTest { @Before fun setUp() { LogHelper.setLevel(NodeVaultService::class) - val databaseAndServices = MockServices.makeTestDatabaseAndMockServices(cordappPackages = cordappPackages) + val databaseAndServices = MockServices.makeTestDatabaseAndMockServices( + listOf(MEGA_CORP_KEY), + makeTestIdentityService(listOf(MEGA_CORP_IDENTITY, MINI_CORP_IDENTITY, DUMMY_CASH_ISSUER_IDENTITY, DUMMY_NOTARY_IDENTITY)), + cordappPackages, + MEGA_CORP.name) database = databaseAndServices.first services = databaseAndServices.second vaultFiller = VaultFiller(services, DUMMY_NOTARY, DUMMY_NOTARY_KEY) diff --git a/node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt b/node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt index 87cb6c5258..c9e23d69f5 100644 --- a/node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt +++ b/node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt @@ -35,6 +35,7 @@ import net.corda.testing.* import net.corda.testing.contracts.* import net.corda.testing.node.MockServices import net.corda.testing.node.MockServices.Companion.makeTestDatabaseAndMockServices +import net.corda.testing.node.makeTestIdentityService import net.corda.testing.schemas.DummyLinearStateSchemaV1 import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThatThrownBy @@ -79,8 +80,11 @@ open class VaultQueryTests { @Before open fun setUp() { // register additional identities - val databaseAndServices = makeTestDatabaseAndMockServices(keys = listOf(MEGA_CORP_KEY, DUMMY_NOTARY_KEY), - cordappPackages = cordappPackages) + val databaseAndServices = makeTestDatabaseAndMockServices( + listOf(MEGA_CORP_KEY, DUMMY_NOTARY_KEY), + makeTestIdentityService(listOf(MEGA_CORP_IDENTITY, MINI_CORP_IDENTITY, DUMMY_CASH_ISSUER_IDENTITY, DUMMY_NOTARY_IDENTITY)), + cordappPackages, + MEGA_CORP.name) database = databaseAndServices.first services = databaseAndServices.second vaultFiller = VaultFiller(services, DUMMY_NOTARY, DUMMY_NOTARY_KEY) diff --git a/node/src/test/kotlin/net/corda/node/services/vault/VaultWithCashTest.kt b/node/src/test/kotlin/net/corda/node/services/vault/VaultWithCashTest.kt index 862a420a63..733082b183 100644 --- a/node/src/test/kotlin/net/corda/node/services/vault/VaultWithCashTest.kt +++ b/node/src/test/kotlin/net/corda/node/services/vault/VaultWithCashTest.kt @@ -29,6 +29,7 @@ import net.corda.testing.* import net.corda.testing.contracts.* import net.corda.testing.node.MockServices import net.corda.testing.node.MockServices.Companion.makeTestDatabaseAndMockServices +import net.corda.testing.node.makeTestIdentityService import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThatThrownBy import org.junit.After @@ -60,7 +61,11 @@ class VaultWithCashTest { @Before fun setUp() { LogHelper.setLevel(VaultWithCashTest::class) - val databaseAndServices = makeTestDatabaseAndMockServices(cordappPackages = cordappPackages, keys = listOf(generateKeyPair(), DUMMY_NOTARY_KEY)) + val databaseAndServices = makeTestDatabaseAndMockServices( + listOf(generateKeyPair(), DUMMY_NOTARY_KEY), + makeTestIdentityService(listOf(MEGA_CORP_IDENTITY, MINI_CORP_IDENTITY, DUMMY_CASH_ISSUER_IDENTITY, DUMMY_NOTARY_IDENTITY)), + cordappPackages, + MEGA_CORP.name) database = databaseAndServices.first services = databaseAndServices.second vaultFiller = VaultFiller(services, DUMMY_NOTARY, DUMMY_NOTARY_KEY) diff --git a/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/contracts/CommercialPaperTests.kt b/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/contracts/CommercialPaperTests.kt index e94ec7e72f..455d2ee71e 100644 --- a/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/contracts/CommercialPaperTests.kt +++ b/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/contracts/CommercialPaperTests.kt @@ -14,6 +14,7 @@ import net.corda.core.utilities.days import net.corda.core.utilities.seconds import net.corda.testing.* import net.corda.testing.node.MockServices +import net.corda.testing.node.makeTestIdentityService import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @@ -216,7 +217,10 @@ class CommercialPaperTestsGeneric { // @Test fun `issue move and then redeem`() = withTestSerialization{ - val aliceDatabaseAndServices = MockServices.makeTestDatabaseAndMockServices(keys = listOf(ALICE_KEY)) + val aliceDatabaseAndServices = MockServices.makeTestDatabaseAndMockServices( + listOf(ALICE_KEY), + makeTestIdentityService(listOf(MEGA_CORP_IDENTITY, MINI_CORP_IDENTITY, DUMMY_CASH_ISSUER_IDENTITY, DUMMY_NOTARY_IDENTITY)), + initialIdentityName = MEGA_CORP.name) val databaseAlice = aliceDatabaseAndServices.first aliceServices = aliceDatabaseAndServices.second aliceVaultService = aliceServices.vaultService @@ -226,7 +230,10 @@ class CommercialPaperTestsGeneric { aliceVaultService = aliceServices.vaultService } - val bigCorpDatabaseAndServices = MockServices.makeTestDatabaseAndMockServices(keys = listOf(BIG_CORP_KEY)) + val bigCorpDatabaseAndServices = MockServices.makeTestDatabaseAndMockServices( + listOf(BIG_CORP_KEY), + makeTestIdentityService(listOf(MEGA_CORP_IDENTITY, MINI_CORP_IDENTITY, DUMMY_CASH_ISSUER_IDENTITY, DUMMY_NOTARY_IDENTITY)), + initialIdentityName = MEGA_CORP.name) val databaseBigCorp = bigCorpDatabaseAndServices.first bigCorpServices = bigCorpDatabaseAndServices.second bigCorpVaultService = bigCorpServices.vaultService diff --git a/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/contracts/asset/CashTests.kt b/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/contracts/asset/CashTests.kt index bdef97ea64..348929124c 100644 --- a/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/contracts/asset/CashTests.kt +++ b/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/contracts/asset/CashTests.kt @@ -28,6 +28,7 @@ import net.corda.testing.contracts.DummyState import net.corda.testing.contracts.VaultFiller.Companion.calculateRandomlySizedAmounts import net.corda.testing.node.MockServices import net.corda.testing.node.MockServices.Companion.makeTestDatabaseAndMockServices +import net.corda.testing.node.makeTestIdentityService import org.junit.After import org.junit.Before import org.junit.Test @@ -104,7 +105,11 @@ class CashTests { fun setUp() = withTestSerialization { LogHelper.setLevel(NodeVaultService::class) megaCorpServices = MockServices(listOf("com.r3.corda.enterprise.perftestcordapp.contracts.asset","com.r3.corda.enterprise.perftestcordapp.schemas"), MEGA_CORP.name, MEGA_CORP_KEY) - val databaseAndServices = makeTestDatabaseAndMockServices(cordappPackages = listOf("com.r3.corda.enterprise.perftestcordapp.contracts.asset","com.r3.corda.enterprise.perftestcordapp.schemas"), keys = listOf(MINI_CORP_KEY, MEGA_CORP_KEY, OUR_KEY)) + val databaseAndServices = makeTestDatabaseAndMockServices( + listOf(MINI_CORP_KEY, MEGA_CORP_KEY, OUR_KEY), + makeTestIdentityService(listOf(MEGA_CORP_IDENTITY, MINI_CORP_IDENTITY, DUMMY_CASH_ISSUER_IDENTITY, DUMMY_NOTARY_IDENTITY)), + listOf("com.r3.corda.enterprise.perftestcordapp.contracts.asset", "com.r3.corda.enterprise.perftestcordapp.schemas"), + CordaX500Name("Me", "London", "GB")) database = databaseAndServices.first miniCorpServices = databaseAndServices.second diff --git a/samples/attachment-demo/src/integration-test/kotlin/net/corda/attachmentdemo/AttachmentDemoTest.kt b/samples/attachment-demo/src/integration-test/kotlin/net/corda/attachmentdemo/AttachmentDemoTest.kt index d1196aee0d..49ac9c993a 100644 --- a/samples/attachment-demo/src/integration-test/kotlin/net/corda/attachmentdemo/AttachmentDemoTest.kt +++ b/samples/attachment-demo/src/integration-test/kotlin/net/corda/attachmentdemo/AttachmentDemoTest.kt @@ -4,7 +4,9 @@ import net.corda.core.messaging.CordaRPCOps import net.corda.core.utilities.getOrThrow import net.corda.node.services.Permissions.Companion.invokeRpc import net.corda.node.services.Permissions.Companion.startFlow -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User +import net.corda.testing.DUMMY_BANK_A +import net.corda.testing.DUMMY_BANK_B import net.corda.testing.* import net.corda.testing.driver.PortAllocation import net.corda.testing.driver.driver diff --git a/samples/attachment-demo/src/main/kotlin/net/corda/attachmentdemo/Main.kt b/samples/attachment-demo/src/main/kotlin/net/corda/attachmentdemo/Main.kt index eafecb2fa8..9c3b8a2304 100644 --- a/samples/attachment-demo/src/main/kotlin/net/corda/attachmentdemo/Main.kt +++ b/samples/attachment-demo/src/main/kotlin/net/corda/attachmentdemo/Main.kt @@ -1,7 +1,7 @@ package net.corda.attachmentdemo import net.corda.core.internal.div -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.DUMMY_BANK_A import net.corda.testing.DUMMY_BANK_B import net.corda.testing.driver.driver diff --git a/samples/bank-of-corda-demo/src/integration-test/kotlin/net/corda/bank/BankOfCordaRPCClientTest.kt b/samples/bank-of-corda-demo/src/integration-test/kotlin/net/corda/bank/BankOfCordaRPCClientTest.kt index 861b47f2b2..88d7fc0347 100644 --- a/samples/bank-of-corda-demo/src/integration-test/kotlin/net/corda/bank/BankOfCordaRPCClientTest.kt +++ b/samples/bank-of-corda-demo/src/integration-test/kotlin/net/corda/bank/BankOfCordaRPCClientTest.kt @@ -10,7 +10,7 @@ import net.corda.finance.contracts.asset.Cash import net.corda.finance.flows.CashIssueAndPaymentFlow import net.corda.node.services.Permissions.Companion.invokeRpc import net.corda.node.services.Permissions.Companion.startFlow -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.* import net.corda.testing.driver.driver import org.junit.ClassRule diff --git a/samples/bank-of-corda-demo/src/main/kotlin/net/corda/bank/BankOfCordaCordform.kt b/samples/bank-of-corda-demo/src/main/kotlin/net/corda/bank/BankOfCordaCordform.kt index 24dda81869..6ac1baa176 100644 --- a/samples/bank-of-corda-demo/src/main/kotlin/net/corda/bank/BankOfCordaCordform.kt +++ b/samples/bank-of-corda-demo/src/main/kotlin/net/corda/bank/BankOfCordaCordform.kt @@ -13,7 +13,7 @@ import net.corda.core.utilities.NetworkHostAndPort import net.corda.node.services.Permissions.Companion.all import net.corda.node.services.config.NotaryConfig import net.corda.node.services.transactions.ValidatingNotaryService -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.BOC import net.corda.testing.internal.demorun.* import java.util.* diff --git a/samples/bank-of-corda-demo/src/main/kotlin/net/corda/bank/api/BankOfCordaClientApi.kt b/samples/bank-of-corda-demo/src/main/kotlin/net/corda/bank/api/BankOfCordaClientApi.kt index 85fe095d19..ef020df6ef 100644 --- a/samples/bank-of-corda-demo/src/main/kotlin/net/corda/bank/api/BankOfCordaClientApi.kt +++ b/samples/bank-of-corda-demo/src/main/kotlin/net/corda/bank/api/BankOfCordaClientApi.kt @@ -2,7 +2,6 @@ package net.corda.bank.api import net.corda.bank.api.BankOfCordaWebApi.IssueRequestParams import net.corda.client.rpc.CordaRPCClient -import net.corda.core.contracts.Amount import net.corda.core.messaging.startFlow import net.corda.core.transactions.SignedTransaction import net.corda.core.utilities.NetworkHostAndPort diff --git a/samples/irs-demo/src/integration-test/kotlin/net/corda/irs/IRSDemoTest.kt b/samples/irs-demo/src/integration-test/kotlin/net/corda/irs/IRSDemoTest.kt index 9771098324..4ca7816dd2 100644 --- a/samples/irs-demo/src/integration-test/kotlin/net/corda/irs/IRSDemoTest.kt +++ b/samples/irs-demo/src/integration-test/kotlin/net/corda/irs/IRSDemoTest.kt @@ -21,7 +21,7 @@ import net.corda.finance.plugin.registerFinanceJSONMappers import net.corda.irs.contract.InterestRateSwap import net.corda.irs.web.IrsDemoWebApplication import net.corda.node.services.config.NodeConfiguration -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.test.spring.springDriver import net.corda.testing.* import net.corda.testing.http.HttpApi @@ -115,7 +115,7 @@ class IRSDemoTest : IntegrationTest() { private fun runDateChange(nodeApi: HttpApi) { log.info("Running date change against ${nodeApi.root}") - assertThat(nodeApi.putJson("demodate", "\"$futureDate\"")).isTrue() + nodeApi.putJson("demodate", "\"$futureDate\"") } private fun runTrade(nodeApi: HttpApi, oracle: Party) { @@ -128,7 +128,7 @@ class IRSDemoTest : IntegrationTest() { private fun runUploadRates(nodeApi: HttpApi) { log.info("Running upload rates against ${nodeApi.root}") val fileContents = loadResourceFile("net/corda/irs/simulation/example.rates.txt") - assertThat(nodeApi.postPlain("fixes", fileContents)).isTrue() + nodeApi.postPlain("fixes", fileContents) } private fun loadResourceFile(filename: String): String { diff --git a/samples/irs-demo/web/src/test/kotlin/net/corda/irs/web/demo/IrsDemoClientApi.kt b/samples/irs-demo/web/src/test/kotlin/net/corda/irs/web/demo/IrsDemoClientApi.kt index 82e81de047..9bebc4481c 100644 --- a/samples/irs-demo/web/src/test/kotlin/net/corda/irs/web/demo/IrsDemoClientApi.kt +++ b/samples/irs-demo/web/src/test/kotlin/net/corda/irs/web/demo/IrsDemoClientApi.kt @@ -8,7 +8,7 @@ import org.apache.commons.io.IOUtils /** * Interface for communicating with nodes running the IRS demo. */ -class IRSDemoClientApi(private val hostAndPort: NetworkHostAndPort) { +class IRSDemoClientApi(hostAndPort: NetworkHostAndPort) { private val api = HttpApi.fromHostAndPort(hostAndPort, apiRoot) fun runTrade(tradeId: String, oracleName: CordaX500Name) { @@ -17,14 +17,14 @@ class IRSDemoClientApi(private val hostAndPort: NetworkHostAndPort) { api.postJson("deals", tradeFile) } - fun runDateChange(newDate: String): Boolean { - return api.putJson("demodate", "\"$newDate\"") + fun runDateChange(newDate: String) { + api.putJson("demodate", "\"$newDate\"") } // TODO: Add uploading of files to the HTTP API fun runUploadRates() { val fileContents = IOUtils.toString(Thread.currentThread().contextClassLoader.getResourceAsStream("net/corda/irs/simulation/example.rates.txt"), Charsets.UTF_8.name()) - check(api.postPlain("fixes", fileContents)) + api.postPlain("fixes", fileContents) println("Rates successfully uploaded!") } diff --git a/samples/network-visualiser/src/main/kotlin/net/corda/netmap/simulation/IRSSimulation.kt b/samples/network-visualiser/src/main/kotlin/net/corda/netmap/simulation/IRSSimulation.kt index 21ac207f72..af8525a222 100644 --- a/samples/network-visualiser/src/main/kotlin/net/corda/netmap/simulation/IRSSimulation.kt +++ b/samples/network-visualiser/src/main/kotlin/net/corda/netmap/simulation/IRSSimulation.kt @@ -21,10 +21,9 @@ import net.corda.finance.flows.TwoPartyDealFlow.Instigator import net.corda.finance.plugin.registerFinanceJSONMappers import net.corda.irs.contract.InterestRateSwap import net.corda.irs.flows.FixingFlow -import net.corda.node.services.identity.InMemoryIdentityService -import net.corda.testing.DEV_TRUST_ROOT import net.corda.testing.chooseIdentity import net.corda.testing.node.InMemoryMessagingNetwork +import net.corda.testing.node.makeTestIdentityService import net.corda.testing.startFlow import rx.Observable import java.time.LocalDate @@ -45,7 +44,7 @@ class IRSSimulation(networkSendManuallyPumped: Boolean, runAsync: Boolean, laten private val executeOnNextIteration = Collections.synchronizedList(LinkedList<() -> Unit>()) override fun startMainSimulation(): CompletableFuture { - om = JacksonSupport.createInMemoryMapper(InMemoryIdentityService((banks + regulators + ratesOracle).flatMap { it.started!!.info.legalIdentitiesAndCerts }, trustRoot = DEV_TRUST_ROOT)) + om = JacksonSupport.createInMemoryMapper(makeTestIdentityService((banks + regulators + ratesOracle).flatMap { it.started!!.info.legalIdentitiesAndCerts })) registerFinanceJSONMappers(om) return startIRSDealBetween(0, 1).thenCompose { diff --git a/samples/notary-demo/src/main/kotlin/net/corda/notarydemo/SingleNotaryCordform.kt b/samples/notary-demo/src/main/kotlin/net/corda/notarydemo/SingleNotaryCordform.kt index 23381b72d1..ea2366c953 100644 --- a/samples/notary-demo/src/main/kotlin/net/corda/notarydemo/SingleNotaryCordform.kt +++ b/samples/notary-demo/src/main/kotlin/net/corda/notarydemo/SingleNotaryCordform.kt @@ -4,7 +4,7 @@ import net.corda.cordform.CordformContext import net.corda.cordform.CordformDefinition import net.corda.node.services.Permissions.Companion.all import net.corda.node.services.config.NotaryConfig -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.ALICE import net.corda.testing.BOB import net.corda.testing.DUMMY_NOTARY diff --git a/samples/simm-valuation-demo/src/integration-test/kotlin/net/corda/vega/SimmValuationTest.kt b/samples/simm-valuation-demo/src/integration-test/kotlin/net/corda/vega/SimmValuationTest.kt index 808d28fcd6..fff2032368 100644 --- a/samples/simm-valuation-demo/src/integration-test/kotlin/net/corda/vega/SimmValuationTest.kt +++ b/samples/simm-valuation-demo/src/integration-test/kotlin/net/corda/vega/SimmValuationTest.kt @@ -42,7 +42,7 @@ class SimmValuationTest : IntegrationTest() { val nodeBParty = getPartyWithName(nodeAApi, nodeBLegalName) val nodeAParty = getPartyWithName(nodeBApi, nodeALegalName) - assertThat(createTradeBetween(nodeAApi, nodeBParty, testTradeId)).isTrue() + createTradeBetween(nodeAApi, nodeBParty, testTradeId) assertTradeExists(nodeBApi, nodeAParty, testTradeId) assertTradeExists(nodeAApi, nodeBParty, testTradeId) runValuationsBetween(nodeAApi, nodeBParty) @@ -59,10 +59,10 @@ class SimmValuationTest : IntegrationTest() { return partyApi.getJson("whoami") } - private fun createTradeBetween(partyApi: HttpApi, counterparty: PortfolioApi.ApiParty, tradeId: String): Boolean { + private fun createTradeBetween(partyApi: HttpApi, counterparty: PortfolioApi.ApiParty, tradeId: String) { val trade = SwapDataModel(tradeId, "desc", valuationDate, "EUR_FIXED_1Y_EURIBOR_3M", valuationDate, LocalDate.parse("2020-01-02"), BuySell.BUY, BigDecimal.valueOf(1000), BigDecimal.valueOf(0.1)) - return partyApi.putJson("${counterparty.id}/trades", trade) + partyApi.putJson("${counterparty.id}/trades", trade) } private fun assertTradeExists(partyApi: HttpApi, counterparty: PortfolioApi.ApiParty, tradeId: String) { diff --git a/samples/trader-demo/src/integration-test/kotlin/net/corda/traderdemo/TraderDemoTest.kt b/samples/trader-demo/src/integration-test/kotlin/net/corda/traderdemo/TraderDemoTest.kt index dbfc45e894..1534641e79 100644 --- a/samples/trader-demo/src/integration-test/kotlin/net/corda/traderdemo/TraderDemoTest.kt +++ b/samples/trader-demo/src/integration-test/kotlin/net/corda/traderdemo/TraderDemoTest.kt @@ -8,7 +8,11 @@ import net.corda.finance.flows.CashIssueFlow import net.corda.finance.flows.CashPaymentFlow import net.corda.node.services.Permissions.Companion.all import net.corda.node.services.Permissions.Companion.startFlow -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User +import net.corda.testing.BOC +import net.corda.testing.DUMMY_BANK_A +import net.corda.testing.DUMMY_BANK_B +import net.corda.testing.chooseIdentity import net.corda.testing.* import net.corda.testing.driver.NodeHandle import net.corda.testing.driver.driver diff --git a/samples/trader-demo/src/test/kotlin/net/corda/traderdemo/Main.kt b/samples/trader-demo/src/test/kotlin/net/corda/traderdemo/Main.kt index dce315e84e..b59890ab61 100644 --- a/samples/trader-demo/src/test/kotlin/net/corda/traderdemo/Main.kt +++ b/samples/trader-demo/src/test/kotlin/net/corda/traderdemo/Main.kt @@ -4,7 +4,7 @@ import net.corda.core.internal.div import net.corda.finance.flows.CashIssueFlow import net.corda.node.services.Permissions.Companion.all import net.corda.node.services.Permissions.Companion.startFlow -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.BOC import net.corda.testing.DUMMY_BANK_A import net.corda.testing.DUMMY_BANK_B diff --git a/testing/node-driver/src/integration-test/kotlin/net/corda/testing/FlowStackSnapshotTest.kt b/testing/node-driver/src/integration-test/kotlin/net/corda/testing/FlowStackSnapshotTest.kt index f33897854c..c6e01c4193 100644 --- a/testing/node-driver/src/integration-test/kotlin/net/corda/testing/FlowStackSnapshotTest.kt +++ b/testing/node-driver/src/integration-test/kotlin/net/corda/testing/FlowStackSnapshotTest.kt @@ -9,7 +9,7 @@ import net.corda.core.internal.read import net.corda.core.messaging.startFlow import net.corda.core.serialization.CordaSerializable import net.corda.node.services.Permissions.Companion.startFlow -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.driver.driver import net.corda.testing.node.MockNetwork import org.junit.Ignore diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/NodeTestUtils.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/NodeTestUtils.kt index ce353ee79d..e96340e1a8 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/NodeTestUtils.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/NodeTestUtils.kt @@ -2,7 +2,6 @@ package net.corda.testing -import com.nhaarman.mockito_kotlin.doCallRealMethod import com.nhaarman.mockito_kotlin.doReturn import com.nhaarman.mockito_kotlin.whenever import net.corda.core.context.Actor @@ -18,7 +17,7 @@ import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.seconds import net.corda.node.services.api.StartedNodeServices import net.corda.node.services.config.* -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.node.MockServices import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties import net.corda.testing.node.MockServices.Companion.makeTestDatabaseProperties @@ -72,11 +71,7 @@ fun testNodeConfiguration( doReturn(5).whenever(it).messageRedeliveryDelaySeconds doReturn(5.seconds.toMillis()).whenever(it).additionalNodeInfoPollingFrequencyMsec doReturn(null).whenever(it).devModeOptions - doCallRealMethod().whenever(it).certificatesDirectory - doCallRealMethod().whenever(it).trustStoreFile - doCallRealMethod().whenever(it).sslKeystore - doCallRealMethod().whenever(it).nodeKeystore - doReturn(EnterpriseConfiguration(MutualExclusionConfiguration(false, "", 20000, 40000))).whenever(it).enterpriseConfiguration + doReturn(EnterpriseConfiguration(MutualExclusionConfiguration(false, "", 20000, 40000))).whenever(it).enterpriseConfiguration //Enterprise only } } diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/driver/Driver.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/driver/Driver.kt index d8077fc978..51d0fa7266 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/driver/Driver.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/driver/Driver.kt @@ -24,15 +24,15 @@ import net.corda.core.utilities.* import net.corda.node.internal.Node import net.corda.node.internal.NodeStartup import net.corda.node.internal.StartedNode -import net.corda.node.internal.cordapp.CordappLoader import net.corda.node.services.Permissions.Companion.invokeRpc import net.corda.node.services.config.* import net.corda.node.utilities.ServiceIdentityGenerator import net.corda.nodeapi.NodeInfoFilesCopier -import net.corda.nodeapi.User -import net.corda.nodeapi.config.toConfig +import net.corda.nodeapi.internal.config.User +import net.corda.nodeapi.internal.config.toConfig import net.corda.nodeapi.internal.addShutdownHook import net.corda.testing.* +import net.corda.testing.internal.InProcessNode import net.corda.testing.internal.ProcessUtilities import net.corda.testing.node.ClusterSpec import net.corda.testing.node.MockServices.Companion.MOCK_VERSION_INFO @@ -941,12 +941,7 @@ class DriverDSL( // Write node.conf writeConfig(nodeConf.baseDirectory, "node.conf", config) // TODO pass the version in? - val node = Node( - nodeConf, - MOCK_VERSION_INFO, - initialiseSerialization = false, - cordappLoader = CordappLoader.createDefaultWithTestPackages(nodeConf, cordappPackages)) - .start() + val node = InProcessNode(nodeConf, MOCK_VERSION_INFO, cordappPackages).start() val nodeThread = thread(name = nodeConf.myLegalName.organisation) { node.internals.run() } diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/internal/NodeBasedTest.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/internal/NodeBasedTest.kt index 4bc03741a4..62f083a746 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/internal/NodeBasedTest.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/internal/NodeBasedTest.kt @@ -7,23 +7,26 @@ import net.corda.core.internal.createDirectories import net.corda.core.internal.div import net.corda.core.node.NodeInfo import net.corda.core.utilities.getOrThrow +import net.corda.node.VersionInfo import net.corda.node.internal.Node import net.corda.node.internal.StartedNode import net.corda.node.internal.cordapp.CordappLoader +import net.corda.node.services.config.* import net.corda.node.services.config.ConfigHelper import net.corda.node.services.config.configOf import net.corda.node.services.config.parseAsNodeConfiguration import net.corda.node.services.config.plus -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.IntegrationTest import net.corda.testing.SerializationEnvironmentRule import net.corda.testing.driver.addressMustNotBeBoundFuture import net.corda.testing.getFreeLocalPorts -import net.corda.testing.node.MockServices +import net.corda.testing.node.MockServices.Companion.MOCK_VERSION_INFO import org.apache.logging.log4j.Level import org.junit.After import org.junit.Rule import org.junit.rules.TemporaryFolder +import rx.internal.schedulers.CachedThreadScheduler import java.nio.file.Path import java.util.concurrent.Executors import kotlin.concurrent.thread @@ -91,11 +94,7 @@ abstract class NodeBasedTest(private val cordappPackages: List = emptyLi ) val parsedConfig = config.parseAsNodeConfiguration() - val node = Node( - parsedConfig, - MockServices.MOCK_VERSION_INFO.copy(platformVersion = platformVersion), - initialiseSerialization = false, - cordappLoader = CordappLoader.createDefaultWithTestPackages(parsedConfig, cordappPackages)).start() + val node = InProcessNode(parsedConfig, MOCK_VERSION_INFO.copy(platformVersion = platformVersion), cordappPackages).start() nodes += node ensureAllNetworkMapCachesHaveAllNodeInfos() thread(name = legalName.organisation) { @@ -118,3 +117,9 @@ abstract class NodeBasedTest(private val cordappPackages: List = emptyLi } } } + +class InProcessNode( + configuration: NodeConfiguration, versionInfo: VersionInfo, cordappPackages: List) : Node( + configuration, versionInfo, false, CordappLoader.createDefaultWithTestPackages(configuration, cordappPackages)) { + override fun getRxIoScheduler() = CachedThreadScheduler(testThreadFactory()).also { runOnStop += it::shutdown } +} diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/internal/RPCDriver.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/internal/RPCDriver.kt index 1b7c7c694f..33867e5ac4 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/internal/RPCDriver.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/internal/RPCDriver.kt @@ -23,7 +23,7 @@ import net.corda.node.services.messaging.RPCServerConfiguration import net.corda.nodeapi.ArtemisTcpTransport import net.corda.nodeapi.ConnectionDirection import net.corda.nodeapi.RPCApi -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.nodeapi.internal.serialization.KRYO_RPC_CLIENT_CONTEXT import net.corda.testing.driver.* import net.corda.testing.node.NotarySpec diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/internal/demorun/CordformUtils.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/internal/demorun/CordformUtils.kt index dcf0255a9a..9e566a0867 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/internal/demorun/CordformUtils.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/internal/demorun/CordformUtils.kt @@ -6,8 +6,8 @@ import net.corda.cordform.CordformDefinition import net.corda.cordform.CordformNode import net.corda.core.identity.CordaX500Name import net.corda.node.services.config.NotaryConfig -import net.corda.nodeapi.User -import net.corda.nodeapi.config.toConfig +import net.corda.nodeapi.internal.config.User +import net.corda.nodeapi.internal.config.toConfig fun CordformDefinition.node(configure: CordformNode.() -> Unit) { addNode { cordformNode -> cordformNode.configure() } diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/node/MockNode.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/node/MockNode.kt index ab1fad2184..5c1221f816 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/node/MockNode.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/node/MockNode.kt @@ -38,6 +38,7 @@ import net.corda.node.utilities.AffinityExecutor import net.corda.node.utilities.AffinityExecutor.ServiceAffinityExecutor import net.corda.nodeapi.internal.persistence.CordaPersistence import net.corda.testing.DUMMY_NOTARY +import net.corda.testing.internal.testThreadFactory import net.corda.testing.node.MockServices.Companion.MOCK_VERSION_INFO import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties import net.corda.testing.node.MockServices.Companion.makeTestDatabaseProperties @@ -45,6 +46,7 @@ import net.corda.testing.setGlobalSerialization import net.corda.testing.testNodeConfiguration import org.apache.activemq.artemis.utils.ReusableLatch import org.apache.sshd.common.util.security.SecurityUtils +import rx.internal.schedulers.CachedThreadScheduler import java.math.BigInteger import java.nio.file.Path import java.security.KeyPair @@ -246,6 +248,7 @@ class MockNetwork(defaultParameters: MockNetworkParameters = MockNetworkParamete return started } + override fun getRxIoScheduler() = CachedThreadScheduler(testThreadFactory()).also { runOnStop += it::shutdown } private fun advertiseNodeToNetwork(newNode: StartedNode) { mockNet.nodes .mapNotNull { it.started } diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/node/MockServices.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/node/MockServices.kt index 588551a145..f645788216 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/node/MockServices.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/node/MockServices.kt @@ -8,7 +8,6 @@ import net.corda.core.concurrent.CordaFuture import net.corda.core.cordapp.CordappProvider import net.corda.core.crypto.* import net.corda.core.flows.FlowLogic -import net.corda.core.flows.StateMachineRunId import net.corda.core.identity.CordaX500Name import net.corda.core.identity.PartyAndCertificate import net.corda.core.internal.concurrent.doneFuture @@ -22,18 +21,15 @@ import net.corda.core.serialization.SingletonSerializeAsToken import net.corda.core.toFuture import net.corda.core.transactions.SignedTransaction import net.corda.node.VersionInfo -import net.corda.node.internal.StateLoaderImpl import net.corda.node.internal.configureDatabase import net.corda.node.internal.cordapp.CordappLoader import net.corda.node.services.api.SchemaService -import net.corda.node.services.api.StateMachineRecordedTransactionMappingStorage import net.corda.node.services.api.VaultServiceInternal import net.corda.node.services.api.WritableTransactionStorage import net.corda.node.services.config.configOf import net.corda.node.services.identity.InMemoryIdentityService import net.corda.node.services.keys.freshCertificate import net.corda.node.services.keys.getSigner -import net.corda.node.services.persistence.InMemoryStateMachineRecordedTransactionMappingStorage import net.corda.node.services.schema.HibernateObserver import net.corda.node.services.schema.NodeSchemaService import net.corda.node.services.transactions.InMemoryTransactionVerifierService @@ -59,6 +55,7 @@ import java.sql.Connection import java.time.Clock import java.util.* +fun makeTestIdentityService(identities: Iterable = emptySet()) = InMemoryIdentityService(identities, DEV_TRUST_ROOT) /** * A singleton utility that only provides a mock identity, key and storage service. However, this is sufficient for * building chains of transactions and verifying them. It isn't sufficient for testing flows however. @@ -66,13 +63,10 @@ import java.util.* open class MockServices( cordappLoader: CordappLoader, override val validatedTransactions: WritableTransactionStorage, - protected val stateLoader: StateLoaderImpl = StateLoaderImpl(validatedTransactions), private val initialIdentityName: CordaX500Name = MEGA_CORP.name, vararg val keys: KeyPair -) : ServiceHub, StateLoader by stateLoader { +) : ServiceHub, StateLoader by validatedTransactions { companion object { - private val MOCK_IDENTITIES = listOf(MEGA_CORP_IDENTITY, MINI_CORP_IDENTITY, DUMMY_CASH_ISSUER_IDENTITY, DUMMY_NOTARY_IDENTITY) - @JvmStatic val MOCK_VERSION_INFO = VersionInfo(1, "Mock release", "Mock revision", "Mock Vendor") @@ -143,32 +137,16 @@ open class MockServices( return DatabaseConfig(transactionIsolationLevel = transactionIsolationLevel, schema = schema) } - private fun makeTestIdentityService() = InMemoryIdentityService(MOCK_IDENTITIES, trustRoot = DEV_TRUST_ROOT) - /** * Makes database and mock services appropriate for unit tests. - * @param keys a list of [KeyPair] instances to be used by [MockServices]. Defaults to [MEGA_CORP_KEY] - * @param createIdentityService a lambda function returning an instance of [IdentityService]. Defaults to [InMemoryIdentityService]. - * - * @return a pair where the first element is the instance of [CordaPersistence] and the second is [MockServices]. - */ - @JvmStatic - fun makeTestDatabaseAndMockServices(keys: List = listOf(MEGA_CORP_KEY), - identityService: IdentityService = makeTestIdentityService(), - cordappPackages: List = emptyList()): Pair { - return makeTestDatabaseAndMockServices(keys, identityService, cordappPackages, MEGA_CORP.name) - } - - /** - * Makes database and mock services appropriate for unit tests. - * @param keys a list of [KeyPair] instances to be used by [MockServices]. Defaults to [MEGA_CORP_KEY] - * @param createIdentityService a lambda function returning an instance of [IdentityService]. Defauts to [InMemoryIdentityService]. + * @param keys a list of [KeyPair] instances to be used by [MockServices]. + * @param identityService an instance of [IdentityService], see [makeTestIdentityService]. * @param initialIdentityName the name of the first (typically sole) identity the services will represent. * @return a pair where the first element is the instance of [CordaPersistence] and the second is [MockServices]. */ @JvmStatic - fun makeTestDatabaseAndMockServices(keys: List = listOf(MEGA_CORP_KEY), - identityService: IdentityService = makeTestIdentityService(), + fun makeTestDatabaseAndMockServices(keys: List, + identityService: IdentityService, cordappPackages: List = emptyList(), initialIdentityName: CordaX500Name): Pair { val cordappLoader = CordappLoader.createWithTestPackages(cordappPackages) @@ -181,9 +159,7 @@ open class MockServices( override val vaultService: VaultServiceInternal = makeVaultService(database.hibernateConfig, schemaService) override fun recordTransactions(statesToRecord: StatesToRecord, txs: Iterable) { - for (stx in txs) { - validatedTransactions.addTransaction(stx) - } + super.recordTransactions(statesToRecord, txs) // Refactored to use notifyAll() as we have no other unit test for that method with multiple transactions. vaultService.notifyAll(statesToRecord, txs.map { it.tx }) } @@ -204,16 +180,12 @@ open class MockServices( override fun recordTransactions(statesToRecord: StatesToRecord, txs: Iterable) { txs.forEach { - stateMachineRecordedTransactionMapping.addMapping(StateMachineRunId.createRandom(), it.id) - } - for (stx in txs) { - validatedTransactions.addTransaction(stx) + validatedTransactions.addTransaction(it) } } final override val attachments = MockAttachmentStorage() - val stateMachineRecordedTransactionMapping: StateMachineRecordedTransactionMappingStorage = MockStateMachineRecordedTransactionMappingStorage() - override val identityService: IdentityService = makeTestIdentityService() + override val identityService: IdentityService = makeTestIdentityService(listOf(MEGA_CORP_IDENTITY, MINI_CORP_IDENTITY, DUMMY_CASH_ISSUER_IDENTITY, DUMMY_NOTARY_IDENTITY)) override val keyManagementService: KeyManagementService by lazy { MockKeyManagementService(identityService, *keys) } override val vaultService: VaultService get() = throw UnsupportedOperationException() @@ -231,7 +203,7 @@ open class MockServices( lateinit var hibernatePersister: HibernateObserver fun makeVaultService(hibernateConfig: HibernateConfiguration, schemaService: SchemaService): VaultServiceInternal { - val vaultService = NodeVaultService(Clock.systemUTC(), keyManagementService, stateLoader, hibernateConfig) + val vaultService = NodeVaultService(Clock.systemUTC(), keyManagementService, validatedTransactions, hibernateConfig) hibernatePersister = HibernateObserver.install(vaultService.rawUpdates, hibernateConfig, schemaService) return vaultService } @@ -283,10 +255,6 @@ class MockKeyManagementService(val identityService: IdentityService, } } -class MockStateMachineRecordedTransactionMappingStorage( - val storage: StateMachineRecordedTransactionMappingStorage = InMemoryStateMachineRecordedTransactionMappingStorage() -) : StateMachineRecordedTransactionMappingStorage by storage - open class MockTransactionStorage : WritableTransactionStorage, SingletonSerializeAsToken() { override fun trackTransaction(id: SecureHash): CordaFuture { return txns[id]?.let { doneFuture(it) } ?: _updatesPublisher.filter { it.id == id }.toFuture() @@ -334,4 +302,4 @@ fun createMockCordaService(serviceHub: MockServices, serv } } return MockAppServiceHubImpl(serviceHub, serviceConstructor).serviceInstance -} +} \ No newline at end of file diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/node/NotarySpec.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/node/NotarySpec.kt index 852d3e899a..4618bb4717 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/node/NotarySpec.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/node/NotarySpec.kt @@ -3,7 +3,7 @@ package net.corda.testing.node import net.corda.core.identity.CordaX500Name import net.corda.node.services.config.VerifierType import net.corda.node.services.transactions.RaftValidatingNotaryService -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User data class NotarySpec( val name: CordaX500Name, diff --git a/testing/smoke-test-utils/src/main/kotlin/net/corda/smoketesting/NodeConfig.kt b/testing/smoke-test-utils/src/main/kotlin/net/corda/smoketesting/NodeConfig.kt index cc003edc6b..40ace413d3 100644 --- a/testing/smoke-test-utils/src/main/kotlin/net/corda/smoketesting/NodeConfig.kt +++ b/testing/smoke-test-utils/src/main/kotlin/net/corda/smoketesting/NodeConfig.kt @@ -6,7 +6,7 @@ import com.typesafe.config.ConfigRenderOptions import com.typesafe.config.ConfigValue import com.typesafe.config.ConfigValueFactory import net.corda.core.identity.CordaX500Name -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User class NodeConfig( val legalName: CordaX500Name, diff --git a/testing/test-utils/src/main/kotlin/net/corda/testing/CoreTestUtils.kt b/testing/test-utils/src/main/kotlin/net/corda/testing/CoreTestUtils.kt index 2fdb34673d..df5d85661c 100644 --- a/testing/test-utils/src/main/kotlin/net/corda/testing/CoreTestUtils.kt +++ b/testing/test-utils/src/main/kotlin/net/corda/testing/CoreTestUtils.kt @@ -16,7 +16,7 @@ import net.corda.core.utilities.OpaqueBytes import net.corda.core.utilities.loggerFor import net.corda.finance.contracts.asset.DUMMY_CASH_ISSUER import net.corda.node.services.config.configureDevKeyAndTrustStores -import net.corda.nodeapi.config.SSLConfiguration +import net.corda.nodeapi.internal.config.SSLConfiguration import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair import net.corda.nodeapi.internal.crypto.CertificateType import net.corda.nodeapi.internal.crypto.X509CertificateFactory @@ -24,6 +24,7 @@ import net.corda.nodeapi.internal.crypto.X509Utilities import net.corda.nodeapi.internal.serialization.amqp.AMQP_ENABLED import org.mockito.Mockito.mock import org.mockito.internal.stubbing.answers.ThrowsException +import java.lang.reflect.Modifier import java.nio.file.Files import java.security.KeyPair import java.security.PublicKey @@ -180,11 +181,16 @@ class UndefinedMockBehaviorException(message: String) : RuntimeException(message inline fun rigorousMock() = rigorousMock(T::class.java) /** - * Create a Mockito mock that has [UndefinedMockBehaviorException] as the default behaviour of all methods. - * @param T the type to mock. Note if you want to use [com.nhaarman.mockito_kotlin.doCallRealMethod] on a Kotlin interface, + * Create a Mockito mock that has [UndefinedMockBehaviorException] as the default behaviour of all abstract methods, + * and [org.mockito.invocation.InvocationOnMock.callRealMethod] as the default for all concrete methods. + * @param T the type to mock. Note if you want concrete methods of a Kotlin interface to be invoked, * it won't work unless you mock a (trivial) abstract implementation of that interface instead. */ fun rigorousMock(clazz: Class): T = mock(clazz) { - // Use ThrowsException to hack the stack trace, and lazily so we can customise the message: - ThrowsException(UndefinedMockBehaviorException("Please specify what should happen when '${it.method}' is called, or don't call it. Args: ${Arrays.toString(it.arguments)}")).answer(it) + if (Modifier.isAbstract(it.method.modifiers)) { + // Use ThrowsException to hack the stack trace, and lazily so we can customise the message: + ThrowsException(UndefinedMockBehaviorException("Please specify what should happen when '${it.method}' is called, or don't call it. Args: ${Arrays.toString(it.arguments)}")).answer(it) + } else { + it.callRealMethod() + } } diff --git a/testing/test-utils/src/main/kotlin/net/corda/testing/http/HttpApi.kt b/testing/test-utils/src/main/kotlin/net/corda/testing/http/HttpApi.kt index 7e948285dc..b0ffd991e8 100644 --- a/testing/test-utils/src/main/kotlin/net/corda/testing/http/HttpApi.kt +++ b/testing/test-utils/src/main/kotlin/net/corda/testing/http/HttpApi.kt @@ -1,6 +1,7 @@ package net.corda.testing.http import com.fasterxml.jackson.databind.ObjectMapper +import net.corda.client.jackson.JacksonSupport import net.corda.core.utilities.NetworkHostAndPort import java.net.URL @@ -29,16 +30,17 @@ class HttpApi(val root: URL, val mapper: ObjectMapper = defaultMapper) { /** * Send a GET request to the path on the API specified. */ - inline fun getJson(path: String, params: Map = mapOf()) = HttpUtils.getJson(URL(root, path), params, mapper) + inline fun getJson(path: String, params: Map = mapOf()): T { + return HttpUtils.getJson(URL(root, path), params, mapper) + } private fun toJson(any: Any) = any as? String ?: HttpUtils.defaultMapper.writeValueAsString(any) companion object { - fun fromHostAndPort(hostAndPort: NetworkHostAndPort, base: String, protocol: String = "http", mapper: ObjectMapper = defaultMapper): HttpApi - = HttpApi(URL("$protocol://$hostAndPort/$base/"), mapper) - - private val defaultMapper: ObjectMapper by lazy { - net.corda.client.jackson.JacksonSupport.createNonRpcMapper() + fun fromHostAndPort(hostAndPort: NetworkHostAndPort, base: String, protocol: String = "http", mapper: ObjectMapper = defaultMapper): HttpApi { + return HttpApi(URL("$protocol://$hostAndPort/$base/"), mapper) } + + private val defaultMapper: ObjectMapper by lazy { JacksonSupport.createNonRpcMapper() } } } diff --git a/testing/test-utils/src/main/kotlin/net/corda/testing/http/HttpUtils.kt b/testing/test-utils/src/main/kotlin/net/corda/testing/http/HttpUtils.kt index cf1af9b9ab..5e87f4e36b 100644 --- a/testing/test-utils/src/main/kotlin/net/corda/testing/http/HttpUtils.kt +++ b/testing/test-utils/src/main/kotlin/net/corda/testing/http/HttpUtils.kt @@ -5,7 +5,6 @@ import okhttp3.MediaType import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.RequestBody -import org.slf4j.LoggerFactory import java.io.IOException import java.net.URL import java.util.concurrent.TimeUnit @@ -14,8 +13,6 @@ import java.util.concurrent.TimeUnit * A small set of utilities for making HttpCalls, aimed at demos and tests. */ object HttpUtils { - private val logger = LoggerFactory.getLogger(javaClass) - private val client by lazy { OkHttpClient.Builder() .connectTimeout(5, TimeUnit.SECONDS) @@ -26,19 +23,19 @@ object HttpUtils { net.corda.client.jackson.JacksonSupport.createNonRpcMapper() } - fun putJson(url: URL, data: String): Boolean { + fun putJson(url: URL, data: String) { val body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), data) - return makeRequest(Request.Builder().url(url).header("Content-Type", "application/json").put(body).build()) + makeRequest(Request.Builder().url(url).header("Content-Type", "application/json").put(body).build()) } fun postJson(url: URL, data: String) { val body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), data) - makeExceptionalRequest(Request.Builder().url(url).header("Content-Type", "application/json").post(body).build()) + makeRequest(Request.Builder().url(url).header("Content-Type", "application/json").post(body).build()) } - fun postPlain(url: URL, data: String): Boolean { + fun postPlain(url: URL, data: String) { val body = RequestBody.create(MediaType.parse("text/plain; charset=utf-8"), data) - return makeRequest(Request.Builder().url(url).post(body).build()) + makeRequest(Request.Builder().url(url).post(body).build()) } inline fun getJson(url: URL, params: Map = mapOf(), mapper: ObjectMapper = defaultMapper): T { @@ -47,21 +44,10 @@ object HttpUtils { return mapper.readValue(parameterisedUrl, T::class.java) } - // TODO Move everything to use this instead of makeRequest - private fun makeExceptionalRequest(request: Request) { + private fun makeRequest(request: Request) { val response = client.newCall(request).execute() if (!response.isSuccessful) { throw IOException("${request.method()} to ${request.url()} returned a ${response.code()}: ${response.body().string()}") } } - - private fun makeRequest(request: Request): Boolean { - val response = client.newCall(request).execute() - - if (!response.isSuccessful) { - logger.error("Could not fulfill HTTP request of type ${request.method()} to ${request.url()}. Status Code: ${response.code()}. Message: ${response.body().string()}") - } - - return response.isSuccessful - } } diff --git a/testing/test-utils/src/main/kotlin/net/corda/testing/messaging/SimpleMQClient.kt b/testing/test-utils/src/main/kotlin/net/corda/testing/messaging/SimpleMQClient.kt index 705f150f89..235692b111 100644 --- a/testing/test-utils/src/main/kotlin/net/corda/testing/messaging/SimpleMQClient.kt +++ b/testing/test-utils/src/main/kotlin/net/corda/testing/messaging/SimpleMQClient.kt @@ -5,7 +5,7 @@ import net.corda.core.serialization.internal.nodeSerializationEnv import net.corda.core.utilities.NetworkHostAndPort import net.corda.nodeapi.ArtemisTcpTransport import net.corda.nodeapi.ConnectionDirection -import net.corda.nodeapi.config.SSLConfiguration +import net.corda.nodeapi.internal.config.SSLConfiguration import net.corda.testing.configureTestSSL import org.apache.activemq.artemis.api.core.client.* diff --git a/tools/demobench/src/main/kotlin/net/corda/demobench/model/InstallFactory.kt b/tools/demobench/src/main/kotlin/net/corda/demobench/model/InstallFactory.kt index f7709a7ada..2626eb882d 100644 --- a/tools/demobench/src/main/kotlin/net/corda/demobench/model/InstallFactory.kt +++ b/tools/demobench/src/main/kotlin/net/corda/demobench/model/InstallFactory.kt @@ -3,7 +3,7 @@ package net.corda.demobench.model import com.typesafe.config.Config import net.corda.core.internal.div import net.corda.core.utilities.NetworkHostAndPort -import net.corda.nodeapi.config.parseAs +import net.corda.nodeapi.internal.config.parseAs import tornadofx.* import java.io.IOException import java.nio.file.Files diff --git a/tools/demobench/src/main/kotlin/net/corda/demobench/model/NodeConfig.kt b/tools/demobench/src/main/kotlin/net/corda/demobench/model/NodeConfig.kt index 8ac6aeefdf..ae5b6deeb1 100644 --- a/tools/demobench/src/main/kotlin/net/corda/demobench/model/NodeConfig.kt +++ b/tools/demobench/src/main/kotlin/net/corda/demobench/model/NodeConfig.kt @@ -6,8 +6,8 @@ import net.corda.core.internal.copyToDirectory import net.corda.core.internal.createDirectories import net.corda.core.internal.div import net.corda.core.utilities.NetworkHostAndPort -import net.corda.nodeapi.User -import net.corda.nodeapi.config.toConfig +import net.corda.nodeapi.internal.config.User +import net.corda.nodeapi.internal.config.toConfig import java.nio.file.Path import java.nio.file.StandardCopyOption diff --git a/tools/demobench/src/test/kotlin/net/corda/demobench/model/NodeConfigTest.kt b/tools/demobench/src/test/kotlin/net/corda/demobench/model/NodeConfigTest.kt index 8ebcbaf2cc..0c9caca94a 100644 --- a/tools/demobench/src/test/kotlin/net/corda/demobench/model/NodeConfigTest.kt +++ b/tools/demobench/src/test/kotlin/net/corda/demobench/model/NodeConfigTest.kt @@ -5,8 +5,8 @@ import com.typesafe.config.ConfigValueFactory import net.corda.core.identity.CordaX500Name import net.corda.core.utilities.NetworkHostAndPort import net.corda.node.services.config.parseAsNodeConfiguration -import net.corda.nodeapi.User -import net.corda.nodeapi.config.toConfig +import net.corda.nodeapi.internal.config.User +import net.corda.nodeapi.internal.config.toConfig import net.corda.webserver.WebServerConfig import org.assertj.core.api.Assertions.assertThat import org.junit.Test diff --git a/tools/demobench/src/test/kotlin/net/corda/demobench/model/NodeControllerTest.kt b/tools/demobench/src/test/kotlin/net/corda/demobench/model/NodeControllerTest.kt index 21899794d8..18db310a5b 100644 --- a/tools/demobench/src/test/kotlin/net/corda/demobench/model/NodeControllerTest.kt +++ b/tools/demobench/src/test/kotlin/net/corda/demobench/model/NodeControllerTest.kt @@ -2,7 +2,7 @@ package net.corda.demobench.model import net.corda.core.identity.CordaX500Name import net.corda.core.utilities.NetworkHostAndPort -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import org.junit.Test import java.nio.file.Path import java.nio.file.Paths diff --git a/tools/explorer/src/main/kotlin/net/corda/explorer/ExplorerSimulation.kt b/tools/explorer/src/main/kotlin/net/corda/explorer/ExplorerSimulation.kt index f9a79e9cb2..17a8b7dd69 100644 --- a/tools/explorer/src/main/kotlin/net/corda/explorer/ExplorerSimulation.kt +++ b/tools/explorer/src/main/kotlin/net/corda/explorer/ExplorerSimulation.kt @@ -23,7 +23,7 @@ import net.corda.finance.flows.* import net.corda.finance.flows.CashExitFlow.ExitRequest import net.corda.finance.flows.CashIssueAndPaymentFlow.IssueAndPaymentRequest import net.corda.node.services.Permissions.Companion.startFlow -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import net.corda.testing.ALICE import net.corda.testing.BOB import net.corda.testing.driver.NodeHandle diff --git a/tools/jmeter/src/test/kotlin/com/r3/corda/jmeter/StartLocalPerfCorDapp.kt b/tools/jmeter/src/test/kotlin/com/r3/corda/jmeter/StartLocalPerfCorDapp.kt index 359398d44f..397cb0ba4e 100644 --- a/tools/jmeter/src/test/kotlin/com/r3/corda/jmeter/StartLocalPerfCorDapp.kt +++ b/tools/jmeter/src/test/kotlin/com/r3/corda/jmeter/StartLocalPerfCorDapp.kt @@ -1,7 +1,8 @@ package com.r3.corda.jmeter import net.corda.core.utilities.getOrThrow -import net.corda.nodeapi.User +import net.corda.node.services.Permissions +import net.corda.nodeapi.internal.config.User import net.corda.testing.DUMMY_NOTARY import net.corda.testing.node.NotarySpec import java.io.BufferedReader @@ -12,7 +13,7 @@ class StartLocalPerfCorDapp { @JvmStatic fun main(args: Array) { // Typically the RPC port of Bank A is 10004. - val demoUser = User("perf", "perf", setOf(net.corda.node.services.Permissions.Companion.all())) + val demoUser = User("perf", "perf", setOf(Permissions.all())) net.corda.testing.driver.driver(startNodesInProcess = false, waitForAllNodesToFinish = true, notarySpecs = listOf(NotarySpec(DUMMY_NOTARY.name, validating = false)), diff --git a/tools/loadtest/src/main/kotlin/net/corda/loadtest/LoadTestConfiguration.kt b/tools/loadtest/src/main/kotlin/net/corda/loadtest/LoadTestConfiguration.kt index 8e4a962002..9343605434 100644 --- a/tools/loadtest/src/main/kotlin/net/corda/loadtest/LoadTestConfiguration.kt +++ b/tools/loadtest/src/main/kotlin/net/corda/loadtest/LoadTestConfiguration.kt @@ -1,6 +1,6 @@ package net.corda.loadtest -import net.corda.nodeapi.User +import net.corda.nodeapi.internal.config.User import java.nio.file.Path import java.util.concurrent.ForkJoinPool diff --git a/tools/loadtest/src/main/kotlin/net/corda/loadtest/Main.kt b/tools/loadtest/src/main/kotlin/net/corda/loadtest/Main.kt index 0bd12ae78d..eb4e103c73 100644 --- a/tools/loadtest/src/main/kotlin/net/corda/loadtest/Main.kt +++ b/tools/loadtest/src/main/kotlin/net/corda/loadtest/Main.kt @@ -5,7 +5,7 @@ import com.typesafe.config.ConfigParseOptions import net.corda.loadtest.tests.StabilityTest import net.corda.loadtest.tests.crossCashTest import net.corda.loadtest.tests.selfIssueTest -import net.corda.nodeapi.config.parseAs +import net.corda.nodeapi.internal.config.parseAs import java.io.File /** diff --git a/verifier/src/integration-test/kotlin/net/corda/verifier/VerifierDriver.kt b/verifier/src/integration-test/kotlin/net/corda/verifier/VerifierDriver.kt index 04e46e395d..7d1b771830 100644 --- a/verifier/src/integration-test/kotlin/net/corda/verifier/VerifierDriver.kt +++ b/verifier/src/integration-test/kotlin/net/corda/verifier/VerifierDriver.kt @@ -20,8 +20,8 @@ import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.NODE_USER import net.corda.nodeapi.ArtemisTcpTransport import net.corda.nodeapi.ConnectionDirection import net.corda.nodeapi.VerifierApi -import net.corda.nodeapi.config.NodeSSLConfiguration -import net.corda.nodeapi.config.SSLConfiguration +import net.corda.nodeapi.internal.config.NodeSSLConfiguration +import net.corda.nodeapi.internal.config.SSLConfiguration import net.corda.testing.driver.* import net.corda.testing.internal.ProcessUtilities import net.corda.testing.node.NotarySpec diff --git a/verifier/src/main/kotlin/net/corda/verifier/Verifier.kt b/verifier/src/main/kotlin/net/corda/verifier/Verifier.kt index 7c04bf1ce9..5db494cad1 100644 --- a/verifier/src/main/kotlin/net/corda/verifier/Verifier.kt +++ b/verifier/src/main/kotlin/net/corda/verifier/Verifier.kt @@ -12,8 +12,8 @@ import net.corda.nodeapi.ArtemisTcpTransport.Companion.tcpTransport import net.corda.nodeapi.ConnectionDirection import net.corda.nodeapi.VerifierApi import net.corda.nodeapi.VerifierApi.VERIFICATION_REQUESTS_QUEUE_NAME -import net.corda.nodeapi.config.NodeSSLConfiguration -import net.corda.nodeapi.config.getValue +import net.corda.nodeapi.internal.config.NodeSSLConfiguration +import net.corda.nodeapi.internal.config.getValue import net.corda.nodeapi.internal.addShutdownHook import net.corda.nodeapi.internal.serialization.* import net.corda.nodeapi.internal.serialization.amqp.AbstractAMQPSerializationScheme diff --git a/webserver/src/main/kotlin/net/corda/webserver/WebServerConfig.kt b/webserver/src/main/kotlin/net/corda/webserver/WebServerConfig.kt index 53522b8399..b3be74b11b 100644 --- a/webserver/src/main/kotlin/net/corda/webserver/WebServerConfig.kt +++ b/webserver/src/main/kotlin/net/corda/webserver/WebServerConfig.kt @@ -2,9 +2,9 @@ package net.corda.webserver import com.typesafe.config.Config import net.corda.core.utilities.NetworkHostAndPort -import net.corda.nodeapi.User -import net.corda.nodeapi.config.NodeSSLConfiguration -import net.corda.nodeapi.config.getValue +import net.corda.nodeapi.internal.config.User +import net.corda.nodeapi.internal.config.NodeSSLConfiguration +import net.corda.nodeapi.internal.config.getValue import java.nio.file.Path /**