From 729aa65e7f21e5e56e869d5cf7914ff771e405a2 Mon Sep 17 00:00:00 2001 From: josecoll Date: Sat, 13 Jan 2018 11:00:01 +0000 Subject: [PATCH] Merge from R3 Corda 3.0 Dev Preview release branch to master --- build.gradle | 10 +- constants.properties | 2 +- .../net/corda/core/utilities/ByteArrays.kt | 6 +- docs/source/_static/versions | 13 +- .../_templates/layout_for_doc_website.html | 2 +- docs/source/api-persistence.rst | 4 +- docs/source/changelog.rst | 986 +----------------- docs/source/clientrpc.rst | 4 + docs/source/conf.py | 6 +- docs/source/corda-configuration-file.rst | 28 +- docs/source/cordapp-build-systems.rst | 26 +- docs/source/generating-a-node.rst | 6 +- docs/source/hello-world-running.rst | 6 +- docs/source/network-map.rst | 126 ++- docs/source/node-administration.rst | 2 + docs/source/node-database.rst | 58 +- docs/source/node-explorer.rst | 28 +- docs/source/release-notes.rst | 419 +++----- docs/source/running-a-node.rst | 10 + docs/source/running-doorman.rst | 2 +- docs/source/serialization.rst | 93 +- docs/source/shell.rst | 2 + docs/source/tutorial-clientrpc-api.rst | 14 +- docs/source/upgrade-notes.rst | 401 ++++++- .../kotlin/net/corda/plugins/CordappPlugin.kt | 4 +- .../kotlin/net/corda/plugins/Cordformation.kt | 3 +- .../src/main/kotlin/net/corda/plugins/Node.kt | 3 +- network-management/README.md | 4 +- .../PersistentCertificateRequestStorage.kt | 2 +- .../doorman/webservice/NodeInfoWebService.kt | 6 +- .../hsm/configuration/Configuration.kt | 2 +- .../network-manager.changelog-init.xml | 1 + .../PersitenceNodeInfoStorageTest.kt} | 0 .../common/signer/NetworkMapSignerTest.kt | 1 + .../nodeapi/internal/crypto/X509Utilities.kt | 2 - .../serialization/amqp/EvolutionSerializer.kt | 2 +- .../serialization/amqp/ObjectSerializer.kt | 2 + .../serialization/amqp/PropertySerializer.kt | 100 +- .../serialization/amqp/SerializationHelper.kt | 69 +- .../serialization/amqp/SerializerFactory.kt | 2 + .../amqp/custom/ThrowableSerializer.kt | 2 +- .../amqp/JavaPrivatePropertyTests.java | 79 ++ .../serialization/amqp/AMQPTestUtils.kt | 2 - .../amqp/PrivatePropertyTests.kt | 117 +++ .../carpenter/ClassCarpenterTestUtils.kt | 9 +- node/capsule/build.gradle | 4 +- .../node/services/MySQLNotaryServiceTests.kt | 8 +- .../services/messaging/P2PMessagingTest.kt | 5 + .../net/corda/node/internal/AbstractNode.kt | 2 +- .../kotlin/net/corda/node/internal/Node.kt | 3 + .../node/services/config/ConfigUtilities.kt | 3 - .../net/corda/node/services/keys/KMSUtils.kt | 9 +- .../services/persistence/RunOnceService.kt | 10 +- .../identity/InMemoryIdentityServiceTests.kt | 6 +- .../persistence/RunOnceServiceTest.kt | 27 +- .../corda/notarydemo/RaftNotaryCordform.kt | 2 +- sgx-jvm/remote-attestation/build.gradle | 2 +- .../kotlin/net/corda/testing/node/MockNode.kt | 1 - tools/demobench/README.md | 3 + .../net/corda/demobench/model/NodeConfig.kt | 6 +- .../corda/demobench/model/NodeController.kt | 2 +- tools/explorer/README.md | 42 +- .../main/kotlin/net/corda/explorer/Main.kt | 6 +- 63 files changed, 1247 insertions(+), 1560 deletions(-) rename network-management/src/{integration-test/kotlin/com/r3/corda/networkmanage/doorman/DoormanIntegrationTest.kt => test/kotlin/com/r3/corda/networkmanage/common/persistence/PersitenceNodeInfoStorageTest.kt} (100%) create mode 100644 node-api/src/test/java/net/corda/nodeapi/internal/serialization/amqp/JavaPrivatePropertyTests.java create mode 100644 node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/PrivatePropertyTests.kt diff --git a/build.gradle b/build.gradle index aba2e4bb33..e6d7683e94 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,9 @@ buildscript { file("$projectDir/constants.properties").withInputStream { constants.load(it) } // Our version: bump this on release. - ext.corda_release_version = "3.0-ENT-snapshot" + ext.corda_release_version = "R3.CORDA-3.0-SNAPSHOT" // "CORDA-3.0-SNAPSHOT" for Corda (Open Source) + ext.corda_release_distribution = "com.r3.corda" // "net.corda" for Corda (Open Source) + // Increment this on any release that changes public APIs anywhere in the Corda platform ext.corda_platform_version = constants.getProperty("platformVersion") ext.gradle_plugins_version = constants.getProperty("gradlePluginsVersion") @@ -154,7 +156,7 @@ allprojects { attributes('Corda-Release-Version': corda_release_version) attributes('Corda-Platform-Version': corda_platform_version) attributes('Corda-Revision': corda_revision) - attributes('Corda-Vendor': 'Corda Enterprise Edition') + attributes('Corda-Vendor': 'R3 Corda Edition') attributes('Automatic-Module-Name': "net.corda.${task.project.name.replaceAll('-', '.')}") } } @@ -191,7 +193,7 @@ allprojects { } } - group 'com.r3.corda.enterprise' + group 'com.r3.corda' version "$corda_release_version" repositories { @@ -301,7 +303,7 @@ task deployNodes(type: net.corda.plugins.Cordform, dependsOn: ['jar']) { } } -// User and key are commented out to prevent accidental pushes of Enterprise to public repos. DO NOT UNCOMMENT. +// User and key are commented out to prevent accidental pushes of R3 Corda to public repos. DO NOT UNCOMMENT. bintrayConfig { // user = System.getenv('CORDA_BINTRAY_USER') // key = System.getenv('CORDA_BINTRAY_KEY') diff --git a/constants.properties b/constants.properties index ea74e20f17..fefe5c410c 100644 --- a/constants.properties +++ b/constants.properties @@ -1,6 +1,6 @@ gradlePluginsVersion=3.0.3 kotlinVersion=1.1.60 -platformVersion=1 +platformVersion=3 guavaVersion=21.0 bouncycastleVersion=1.57 typesafeConfigVersion=1.3.1 diff --git a/core/src/main/kotlin/net/corda/core/utilities/ByteArrays.kt b/core/src/main/kotlin/net/corda/core/utilities/ByteArrays.kt index ecbad03375..81007def1e 100644 --- a/core/src/main/kotlin/net/corda/core/utilities/ByteArrays.kt +++ b/core/src/main/kotlin/net/corda/core/utilities/ByteArrays.kt @@ -47,7 +47,8 @@ sealed class ByteSequence : Comparable { fun open() = ByteArrayInputStream(_bytes, offset, size) /** - * Create a sub-sequence backed by the same array. + * Create a sub-sequence of this sequence. A copy of the underlying array may be made, if a subclass overrides + * [bytes] to do so, as [OpaqueBytes] does. * * @param offset The offset within this sequence to start the new sequence. Note: not the offset within the backing array. * @param size The size of the intended sub sequence. @@ -55,7 +56,8 @@ sealed class ByteSequence : Comparable { fun subSequence(offset: Int, size: Int): ByteSequence { require(offset >= 0) require(offset + size <= this.size) - // Intentionally use bytes rather than _bytes, to mirror the copy-or-not behaviour of that property. + // Intentionally use bytes rather than _bytes, in case a subclass wants to prevent access to the original + // underlying array which could be revealed here (e.g. OpaqueBytes). return if (offset == 0 && size == this.size) this else of(bytes, this.offset + offset, size) } diff --git a/docs/source/_static/versions b/docs/source/_static/versions index b7932ed452..f9530c76b0 100644 --- a/docs/source/_static/versions +++ b/docs/source/_static/versions @@ -1,14 +1,3 @@ { - "https://docs.corda.net/releases/release-M6.0": "M6.0", - "https://docs.corda.net/releases/release-M7.0": "M7.0", - "https://docs.corda.net/releases/release-M8.2": "M8.2", - "https://docs.corda.net/releases/release-M9.2": "M9.2", - "https://docs.corda.net/releases/release-M10.1": "M10.1", - "https://docs.corda.net/releases/release-M11.2": "M11.2", - "https://docs.corda.net/releases/release-M12.1": "M12.1", - "https://docs.corda.net/releases/release-M13.0": "M13.0", - "https://docs.corda.net/releases/release-M14.0": "M14.0", - "https://docs.corda.net/releases/release-V1.0": "V1.0", - "https://docs.corda.net/releases/release-V2.0": "V2.0", - "https://docs.corda.net/head/": "Master" + "https://docs.corda.r3.com/releases/release-V3.0": "V3.0" } diff --git a/docs/source/_templates/layout_for_doc_website.html b/docs/source/_templates/layout_for_doc_website.html index f0992030c9..e73cf409e3 100644 --- a/docs/source/_templates/layout_for_doc_website.html +++ b/docs/source/_templates/layout_for_doc_website.html @@ -18,7 +18,7 @@ API reference: Kotlin/ `_, for his contribution which adds -support for more currencies to the DemoBench and Explorer tools. - -* A new Vault Query service: - - * Implemented using JPA and Hibernate, this new service provides the ability to specify advanced queries using - criteria specification sets for both vault attributes and custom contract specific attributes. In addition, new - queries provide sorting and pagination capabilities. - The new API provides two function variants which are exposed for usage within Flows and by RPC clients: - - ``queryBy()`` for point-in-time snapshot queries - (replaces several existing VaultService functions and a number of Kotlin-only extension functions) - - ``trackBy()`` for snapshot and streaming updates - (replaces the VaultService ``track()`` function and the RPC ``vaultAndUpdates()`` function) - Existing VaultService API methods will be maintained as deprecated until the following milestone release. - - * The NodeSchema service has been enhanced to automatically generate mapped objects for any ContractState objects - that extend FungibleAsset or LinearState, such that common attributes of those parent states are persisted to - two new vault tables: vault_fungible_states and vault_linear_states (and thus queryable using the new Vault Query - service API). - Similarly, two new common JPA superclass schemas (``CommonSchemaV1.FungibleState`` and - ``CommonSchemaV1.LinearState``) mirror the associated FungibleAsset and LinearState interface states to enable - CorDapp developers to create new custom schemas by extension (rather than duplication of common attribute mappings) - - * A new configurable field ``requiredSchemas`` has been added to the CordaPluginRegistry to enable CorDapps to - register custom contract state schemas they wish to query using the new Vault Query service API (using the - ``VaultCustomQueryCriteria``). - - * See :doc:`vault-query` for full details and code samples of using the new Vault Query service. - -* Identity and cryptography related changes: - - * Enable certificate validation in most scenarios (will be enforced in all cases in an upcoming milestone). - - * Added DER encoded format for CompositeKey so they can be used in X.509 certificates. - - * Corrected several tests which made assumptions about counterparty keys, which are invalid when confidential - identities are used. - - * A new RPC has been added to support fuzzy matching of X.500 names, for instance, to translate from user input to - an unambiguous identity by searching the network map. - - * A function for deterministic key derivation ``Crypto.deriveKeyPair(privateKey: PrivateKey, seed: ByteArray)`` - has been implemented to support deterministic ``KeyPair`` derivation using an existing private key and a seed - as inputs. This operation is based on the HKDF scheme and it's a variant of the hardened parent-private -> - child-private key derivation function of the BIP32 protocol, but it doesn't utilize extension chain codes. - Currently, this function supports the following schemes: ECDSA secp256r1 (NIST P-256), ECDSA secp256k1 and - EdDSA ed25519. - -* A new ``ClassWhitelist`` implementation, ``AllButBlacklisted`` is used internally to blacklist classes/interfaces, - which are not expected to be serialised during checkpoints, such as ``Thread``, ``Connection`` and ``HashSet``. - This implementation supports inheritance and if a superclass or superinterface of a class is blacklisted, so is - the class itself. An ``IllegalStateException`` informs the user if a class is blacklisted and such an exception is - returned before checking for ``@CordaSerializable``; thus, blacklisting precedes annotation checking. - -* ``TimeWindow`` has a new 5th factory method ``TimeWindow.fromStartAndDuration(fromTime: Instant, duration: Duration)`` - which takes a start-time and a period-of-validity (after this start-time) as inputs. - -* The node driver has moved to net.corda.testing.driver in the test-utils module. - -* Web API related collections ``CordaPluginRegistry.webApis`` and ``CordaPluginRegistry.staticServeDirs`` moved to - ``net.corda.webserver.services.WebServerPluginRegistry`` in ``webserver`` module. - Classes serving Web API should now extend ``WebServerPluginRegistry`` instead of ``CordaPluginRegistry`` - and they should be registered in ``resources/META-INF/services/net.corda.webserver.services.WebServerPluginRegistry``. - -* Added a flag to the driver that allows the running of started nodes in-process, allowing easier debugging. - To enable use `driver(startNodesInProcess = true) { .. }`, or `startNode(startInSameProcess = true, ..)` - to specify for individual nodes. - -* Dependencies changes: - * Upgraded Dokka to v0.9.14. - * Upgraded Gradle Plugins to 0.12.4. - * Upgraded Apache ActiveMQ Artemis to v2.1.0. - * Upgraded Netty to v4.1.9.Final. - * Upgraded BouncyCastle to v1.57. - * Upgraded Requery to v1.3.1. - -.. _changelog_m12: - -Milestone 12 (First Public Beta) --------------------------------- - -* Quite a few changes have been made to the flow API which should make things simpler when writing CorDapps: - - * ``CordaPluginRegistry.requiredFlows`` is no longer needed. Instead annotate any flows you wish to start via RPC with - ``@StartableByRPC`` and any scheduled flows with ``@SchedulableFlow``. - - * ``CordaPluginRegistry.servicePlugins`` is also no longer used, along with ``PluginServiceHub.registerFlowInitiator``. - Instead annotate your initiated flows with ``@InitiatedBy``. This annotation takes a single parameter which is the - initiating flow. This initiating flow further has to be annotated with ``@InitiatingFlow``. For any services you - may have, such as oracles, annotate them with ``@CordaService``. These annotations will be picked up automatically - when the node starts up. - - * Due to these changes, when unit testing flows make sure to use ``AbstractNode.registerInitiatedFlow`` so that the flows - are wired up. Likewise for services use ``AbstractNode.installCordaService``. - - * Related to ``InitiatingFlow``, the ``shareParentSessions`` boolean parameter of ``FlowLogic.subFlow`` has been - removed. This was an unfortunate parameter that unnecessarily exposed the inner workings of flow sessions. Now, if - your sub-flow can be started outside the context of the parent flow then annotate it with ``@InitiatingFlow``. If - it's meant to be used as a continuation of the existing parent flow, such as ``CollectSignaturesFlow``, then it - doesn't need any annotation. - - * The ``InitiatingFlow`` annotation also has an integer ``version`` property which assigns the initiating flow a version - number, defaulting to 1 if it's not specified. This enables versioning of flows with nodes only accepting communication - if the version number matches. At some point we will support the ability for a node to have multiple versions of the - same flow registered, enabling backwards compatibility of flows. - - * ``ContractUpgradeFlow.Instigator`` has been renamed to just ``ContractUpgradeFlow``. - - * ``NotaryChangeFlow.Instigator`` has been renamed to just ``NotaryChangeFlow``. - - * ``FlowLogic.getCounterpartyMarker`` is no longer used and been deprecated for removal. If you were using this to - manage multiple independent message streams with the same party in the same flow then use sub-flows instead. - -* There are major changes to the ``Party`` class as part of confidential identities: - - * ``Party`` has moved to the ``net.corda.core.identity`` package; there is a deprecated class in its place for - backwards compatibility, but it will be removed in a future release and developers should move to the new class as soon - as possible. - * There is a new ``AbstractParty`` superclass to ``Party``, which contains just the public key. This now replaces - use of ``Party`` and ``PublicKey`` in state objects, and allows use of full or anonymised parties depending on - use-case. - * A new ``PartyAndCertificate`` class has been added which aggregates a Party along with an X.509 certificate and - certificate path back to a network trust root. This is used where a Party and its proof of identity are required, - for example in identity registration. - * Names of parties are now stored as a ``X500Name`` rather than a ``String``, to correctly enforce basic structure of the - name. As a result all node legal names must now be structured as X.500 distinguished names. - -* The identity management service takes an optional network trust root which it will validate certificate paths to, if - provided. A later release will make this a required parameter. - -* There are major changes to transaction signing in flows: - - * You should use the new ``CollectSignaturesFlow`` and corresponding ``SignTransactionFlow`` which handle most - of the details of this for you. They may get more complex in future as signing becomes a more featureful - operation. - * ``ServiceHub.legalIdentityKey`` no longer returns a ``KeyPair``, it instead returns just the ``PublicKey`` portion of this pair. - The ``ServiceHub.notaryIdentityKey`` has changed similarly. The goal of this change is to keep private keys - encapsulated and away from most flow code/Java code, so that the private key material can be stored in HSMs - and other key management devices. - * The ``KeyManagementService`` no longer provides any mechanism to request the node's ``PrivateKey`` objects directly. - Instead signature creation occurs in the ``KeyManagementService.sign``, with the ``PublicKey`` used to indicate - which of the node's keypairs to use. This lookup also works for ``CompositeKey`` scenarios - and the service will search for a leaf key hosted on the node. - * The ``KeyManagementService.freshKey`` method now returns only the ``PublicKey`` portion of the newly generated ``KeyPair`` - with the ``PrivateKey`` kept internally to the service. - * Flows which used to acquire a node's ``KeyPair``, typically via ``ServiceHub.legalIdentityKey``, - should instead use the helper methods on ``ServiceHub``. In particular to freeze a ``TransactionBuilder`` and - generate an initial partially signed ``SignedTransaction`` the flow should use ``ServiceHub.toSignedTransaction``. - Flows generating additional party signatures should use ``ServiceHub.createSignature``. Each of these methods is - provided with two signatures. One version that signs with the default node key, the other which allows key selection - by passing in the ``PublicKey`` partner of the desired signing key. - * The original ``KeyPair`` signing methods have been left on the ``TransactionBuilder`` and ``SignedTransaction``, but - should only be used as part of unit testing. - -* ``Timestamp`` used for validation/notarization time-range has been renamed to ``TimeWindow``. - There are now 4 factory methods ``TimeWindow.fromOnly(fromTime: Instant)``, - ``TimeWindow.untilOnly(untilTime: Instant)``, ``TimeWindow.between(fromTime: Instant, untilTime: Instant)`` and - ``TimeWindow.withTolerance(time: Instant, tolerance: Duration)``. - Previous constructors ``TimeWindow(fromTime: Instant, untilTime: Instant)`` and - ``TimeWindow(time: Instant, tolerance: Duration)`` have been removed. - -* The Bouncy Castle library ``X509CertificateHolder`` class is now used in place of ``X509Certificate`` in order to - have a consistent class used internally. Conversions to/from ``X509Certificate`` are done as required, but should - be avoided where possible. - -* The certificate hierarchy has been changed in order to allow corda node to sign keys with proper certificate chain. - * The corda node will now be issued a restricted client CA for identity/transaction key signing. - * TLS certificate are now stored in `sslkeystore.jks` and identity keys are stored in `nodekeystore.jks` - -.. warning:: The old keystore will need to be removed when upgrading to this version. - -Milestone 11.1 --------------- - -* Fix serialisation error when starting a flow. -* Automatically whitelist subclasses of `InputStream` when serialising. -* Fix exception in DemoBench on Windows when loading CorDapps into the Node Explorer. -* Detect when localhost resolution is broken on MacOSX, and provide instructions on how to fix it. - -Milestone 11.0 --------------- - -* API changes: - * Added extension function ``Database.transaction`` to replace ``databaseTransaction``, which is now deprecated. - - * Starting a flow no longer enables progress tracking by default. To enable it, you must now invoke your flow using - one of the new ``CordaRPCOps.startTrackedFlow`` functions. ``FlowHandle`` is now an interface, and its ``progress: Observable`` - field has been moved to the ``FlowProgressHandle`` child interface. Hence developers no longer need to invoke ``notUsed`` - on their flows' unwanted progress-tracking observables. - - * Moved ``generateSpend`` and ``generateExit`` functions into ``OnLedgerAsset`` from the vault and - ``AbstractConserveAmount`` clauses respectively. - - * Added ``CompositeSignature`` and ``CompositeSignatureData`` as part of enabling ``java.security`` classes to work - with composite keys and signatures. - - * ``CompositeKey`` now implements ``java.security.PublicKey`` interface, so that keys can be used on standard classes - such as ``Certificate``. - - * There is no longer a need to transform single keys into composite - ``composite`` extension was removed, it is - imposible to create ``CompositeKey`` with only one leaf. - - * Constructor of ``CompositeKey`` class is now private. Use ``CompositeKey.Builder`` to create a composite key. - Keys emitted by the builder are normalised so that it's impossible to create a composite key with only one node. - (Long chains of single nodes are shortened.) - - * Use extension function ``PublicKeys.keys`` to access all keys belonging to an instance of ``PublicKey``. For a - ``CompositeKey``, this is equivalent to ``CompositeKey.leafKeys``. - - * Introduced ``containsAny``, ``isFulfilledBy``, ``keys`` extension functions on ``PublicKey`` - ``CompositeKey`` - type checking is done there. - -* Corda now requires JDK 8u131 or above in order to run. Our Kotlin now also compiles to JDK8 bytecode, and so you'll need - to update your CorDapp projects to do the same. E.g. by adding this to ``build.gradle``: - -.. parsed-literal:: - - tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all { - kotlinOptions { - languageVersion = "1.1" - apiVersion = "1.1" - jvmTarget = "1.8" - } - } - -.. - - or by adjusting ``Settings/Build,Execution,Deployment/Compiler/KotlinCompiler`` in IntelliJ:: - - - Language Version: 1.1 - - API Version: 1.1 - - Target JVM Version: 1.8 - -* DemoBench is now installed as ``Corda DemoBench`` instead of ``DemoBench``. - -* Rewrote standard test identities to have full X.500 distinguished names. As part of this work we standardised on a - smaller set of test identities, to reduce risk of subtle differences (i.e. similar common names varying by whitespace) - in naming making it hard to diagnose issues. - -Milestone 10.0 --------------- - -Special thank you to `Qian Hong `_, `Marek Skocovsky `_, -`Karel Hajek `_, and `Jonny Chiu `_ for their contributions -to Corda in M10. - -.. warning:: Due to incompatibility between older version of IntelliJ and gradle 3.4, you will need to upgrade Intellij - to 2017.1 (with kotlin-plugin v1.1.1) in order to run Corda demos in IntelliJ. You can download the latest IntelliJ - from `JetBrains `_. - -.. warning:: The Kapt-generated models are no longer included in our codebase. If you experience ``unresolved references`` - errors when building in IntelliJ, please rebuild the schema model by running ``gradlew kaptKotlin`` in Windows or - ``./gradlew kaptKotlin`` in other systems. Alternatively, perform a full gradle build or install. - -.. note:: Kapt is used to generate schema model and entity code (from annotations in the codebase) using the Kotlin Annotation - processor. - -* Corda DemoBench: - * DemoBench is a new tool to make it easy to configure and launch local Corda nodes. A very useful tool to demonstrate - to your colleagues the fundamentals of Corda in real-time. It has the following features: - - * Clicking "Add node" creates a new tab that lets you edit the most important configuration properties of the node - before launch, such as its legal name and which CorDapps will be loaded. - * Each tab contains a terminal emulator, attached to the pseudoterminal of the node. This lets you see console output. - * You can launch an Corda Explorer instance for each node via the DemoBench UI. Credentials are handed to the Corda - Explorer so it starts out logged in already. - * Some basic statistics are shown about each node, informed via the RPC connection. - * Another button launches a database viewer in the system browser. - * The configurations of all running nodes can be saved into a single ``.profile`` file that can be reloaded later. - - * You can download Corda DemoBench from `here `_ - -* Vault: - * Soft Locking is a new feature implemented in the vault which prevent a node constructing transactions that attempt - to use the same input(s) simultaneously. - * Such transactions would result in naturally wasted effort when the notary rejects them as double spend attempts. - * Soft locks are automatically applied to coin selection (eg. cash spending) to ensure that no two transactions attempt - to spend the same fungible states. - -* Corda Shell : - * The shell lets developers and node administrators easily command the node by running flows, RPCs and SQL queries. - * It provides a variety of commands to monitor the node. - * The Corda Shell is based on the popular `CRaSH project `_ and new commands can be easily - added to the node by simply dropping Groovy or Java files into the node's ``shell-commands`` directory. - * We have many enhancements planned over time including SSH access, more commands and better tab completion. - -* API changes: - * The new Jackson module provides JSON/YAML serialisers for common Corda datatypes. - If you have previously been using the JSON support in the standalone web server, - please be aware that Amounts are now serialised as strings instead of { quantity, token } pairs as before. - The old format is still accepted, but the new JSON will be produced using strings like "1000.00 USD" when writing. - You can use any format supported by ``Amount.parseCurrency`` as input. - - * We have restructured client package in this milestone. - * ``CordaClientRPC`` is now in the new ``:client:rpc`` module. - * The old ``:client`` module has been split up into ``:client:jfx`` and ``:client:mock``. - * We also have a new ``:node-api`` module (package ``net.corda.nodeapi``) which contains the shared code between - ``node`` and ``client``. - - * The basic Amount API has been upgraded to have support for advanced financial use cases and to better integrate with - currency reference data. - -* Configuration: - * Replace ``artemisPort`` with ``p2pPort`` in Gradle configuration. - * Replace ``artemisAddress`` with ``p2pAddress`` in node configuration. - * Added ``rpcAddress`` in node configuration for non-ssl RPC connection. - -* Object Serialization: - * Pool Kryo instances for efficiency. - -* RPC client changes: - * RPC clients can now connect to the node without the need for SSL. This requires a separate port on the Artemis broker, - SSL must not be used for RPC connection. - * CordaRPCClient now needs to connect to ``rpcAddress`` rather than ``p2pAddress``. - -* Dependencies changes: - * Upgraded Kotlin to v1.1.1. - * Upgraded Gradle to v3.4.1. - * Upgraded requery to v1.2.1. - * Upgraded H2 to v1.4.194. - * Replaced kotlinx-support-jdk8 with kotlin-stdlib-jre8. - -* Improvements: - * Added ``--version`` command line flag to print the version of the node. - * Flows written in Java can now execute a sub-flow inside ``UntrustworthyData.unwrap``. - * Added optional out-of-process transaction verification. Any number of external verifier processes may be attached - to the node which can handle loadbalanced verification requests. - -* Bug fixes: - * ``--logging-level`` command line flag was previously broken, now correctly sets the logging level. - * Fixed bug whereby Cash Exit was not taking into account the issuer reference. - - -Milestone 9.1 -------------- - -* Correct web server ports for IRS demo. -* Correct which corda-webserver JAR is published to Maven. - -Milestone 9 ------------ - -* With thanks to `Thomas Schroeter `_ for the Byzantine fault tolerant (BFT) - notary prototype. -* Web server is a separate JAR. This is a breaking change. The new webserver JAR (``corda-webserver.jar``) - must be invoked separately to node startup, using the command``java -jar corda-webserver.jar`` in the same - directory as the ``node.conf``. Further changes are anticipated in upcoming milestone releases. - -* API: - - * Pseudonymous ``AnonymousParty`` class added as a superclass of ``Party``. - * Split ``CashFlow`` into individual ``CashIssueFlow``, ``CashPaymentFlow`` and ``CashExitFlow`` flows, so that fine - grained permissions can be applied. Added ``CashFlowCommand`` for use-cases where cash flow triggers need to be - captured in an object that can be passed around. - * ``CordaPluginRegistry`` method ``registerRPCKryoTypes`` is renamed ``customizeSerialization`` and the argument - types now hide the presence of Kryo. - * New extension functions for encoding/decoding to base58, base64, etc. See - ``core/src/main/kotlin/net/corda/core/crypto/EncodingUtils.kt`` - * Add ``openAttachment`` function to Corda RPC operations, for downloading an attachment from a node's data storage. - * Add ``getCashBalances`` function to Corda RPC operations, for getting cash balances from a node's vault. - -* Configuration: - * ``extraAdvertisedServiceIds`` config is now a list of strings, rather than a comma separated string. For example - ``[ "corda.interest_rates" ]`` instead of ``"corda.interest_rates"``. - -* Flows: - * Split ``CashFlow`` into separate ``CashIssueFlow``, ``CashPaymentFlow`` and ``CashExitFlow`` so that permissions can - be assigned individually. - * Split single example user into separate "bankUser" and "bigCorpUser" so that permissions for the users make sense - rather than being a combination of both roles. - * ``ProgressTracker`` emits exception thrown by the flow, allowing the ANSI renderer to correctly stop and print the error - -* Object Serialization: - - * Consolidated Kryo implementations across RPC and P2P messaging with whitelisting of classes via plugins or with - ``@CordaSerializable`` for added node security. - -* Privacy: - * Non-validating notary service now takes in a ``FilteredTransaction`` so that no potentially sensitive transaction - details are unnecessarily revealed to the notary - -* General: - * Add vault service persistence using Requery - * Certificate signing utility output is now more verbose - -Milestone 8 ------------ - -* Node memory usage and performance improvements, demo nodes now only require 200 MB heap space to run. - -* The Corda node no longer runs an internal web server, it's now run in a separate process. Driver and Cordformation have - been updated to reflect this change. Existing CorDapps should be updated with additional calls to the new ``startWebserver()`` - interface in their Driver logic (if they use the driver e.g. in integration tests). See the IRS demo for an example. - -* Data model: ``Party`` equality is now based on the owning key, rather than the owning key and name. This is important for - party anonymisation to work, as each key must identify exactly one party. - -* Contracts: created new composite clauses called ``AllOf``, ``AnyOf`` and ``FirstOf`` to replace ``AllComposition``, ``AnyComposition`` - and ``FirstComposition``, as this is significantly clearer in intent. ``AnyOf`` also enforces that at least one subclause - must match, whereas ``AnyComposition`` would accept no matches. - -* Explorer: the user can now configure certificate path and keystore/truststore password on the login screen. - -* Documentation: - - * Key Concepts section revamped with new structure and content. - * Added more details to :doc:`getting-set-up` page. - -* Flow framework: improved exception handling with the introduction of ``FlowException``. If this or a subtype is thrown - inside a flow it will propagate to all counterparty flows and subsequently be thrown by them as well. Existing flows such as - ``NotaryFlow.Client/Service`` and others have been modified to throw a ``FlowException`` (in this particular case a - ``NotaryException``) instead of sending back error responses. - -* Notary flow: provide complete details of underlying error when contract validation fails. - -Milestone 7 ------------ - -* With thanks to `Thomas Schroeter `_ ``NotaryFlow`` is now idempotent. - -* Explorer: - - * The GUI for the explorer now shows other nodes on the network map and the transactions between them. - * Map resolution increased and allows zooming and panning. - * `Video demonstration `_ of the Node Explorer. - -* The CorDapp template now has a Java example that parallels the Kotlin one for developers more comfortable with Java. - ORM support added to the Kotlin example. - -* Demos: - - * Added the Bank of Corda demo - a demo showing a node (Bank of Corda) acting as an issuer of Cash, and a client - driver providing both Web and RPC access to request issuance of cash. - * Demos now use RPC to communicate with the node from the webserver. This brings the demos more in line with how - interaction with nodes is expected to be. The demos now treat their webservers like clients. This will also allow - for the splitting of the webserver from the node for milestone 8. - * Added a SIMM valuation demo integration test to catch regressions. - -* Security: - - * MQ broker of the node now requires authentication which means that third parties cannot connect to and - listen to queues on the Node. RPC and P2P between nodes is now authenticated as a result of this change. - This also means that nodes or RPC users cannot pretend to be other nodes or RPC users. - * The node now does host verification of any node that connects to it and prevents man in the middle attacks. - -* Improvements: - - * Vault updates now contain full ``StateAndRef`` which allows subscribers to check whether the update contains - relevant states. - * Cash balances are calculated using aggregate values to prevent iterating through all states in the vault, which - improves performance. - * Multi-party services, such as notaries, are now load balanced and represented as a single ``Party`` object. - * The Notary Change flow now supports encumbrances. - -Milestone 6 ------------ - -* Added the `Corda technical white paper <_static/corda-technical-whitepaper.pdf>`_. Note that its current version - is 0.5 to reflect the fact that the Corda design is still evolving. Although we expect only relatively small tweaks - at this point, when Corda reaches 1.0 so will the white paper. - -* Major documentation restructuring and new content: - - * More details on Corda node internals. - * New CorDapp tutorial. - * New tutorial on building transactions. - * New tutorials on how to run and use a notary service. - -* An experimental version of the deterministic JVM sandbox has been added. It is not integrated with the node and will - undergo some significant changes in the coming releases before it is integrated, as the code is finished, as bugs are - found and fixed, and as the platform subset we choose to expose is finalised. Treat this as an outline of the basic - approach rather than something usable for production. - -* Developer experience: - - * Samples have been merged back into the main repository. All samples can now be run via command line or IntelliJ. - - * Added a Client RPC python example. - - * Node console output now displays concise startup information, such as startup time or web address. All logging to - the console is suppressed apart from errors and flow progress tracker steps. It can be re-enabled by passing - ``--log-to-console`` command line parameter. Note that the log file remains unchanged and will still contain all - log entries. - - * The ``runnodes`` scripts generated by the Gradle plugins now open each node in separate terminal windows or (on macOS) tabs. - - * A much more complete template app. - - * JARs now available on Maven Central. - -* Data model: A party is now identified by a composite key (formerly known as a "public key tree") instead of a single public key. - Read more in :ref:`composite-keys`. This allows expressing distributed service identities, e.g. a distributed notary. - In the future this will also allow parties to use multiple signing keys for their legal identity. - -* Decentralised consensus: A prototype RAFT based notary composed of multiple nodes has been added. This implementation - is optimised for high performance over robustness against malicious cluster members, which may be appropriate for - some financial situations. See :ref:`notary-demo` to try it out. A BFT notary will be added later. - -* Node explorer app: - - * New theme aligned with the Corda branding. - * The New Transaction screen moved to the Cash View (as it is used solely for cash transactions) - * Removed state machine/flow information from Transaction table. A new view for this will be created in a future release. - * Added a new Network View that displays details of all nodes on the network. - * Users can now configure the reporting currency in settings. - * Various layout and performance enhancements. - -* Client RPC: - - * Added a generic ``startFlow`` method that enables starting of any flow, given sufficient permissions. - * Added the ability for plugins to register additional classes or custom serialisers with Kryo for use in RPC. - * ``rpc-users.properties`` file has been removed with RPC user settings moved to the config file. - -* Configuration changes: It is now possible to specify a custom legal name for any of the node's advertised services. - -* Added a load testing framework which allows stress testing of a node cluster, as well as specifying different ways of - disrupting the normal operation of nodes. See :doc:`loadtesting`. - -* Improvements to the experimental contract DSL, by Sofus Mortensen of Nordea Bank (please give Nordea a shoutout too). - -API changes: - -* The top level package has been renamed from ``com.r3corda`` to ``net.corda``. -* Protocols have been renamed to "flows". -* ``OpaqueBytes`` now uses ``bytes`` as the field name rather than ``bits``. - -Milestone 5 ------------ - -* A simple RPC access control mechanism. Users, passwords and permissions can be defined in a configuration file. - This mechanism will be extended in future to support standard authentication systems like LDAP. - -* New features in the explorer app and RPC API for working with cash: - - * Cash can now be sent, issued and exited via RPC. - * Notes can now be associated with transactions. - * Hashes are visually represented using identicons. - * Lots of functional work on the explorer UI. You can try it out by running ``gradle tools:explorer:runDemoNodes`` to run - a local network of nodes that swap cash with each other, and then run ``gradle tools:explorer:run`` to start - the app. - -* A new demo showing shared valuation of derivatives portfolios using the ISDA SIMM has been added. Note that this app - relies on a proprietary implementation of the ISDA SIMM business logic from OpenGamma. A stub library is provided - to ensure it compiles but if you want to use the app for real please contact us. - -* Developer experience (we plan to do lots more here in milestone 6): - - * Demos and samples have been split out of the main repository, and the initial developer experience continues to be - refined. All necessary JARs can now be installed to Maven Local by simply running ``gradle install``. - * It's now easier to define a set of nodes to run locally using the new "CordFormation" gradle plugin, which - defines a simple DSL for creating networks of nodes. - * The template CorDapp has been upgraded with more documentation and showing more features. - -* Privacy: transactions are now structured as Merkle trees, and can have sections "torn off" - presented for - verification and signing without revealing the rest of the transaction. - -* Lots of bug fixes, tweaks and polish starting the run up to the open source release. - -API changes: - -* Plugin service classes now take a ``PluginServiceHub`` rather than a ``ServiceHubInternal``. -* ``UniqueIdentifier`` equality has changed to only take into account the underlying UUID. -* The contracts module has been renamed to finance, to better reflect what it is for. - -Milestone 4 ------------ - -New features in this release: - -* Persistence: - - * States can now be written into a relational database and queried using JDBC. The schemas are defined by the - smart contracts and schema versioning is supported. It is reasonable to write an app that stores data in a mix - of global ledger transactions and local database tables which are joined on demand, using join key slots that - are present in many state definitions. Read more about :doc:`persistence`. - * The embedded H2 SQL database is now exposed by default to any tool that can speak JDBC. The database URL is - printed during node startup and can be used to explore the database, which contains both node internal data - and tables generated from ledger states. - * Protocol checkpoints are now stored in the database as well. Message processing is now atomic with protocol - checkpointing and run under the same RDBMS transaction. - * MQ message deduplication is now handled at the app layer and performed under the RDMS transaction, so - ensuring messages are only replayed if the RDMS transaction rolled back. - * "The wallet" has been renamed to "the vault". - -* Client RPC: - - * New RPCs added to subscribe to snapshots and update streams state of the vault, currently executing protocols - and other important node information. - * New tutorial added that shows how to use the RPC API to draw live transaction graphs on screen. - -* Protocol framework: - - * Large simplifications to the API. Session management is now handled automatically. Messages are now routed - based on identities rather than node IP addresses. - -* Decentralised consensus: - - * A standalone one-node notary backed by a JDBC store has been added. - * A prototype RAFT based notary composed of multiple nodes is available on a branch. - -* Data model: - - * Compound keys have been added as preparation for merging a distributed RAFT based notary. Compound keys - are trees of public keys in which interior nodes can have validity thresholds attached, thus allowing - boolean formulas of keys to be created. This is similar to Bitcoin's multi-sig support and the data model - is the same as the InterLedger Crypto-Conditions spec, which should aid interop in future. Read more about - key trees in the ":doc:`api-core-types`" article. - * A new tutorial has been added showing how to use transaction attachments in more detail. - -* Testnet - - * Permissioning infrastructure phase one is built out. The node now has a notion of developer mode vs normal - mode. In developer mode it works like M3 and the SSL certificates used by nodes running on your local - machine all self-sign using a developer key included in the source tree. When developer mode is not active, - the node won't start until it has a signed certificate. Such a certificate can be obtained by simply running - an included command line utility which generates a CSR and submits it to a permissioning service, then waits - for the signed certificate to be returned. Note that currently there is no public Corda testnet, so we are - not currently running a permissioning service. - -* Standalone app development: - - * The Corda libraries that app developers need to link against can now be installed into your local Maven - repository, where they can then be used like any other JAR. See :doc:`running-a-node`. - -* User interfaces: - - * Infrastructure work on the node explorer is now complete: it is fully switched to using the MQ based RPC system. - * A library of additional reactive collections has been added. This API builds on top of Rx and the observable - collections API in Java 8 to give "live" data structures in which the state of the node and ledger can be - viewed as an ordinary Java ``List``, ``Map`` and ``Set``, but which also emit callbacks when these views - change, and which can have additional views derived in a functional manner (filtered, mapped, sorted, etc). - Finally, these views can then be bound directly into JavaFX UIs. This makes for a concise and functional - way of building application UIs that render data from the node, and the API is available for third party - app developers to use as well. We believe this will be highly productive and enjoyable for developers who - have the option of building JavaFX apps (vs web apps). - * The visual network simulator tool that was demoed back in April as part of the first Corda live demo has - been merged into the main repository. - -* Documentation - - * New secure coding guidelines. Corda tries to eliminate as many security mistakes as practical via the type - system and other mechanically checkable processes, but there are still things that one must be aware of. - * New attachments tutorial. - * New Client RPC tutorial. - * More tutorials on how to build a standalone CorDapp. - -* Testing - - * More integration testing support - * New micro-DSLs for expressing expected sequences of operations with more or less relaxed ordering constraints. - * QuickCheck generators to create streams of randomised transactions and other basic types. QuickCheck is a way - of writing unit tests that perform randomised fuzz testing of code, originally developed by the Haskell - community and now also available in Java. - -API changes: - -* The transaction types (Signed, Wire, LedgerTransaction) have moved to ``net.corda.core.transactions``. You can - update your code by just deleting the broken import lines and letting your IDE re-import them from the right - location. -* ``AbstractStateReplacementProtocol.verifyProposal`` has changed its prototype in a minor way. -* The ``UntrustworthyData.validate`` method has been renamed to ``unwrap`` - the old name is now deprecated. -* The wallet, wallet service, etc. are now vault, vault service, etc. These better reflect the intent that they - are a generic secure data store, rather than something which holds cash. -* The protocol send/receive APIs have changed to no longer require a session id. Please check the current version - of the protocol framework tutorial for more details. - -Milestone 3 ------------ - -* More work on preparing for the testnet: - - * Corda is now a standalone app server that loads "CorDapps" into itself as plugins. Whilst the existing IRS - and trader demos still exist for now, these will soon be removed and there will only be a single Corda node - program. Note that the node is a single, standalone jar file that is easier to execute than the demos. - * Project Vega (shared SIMM modelling for derivative portfolios) has already been converted to be a CorDapp. - * Significant work done on making the node persist its wallet data to a SQL backend, with more on the way. - * Upgrades and refactorings of the core transaction types in preparation for the incoming sandboxing work. - -* The Clauses API that seeks to make writing smart contracts easier has gone through another design iteration, - with the result that clauses are now cleaner and more composable. -* Improvements to the protocol API for finalising transactions (notarising, transmitting and storing). -* Lots of work done on an MQ based client API. -* Improvements to the developer site: - - * The developer site has been re-read from start to finish and refreshed for M3 so there should be no obsolete - texts or references anywhere. - * The Corda non-technical white paper is now a part of the developer site and git repository. The LaTeX source is - also provided so if you spot any issues with it, you can send us patches. - * There is a new section on how to write CorDapps. - -* Further R&D work by Sofus Mortensen in the experimental module on a new 'universal' contract language. -* SSL for the REST API and webapp server can now be configured. - - -Milestone 2 ------------ - -* Big improvements to the interest rate swap app: - - * A new web app demonstrating the IRS contract has been added. This can be used as an example for how to interact with - the Corda API from the web. - * Simplifications to the way the demo is used from the command line. - * :doc:`Detailed documentation on how the contract works and can be used ` has been written. - * Better integration testing of the app. - -* Smart contracts have been redesigned around reusable components, referred to as "clauses". The cash, commercial paper - and obligation contracts now share a common issue clause. -* New code in the experimental module (note that this module is a place for work-in-progress code which has not yet gone - through code review and which may, in general, not even function correctly): - - * Thanks to the prolific Sofus Mortensen @ Nordea Bank, an experimental generic contract DSL that is based on the famous - 2001 "Composing contracts" paper has been added. We thank Sofus for this great and promising research, which is so - relevant in the wake of the DAO hack. - * The contract code from the recent trade finance demos is now in experimental. This code comes thanks to a - collaboration of the members; all credit to: - - * Mustafa Ozturk @ Natixis - * David Nee @ US Bank - * Johannes Albertsen @ Dankse Bank - * Rui Hu @ Nordea - * Daniele Barreca @ Unicredit - * Sukrit Handa @ Scotiabank - * Giuseppe Cardone @ Banco Intesa - * Robert Santiago @ BBVA - -* The usability of the command line demo programs has been improved. -* All example code and existing contracts have been ported to use the new Java/Kotlin unit testing domain-specific - languages (DSLs) which make it easy to construct chains of transactions and verify them together. This cleans up - and unifies the previous ad-hoc set of similar DSLs. A tutorial on how to use it has been added to the documentation. - We believe this largely completes our testing story for now around smart contracts. Feedback from bank developers - during the Trade Finance project has indicated that the next thing to tackle is docs and usability improvements in - the protocols API. -* Significant work done towards defining the "CorDapp" concept in code, with dynamic loading of API services and more to - come. -* Inter-node communication now uses SSL/TLS and AMQP/1.0, albeit without all nodes self-signing at the moment. A real - PKI for the p2p network will come later. -* Logging is now saved to files with log rotation provided by Log4J. - -API changes: - -* Some utility methods and extension functions that are specific to certain contract types have moved packages: just - delete the import lines that no longer work and let IntelliJ replace them with the correct package paths. -* The ``arg`` method in the test DSL is now called ``command`` to be consistent with the rest of the data model. -* The messaging APIs have changed somewhat to now use a new ``TopicSession`` object. These APIs will continue to change - in the upcoming releases. -* Clauses now have default values provided for ``ifMatched``, ``ifNotMatched`` and ``requiredCommands``. - -New documentation: - -* :doc:`contract-catalogue` -* :doc:`contract-irs` -* :doc:`tutorial-test-dsl` - -Milestone 1 ------------ - -Highlights of this release: - -* Event scheduling. States in the ledger can now request protocols to be invoked at particular times, for states - considered relevant by the wallet. -* Upgrades to the notary/consensus service support: - - * There is now a way to change the notary controlling a state. - * You can pick between validating and non-validating notaries, these let you select your privacy/robustness tradeoff. - -* A new obligation contract that supports bilateral and multilateral netting of obligations, default tracking and - more. -* Improvements to the financial type system, with core classes and contracts made more generic. -* Switch to a better digital signature algorithm: ed25519 instead of the previous JDK default of secp256r1. -* A new integration test suite. -* A new Java unit testing DSL for contracts, similar in spirit to the one already developed for Kotlin users (which - depended on Kotlin specific features). -* An experimental module, where developers who want to work with the latest Corda code can check in contracts/cordapp - code before it's been fully reviewed. Code in this module has compiler warnings suppressed but we will still make - sure it compiles across refactorings. -* Persistence improvements: transaction data is now stored to disk and automatic protocol resume is now implemented. -* Many smaller bug fixes, cleanups and improvements. - -We have new documentation on: - -* :doc:`event-scheduling` -* :doc:`core-types` -* :doc:`key-concepts-consensus` - -Summary of API changes (not exhaustive): - -* Notary/consensus service: - - * ``NotaryService`` is now extensible. - * Every ``ContractState`` now has to specify a *participants* field, which is a list of parties that are able to - consume this state in a valid transaction. This is used for e.g. making sure all relevant parties obtain the updated - state when changing a notary. - * Introduced ``TransactionState``, which wraps ``ContractState``, and is used when defining a transaction output. - The notary field is moved from ``ContractState`` into ``TransactionState``. - * Every transaction now has a *type* field, which specifies custom build & validation rules for that transaction type. - Currently two types are supported: General (runs the default build and validation logic) and NotaryChange ( - contract code is not run during validation, checks that the notary field is the only difference between the - inputs and outputs). - ``TransactionBuilder()`` is now abstract, you should use ``TransactionType.General.Builder()`` for building transactions. - -* The cash contract has moved from ``net.corda.contracts`` to ``net.corda.contracts.cash`` -* ``Amount`` class is now generic, to support non-currency types such as physical assets. Where you previously had just - ``Amount``, you should now use ``Amount``. -* Refactored the Cash contract to have a new FungibleAsset superclass, to model all countable assets that can be merged - and split (currency, barrels of oil, etc.) -* Messaging: - - * ``addMessageHandler`` now has a different signature as part of error handling changes. - * If you want to return nothing to a protocol, use ``Ack`` instead of ``Unit`` from now on. - -* In the IRS contract, dateOffset is now an integer instead of an enum. -* In contracts, you now use ``tx.getInputs`` and ``tx.getOutputs`` instead of ``getInStates`` and ``getOutStates``. This is - just a renaming. -* A new ``NonEmptySet`` type has been added for cases where you wish to express that you have a collection of unique - objects which cannot be empty. -* Please use the global ``newSecureRandom()`` function rather than instantiating your own SecureRandom's from now on, as - the custom function forces the use of non-blocking random drivers on Linux. - -Milestone 0 ------------ - -This is the first release, which includes: - -* Some initial smart contracts: cash, commercial paper, interest rate swaps -* An interest rate oracle -* The first version of the protocol/orchestration framework -* Some initial support for pluggable consensus mechanisms -* Tutorials and documentation explaining how it works -* Much more ... diff --git a/docs/source/clientrpc.rst b/docs/source/clientrpc.rst index ae30828149..38f27c9265 100644 --- a/docs/source/clientrpc.rst +++ b/docs/source/clientrpc.rst @@ -18,6 +18,8 @@ an ongoing stream of updates from the node. More detail on how to use this is pr For a brief tutorial on how one can use the RPC API see :doc:`tutorial-clientrpc-api`. +.. _rpc_security_mgmt_ref: + RPC permissions --------------- If a node's owner needs to interact with their node via RPC (e.g. to read the contents of the node's storage), they @@ -68,6 +70,8 @@ Fine grained permissions allow a user to invoke a specific RPC operation, or to - to invoke a RPC operation: ``InvokeRpc.`` e.g., ``InvokeRpc.nodeInfo``. .. note:: Permission ``InvokeRpc.startFlow`` allows a user to initiate all flows. +.. _authentication_ref: + RPC security management ----------------------- diff --git a/docs/source/conf.py b/docs/source/conf.py index b34fa914f9..608840b29b 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -54,11 +54,11 @@ author = u'R3 DLG' # built documents. # # The short X.Y version. -version = 'Master' +version = '3.0' # The full version, including alpha/beta/rc tags. -release = 'Master' +release = 'R3 Corda V3.0 Developer Preview' # The version for use in the dropdown html. -html_context = {'version': 'Master'} +html_context = {'version': 'V3.0'} # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/source/corda-configuration-file.rst b/docs/source/corda-configuration-file.rst index 71e292e1d6..25490f055d 100644 --- a/docs/source/corda-configuration-file.rst +++ b/docs/source/corda-configuration-file.rst @@ -68,28 +68,24 @@ path to the node's base directory. .. note:: Longer term these keys will be managed in secure hardware devices. -:database: Database configuration: +.. _database_properties_ref: - :transactionIsolationLevel: Transaction isolation level as defined by the ``TRANSACTION_`` constants in +:database: This section is used to configure JDBC and Hibernate related properties: + + :transactionIsolationLevel: Transaction isolation level as defined by the ``TRANSACTION_`` constants in ``java.sql.Connection``, but without the "TRANSACTION_" prefix. Defaults to REPEATABLE_READ. - :exportHibernateJMXStatistics: Whether to export Hibernate JMX statistics (caution: expensive run-time overhead) + + :exportHibernateJMXStatistics: Whether to export Hibernate JMX statistics (caution: expensive run-time overhead) + + :runMigration: Boolean on whether to run the database migration scripts. Defaults to true. + + :schema: (optional) some database providers require a schema name when generating DDL and SQL statements. + (the value is passed to Hibernate property 'hibernate.default_schema'). :dataSourceProperties: This section is used to configure the jdbc connection and database driver used for the nodes persistence. Currently the defaults in ``/node/src/main/resources/reference.conf`` are as shown in the first example. This is currently the only configuration that has been tested, although in the future full support for other storage layers will be validated. -:database: This section is used to configure JDBC and Hibernate related properties: - - :transactionIsolationLevel: Transaction isolation level as defined by the ``TRANSACTION_`` constants in - ``java.sql.Connection``, but without the "TRANSACTION_" prefix. Defaults to REPEATABLE_READ. - - :exportHibernateJMXStatistics: Whether to export Hibernate JMX statistics (caution: expensive run-time overhead) - - :runMigration: Boolean on whether to run the database migration scripts. Defaults to true. - - :schema: (optional) some database providers require a schema name when generating DDL and SQL statements. - (the value is passed to Hibernate property 'hibernate.hbm2ddl.auto'). - :messagingServerAddress: The address of the ArtemisMQ broker instance. If not provided the node will run one locally. :p2pAddress: The host and port on which the node is available for protocol operations over ArtemisMQ. @@ -196,5 +192,7 @@ path to the node's base directory. :exportJMXTo: If set to ``http``, will enable JMX metrics reporting via the Jolokia HTTP/JSON agent. Default Jolokia access url is http://127.0.0.1:7005/jolokia/ +.. _config_amqp_bridge: + :useAMQPBridges: Optionally can be set to ``false`` to use Artemis CORE Bridges for peer-to-peer communications. Otherwise, defaults to ``true`` and the AMQP 1.0 protocol will be used for message transfer between nodes. \ No newline at end of file diff --git a/docs/source/cordapp-build-systems.rst b/docs/source/cordapp-build-systems.rst index 5cba71b9af..d572e89e80 100644 --- a/docs/source/cordapp-build-systems.rst +++ b/docs/source/cordapp-build-systems.rst @@ -28,14 +28,12 @@ Setting your dependencies Choosing your Corda version ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -``ext.corda_release_version`` and ``ext.corda_gradle_plugins_version`` are used in the ``build.gradle`` to define the -versions of Corda and the Corda Gradle Plugins that are used to build your CorDapp. - -For example, to use version 1.0 of Corda and version 1.0 of the Corda gradle plugins, you'd write: +The following three lines of the ``build.gradle`` file define the Corda version and distribution used to build your CorDapp: .. sourcecode:: groovy ext.corda_release_version = '1.0.0' + ext.corda_release_distribution = 'net.corda' ext.corda_gradle_plugins_version = '1.0.0' You can find the latest published version of both here: https://bintray.com/r3/corda. @@ -94,21 +92,21 @@ is already correctly configured and this is for reference only; dependencies { // Corda integration dependencies - cordaCompile "net.corda:corda-core:$corda_release_version" - cordaCompile "net.corda:corda-finance:$corda_release_version" - cordaCompile "net.corda:corda-jackson:$corda_release_version" - cordaCompile "net.corda:corda-rpc:$corda_release_version" - cordaCompile "net.corda:corda-node-api:$corda_release_version" - cordaCompile "net.corda:corda-webserver-impl:$corda_release_version" - cordaRuntime "net.corda:corda:$corda_release_version" - cordaRuntime "net.corda:corda-webserver:$corda_release_version" - testCompile "net.corda:corda-test-utils:$corda_release_version" + cordaCompile "$corda_release_distribution:corda-core:$corda_release_version" + cordaCompile "$corda_release_distribution:corda-finance:$corda_release_version" + cordaCompile "$corda_release_distribution:corda-jackson:$corda_release_version" + cordaCompile "$corda_release_distribution:corda-rpc:$corda_release_version" + cordaCompile "$corda_release_distribution:corda-node-api:$corda_release_version" + cordaCompile "$corda_release_distribution:corda-webserver-impl:$corda_release_version" + cordaRuntime "$corda_release_distribution:corda:$corda_release_version" + cordaRuntime "$corda_release_distribution:corda-webserver:$corda_release_version" + testCompile "$corda_release_distribution:corda-test-utils:$corda_release_version" // Corda Plugins: dependent flows and services // Identifying a CorDapp by its module in the same project. cordapp project(":cordapp-contracts-states") // Identifying a CorDapp by its fully-qualified name. - cordapp "net.corda:bank-of-corda-demo:1.0" + cordapp "$corda_release_distribution:bank-of-corda-demo:1.0" // Some other dependencies compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version" diff --git a/docs/source/generating-a-node.rst b/docs/source/generating-a-node.rst index eee15b3d5d..7edcd037fe 100644 --- a/docs/source/generating-a-node.rst +++ b/docs/source/generating-a-node.rst @@ -88,7 +88,7 @@ nodes. Here is an example ``Cordform`` task called ``deployNodes`` that creates // No webport property, so no webserver will be created. h2Port 10004 // Includes the corda-finance CorDapp on our node. - cordapps = ["net.corda:corda-finance:$corda_release_version"] + cordapps = ["$corda_release_distribution:corda-finance:$corda_release_version"] } node { name "O=PartyA,L=London,C=GB" @@ -96,7 +96,7 @@ nodes. Here is an example ``Cordform`` task called ``deployNodes`` that creates rpcPort 10006 webPort 10007 h2Port 10008 - cordapps = ["net.corda:corda-finance:$corda_release_version"] + cordapps = ["$corda_release_distribution:corda-finance:$corda_release_version"] // Grants user1 all RPC permissions. rpcUsers = [[ user: "user1", "password": "test", "permissions": ["ALL"]]] } @@ -106,7 +106,7 @@ nodes. Here is an example ``Cordform`` task called ``deployNodes`` that creates rpcPort 10010 webPort 10011 h2Port 10012 - cordapps = ["net.corda:corda-finance:$corda_release_version"] + cordapps = ["$corda_release_distribution:corda-finance:$corda_release_version"] // Grants user1 the ability to start the MyFlow flow. rpcUsers = [[ user: "user1", "password": "test", "permissions": ["StartFlow.net.corda.flows.MyFlow"]]] } diff --git a/docs/source/hello-world-running.rst b/docs/source/hello-world-running.rst index 58e3271c71..357d5a9022 100644 --- a/docs/source/hello-world-running.rst +++ b/docs/source/hello-world-running.rst @@ -25,14 +25,14 @@ service. notary = [validating : true] p2pPort 10002 rpcPort 10003 - cordapps = ["net.corda:corda-finance:$corda_release_version"] + cordapps = ["$corda_release_distribution:corda-finance:$corda_release_version"] } node { name "O=PartyA,L=London,C=GB" p2pPort 10005 rpcPort 10006 webPort 10007 - cordapps = ["net.corda:corda-finance:$corda_release_version"] + cordapps = ["$corda_release_distribution:corda-finance:$corda_release_version"] rpcUsers = [[ user: "user1", "password": "test", "permissions": ["ALL]]] } node { @@ -41,7 +41,7 @@ service. rpcPort 10009 webPort 10010 sshdPort 10024 - cordapps = ["net.corda:corda-finance:$corda_release_version"] + cordapps = ["$corda_release_distribution:corda-finance:$corda_release_version"] rpcUsers = [[ user: "user1", "password": "test", "permissions": ["ALL"]]] } } diff --git a/docs/source/network-map.rst b/docs/source/network-map.rst index efe8110843..49a432aa40 100644 --- a/docs/source/network-map.rst +++ b/docs/source/network-map.rst @@ -1,84 +1,78 @@ Network Map =========== -The network map stores a collection of ``NodeInfo`` objects, each representing another node with which the node can interact. -There are two sources from which a Corda node can retrieve ``NodeInfo`` objects: +The network map is a collection of signed ``NodeInfo`` objects (signed by the node it represents and thus tamper-proof) +forming the set of reachable nodes in a compatbility zone. A node can receive these objects from two sources: -1. the REST protocol with the network map service, which also provides a publishing API, +1. The HTTP network map service if the ``compatibilityZoneURL`` config key is specified. +2. The ``additional-node-infos`` directory within the node's directory. -2. the ``additional-node-infos`` directory. +HTTP network map service +------------------------ +If the node is configured with the ``compatibilityZoneURL`` config then it first uploads its own signed ``NodeInfo`` +to the server (and each time it changes on startup) and then proceeds to download the entire network map. The network map +consists of a list of ``NodeInfo`` hashes. The node periodically polls for the network map (based on the HTTP cache expiry +header) and any new hash entries are downloaded and cached. Entries which no longer exist are deleted from the node's cache. -Protocol Design ---------------- -The node info publishing protocol: +The set of REST end-points for the network map service are as follows. -* Create a ``NodeInfo`` object, and sign it to create a ``SignedNodeInfo`` object. - -* Serialise the signed data and POST the data to the network map server. - -* The network map server validates the signature and acknowledges the registration with a HTTP 200 response, it will return HTTP 400 "Bad Request" if the data failed validation or if the public key wasn't registered with the network. - -* The network map server will sign and distribute the new network map periodically. - -Node side network map update protocol: - -* The Corda node will query the network map service periodically according to the ``Expires`` attribute in the HTTP header. - -* The network map service returns a signed ``NetworkMap`` object which looks as follows: - -.. container:: codeset - - .. sourcecode:: kotlin - - data class NetworkMap { - val nodeInfoHashes: List, - val networkParametersHash: SecureHash - } - -The object contains list of node info hashes and hash of the network parameters data structure (without the signatures). - -* The node updates its local copy of ``NodeInfos`` if it is different from the newly downloaded ``NetworkMap``. - -Network Map service REST API: - -+----------------+-----------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Request method | Path | Description | -+================+===================================+========================================================================================================================================================+ -| POST | /network-map/publish | Publish new ``NodeInfo`` to the network map service, the legal identity in ``NodeInfo`` must match with the identity registered with the doorman. | -+----------------+-----------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------+ -| GET | /network-map | Retrieve ``NetworkMap`` from the server, the ``NetworkMap`` object contains list of node info hashes and ``NetworkParameters`` hash. | -+----------------+-----------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------+ -| GET | /network-map/node-info/{hash} | Retrieve ``NodeInfo`` object with the same hash. | -+----------------+-----------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------+ -| GET | /network-map/parameters/{hash} | Retrieve ``NetworkParameters`` object with the same hash. | -+----------------+-----------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------+ - -TODO: Access control of the network map will be added in the future. ++----------------+-----------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------+ +| Request method | Path | Description | ++================+=========================================+==============================================================================================================================================+ +| POST | /network-map/publish | For the node to upload its signed ``NodeInfo`` object to the network map. | ++----------------+-----------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------+ +| GET | /network-map | Retrieve the current signed network map object. The entire object is signed with the network map certificate which is also attached. | ++----------------+-----------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------+ +| GET | /network-map/node-info/{hash} | Retrieve a signed ``NodeInfo`` as specified in the network map object. | ++----------------+-----------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------+ +| GET | /network-map/network-parameters/{hash} | Retrieve the signed network parameters (see below). The entire object is signed with the network map certificate which is also attached. | ++----------------+-----------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------+ The ``additional-node-infos`` directory --------------------------------------- -Each Corda node reads, and continuously polls, the files contained in a directory named ``additional-node-infos`` inside the node base directory. -Nodes expect to find a serialized ``SignedNodeInfo`` object, the same object which is sent to network map server. - -Whenever a node starts it writes on disk a file containing its own ``NodeInfo``, this file is called ``nodeInfo-XXX`` where ``XXX`` is a long string. - -Hence if an operator wants node A to see node B they can pick B's ``NodeInfo`` file from B base directory and drop it into A's ``additional-node-infos`` directory. +Alongside the HTTP network map service, or as a replacement if the node isn't connected to one, the node polls the +contents of the ``additional-node-infos`` directory located in its base directory. Each file is expected to be the same +signed ``NodeInfo`` object that the network map service vends. These are automtically added to the node's cache and can +be used to supplement or replace the HTTP network map. If the same node is advertised through both mechanisms then the +latest one is taken. +On startup the node generates its own signed node info file, filename of the format ``nodeInfo-${hash}``. To create a simple +network without the HTTP network map service then simply place this file in the ``additional-node-infos`` directory +of every node that's part of this network. Network parameters ------------------ -Network parameters are constants that every node participating in the network needs to agree on and use for interop purposes. -The structure is distributed as a file containing serialized ``SignedData`` with a signature from -a sub-key of the compatibility zone root cert. Network map advertises the hash of currently used network parameters. -The ``NetworkParameters`` structure contains: - * ``minimumPlatformVersion`` - minimum version of Corda platform that is required for nodes in the network. - * ``notaries`` - list of well known and trusted notary identities with information on validation type. - * ``maxMessageSize`` - maximum P2P message size sent over the wire in bytes. - * ``maxTransactionSize`` - maximum permitted transaction size in bytes. - * ``modifiedTime`` - the time the network parameters were created by the CZ operator. - * ``epoch`` - version number of the network parameters. Starting from 1, this will always increment on each new set of parameters. -The set of parameters is still under development and we may find the need to add additional fields. +Network parameters are a set of values that every node participating in the network needs to agree on and use to +correctly interoperate with each other. If the node is using the HTTP network map service then on first startup it will +download the signed network parameters, cache it in a ``network-parameters`` file and apply them on the node. + +.. warning:: If the ``network-parameters`` file is changed and no longer matches what the network map service is advertising +then the node will automatically shutdown. Resolution to this is to delete the incorrect file and restart the node so + that the parameters can be downloaded again. + +.. note:: A future release will support the notion of network parameters changes. + +If the node isn't using a HTTP network map service then it's expected the signed file is provided by some other means. +For such a scenario there is the network bootstrapper tool which in addition to generating the network parameters file +also distributes the node info files to the node directories. More information can be found in :doc:`setting-up-a-corda-network`. + +The current set of network parameters: + +:minimumPlatformVersion: The minimum platform version that the nodes must be running. Any node which is below this will + not start. +:notaries: List of identity and validation type (either validating or non-validating) of the notaries which are permitted + in the compatibility zone. +:maxMessageSize: Maximum allowed P2P message size sent over the wire in bytes. Any message larger than this will be + split up. +:maxTransactionSize: Maximum permitted transaction size in bytes. +:modifiedTime: The time when the network parameters were last modified by the compatibility zone operator. +:epoch: Version number of the network parameters. Starting from 1, this will always increment whenever any of the + parameters change. + +.. note:: ``maxTransactionSize`` is currently not enforced in the node, but will be in a later release. + +More parameters may be added in future releases. diff --git a/docs/source/node-administration.rst b/docs/source/node-administration.rst index fe9b9231fd..5440f30a8e 100644 --- a/docs/source/node-administration.rst +++ b/docs/source/node-administration.rst @@ -73,6 +73,8 @@ Any database browsing tool that supports JDBC can be used, but if you have Intel a tool integrated with your IDE. Just open the database window and add an H2 data source with the above details. You will now be able to browse the tables and row data within them. +.. _jolokia_ref: + Monitoring your node -------------------- diff --git a/docs/source/node-database.rst b/docs/source/node-database.rst index 5d77f2911f..1ec3d35ad2 100644 --- a/docs/source/node-database.rst +++ b/docs/source/node-database.rst @@ -34,12 +34,14 @@ Standalone database ------------------- To run a node against a remote database modify node JDBC connection properties in `dataSourceProperties` entry -and Hibernate properties in `database` entry - see `:ref:`dataSourceProperties`. +and Hibernate properties in `database` entry - see :ref:`Node configuration `. + +.. _sql_server_ref: SQL Azure and SQL Server ```````````````````````` Corda supports SQL Server 2017 (14.0.3006.16) and Azure SQL (12.0.2000.8). -The minimum transaction isolation level ``database.transactionIsolationLevel`` is 'readCommitted'. +The minimum transaction isolation level ``database.transactionIsolationLevel`` is 'READ_COMMITTED'. The property ``database.schema`` is optional. Corda ships with Microsoft JDBC Driver 6.2 for SQLServer out-of-the-box. @@ -47,36 +49,40 @@ Example node configuration for SQL Azure: .. sourcecode:: none -dataSourceProperties { - dataSourceClassName = "com.microsoft.sqlserver.jdbc.SQLServerDataSource" - dataSourceProperties.dataSource.url = "jdbc:sqlserver://[DATABASE_SERVER].database.windows.net:1433;databaseName=[DATABASE]; - encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.database.windows.net;loginTimeout=30" - dataSourceProperties.dataSource.user = [USER] - dataSourceProperties.dataSource.password = [PASSWORD] -} -database { - transactionIsolationLevel = "readCommitted" - schema = [SCHEMA] -} + dataSourceProperties { + dataSourceClassName = "com.microsoft.sqlserver.jdbc.SQLServerDataSource" + dataSourceProperties.dataSource.url = "jdbc:sqlserver://[DATABASE_SERVER].database.windows.net:1433;databaseName=[DATABASE]; + encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.database.windows.net;loginTimeout=30" + dataSourceProperties.dataSource.user = [USER] + dataSourceProperties.dataSource.password = [PASSWORD] + } + database { + transactionIsolationLevel = READ_COMMITTED + schema = [SCHEMA] + } + +.. _postgres_ref: PostgreSQL ```````````````````````` -Corda supports PostgreSQL 9.6 database. -The property ``database.schema`` is optional. The value of ``database.schema`` is automatically wrapped in double quotes -to preserve case-sensitivity (e.g. `AliceCorp` becomes `"AliceCorp"`, without quotes PostgresSQL would treat the value as `alicecorp`). + +Corda supports PostgreSQL 9.6 database preliminarily. +The property ``database.schema`` is optional. Currently only lowercase value is supported, +please ensure your database setup uses lowercase schema names (Corda sends an unquoted schema name +and PostgresSQL interprets the value as a lowercase one e.g. `AliceCorp` becomes `alicecorp`). Corda ships with PostgreSQL JDBC Driver 42.1.4 out-of-the-box. Example node configuration for PostgreSQL: .. sourcecode:: none -dataSourceProperties = { - dataSourceClassName = "org.postgresql.ds.PGSimpleDataSource" - dataSource.url = "jdbc:postgresql://[HOST]:[PORT]/postgres" - dataSource.user = [USER] - dataSource.password = [PASSWORD] -} -database = { - transactionIsolationLevel = READ_COMMITTED - schema = [SCHEMA] -} + dataSourceProperties = { + dataSourceClassName = "org.postgresql.ds.PGSimpleDataSource" + dataSource.url = "jdbc:postgresql://[HOST]:[PORT]/postgres" + dataSource.user = [USER] + dataSource.password = [PASSWORD] + } + database = { + transactionIsolationLevel = READ_COMMITTED + schema = [SCHEMA] + } \ No newline at end of file diff --git a/docs/source/node-explorer.rst b/docs/source/node-explorer.rst index 48c0a96088..c8e15d367b 100644 --- a/docs/source/node-explorer.rst +++ b/docs/source/node-explorer.rst @@ -29,7 +29,7 @@ parties on the network or to exit cash (for itself only). When connected to a *Participant* node a user can only execute cash transaction commands to move cash to other parties on the network. -The Demo Nodes can be started in one of two modes: +The Demo Nodes can be started in one of three modes: 1. Normal @@ -60,14 +60,30 @@ The Demo Nodes can be started in one of two modes: ./gradlew tools:explorer:runSimulationNodes +.. _flow_triage: + +3. Flow triage + + Once again, building on the demonstration Corda network topology described above, this scenario mode triggers + an exception within a flow which can then be visualized using the "Flow Triage" panel within the Explorer. + The "Flow Triage" panel will be enhanced in the future to enable operators to take corrective actions upon flow failures + (eg. retry, terminate, amend and replay) + +**Windows:** + + gradlew.bat tools:explorer:runFlowTriageNodes + +**Other:** + + ./gradlew tools:explorer:runFlowTriageNodes .. note:: 5 Corda nodes will be created on the following port on localhost by default. - * Notary -> 20003 (Does not accept logins) - * Alice -> 20006 - * Bob -> 20009 - * UK Bank Plc -> 20012 (*Issuer node*) - * USA Bank Corp -> 20015 (*Issuer node*) + * Notary -> 20001 (Does not accept logins) + * Alice -> 20004 + * Bob -> 20007 + * UK Bank Plc -> 20010 (*Issuer node*) + * USA Bank Corp -> 20013 (*Issuer node*) Explorer login credentials to the Issuer nodes are defaulted to ``manager`` and ``test``. Explorer login credentials to the Participants nodes are defaulted to ``user1`` and ``test``. diff --git a/docs/source/release-notes.rst b/docs/source/release-notes.rst index 64d9ad8881..e361fcfe98 100644 --- a/docs/source/release-notes.rst +++ b/docs/source/release-notes.rst @@ -1,37 +1,164 @@ Release notes ============= -Here are release notes for each snapshot release from M9 onwards. - Unreleased ---------- + +R3 Corda 3.0 Developer Preview +------------------------------ +This Developer Preview takes us towards the launch of R3 Corda, R3's commercially supported enterprise blockchain platform. + +Whilst the recent major releases of **Corda** ("Open Source") - V1.0 and V2.0 - have focused on providing API stability and +functionality, **R3 Corda** has been primarily focused on non-functional aspects of the platform: performance, scalability, +robustness, security, configurability, manageability, supportability and upgradeability. + +Here is a summary of some of the key new features in this preview, many of which will also appear in the next open +source release: + +- support for :ref:`Azure SQL and SQL Server 2017 ` databases. +- integrated :ref:`database schema management ` tooling using `Liquibase `_ +- completely re-designed :doc:`network-map` Service. +- enabled :ref:`AMQP serialization ` for peer to peer messaging, and vault transaction storage. +- pluggable :ref:`user authentication ` and :ref:`fine-grained access control `. +- re-designed Flow Framework manager in preparation for fully multi-threaded implementation. +- improvements to the Doorman certificate issuance process (including integration with HSMs). +- additional JMX metrics exported via :ref:`Jolokia for monitoring ` and pro-active alert management. +- a secure, remotely accessible, :ref:`SSH server ` in the node with built-in authorization and permissioning to enable remote + node administration without requiring console access to the underlying operating system. +- re-architected and re-designed Corda bridge management for secure P2P connectivity between participants. +- enhanced Explorer tool with new :ref:`flow triage ` user interface panel to visualize all currently running flows. +- preliminary implementation of Business Networks concept (a private sub group within a Corda Compatibility Zone). + +We also continue to make improvements in usability of our Test Framework APIs in preparation for declaring the test +framework API stable (in addition to the already-stabilised core APIs). + +Significant changes implemented in reaching this Developer Preview include: + +* **AMQP**: + AMQP Serialization is now enabled for both peer to peer communication and the writing of states to the vault. This + change brings a serialisation format that will allow us to deliver enhanced security and wire stability. It is a key + prerequisite to enabling different Corda node versions to coexist on the same network and to enable easier upgrades. + + Details on the AMQP serialization framework can be found :ref:`here `. This provides an introduction and + overview of the framework whilst more specific details on object evolution as it relates to serialization is similarly + found in :doc:`serialization-default-evolution` and :doc:`serialization-enum-evolution` respectively. + + .. note:: This release delivers the bulk of our transition from Kryo serialisation to AMQP serialisation. This means that many of the restrictions + that were documented in previous versions of Corda are now enforced. + + In particular, you are advised to review the section titled :ref:`Custom Types `. + To aid with the transition, we have included support in this release for default construction and instantiation of + objects with inaccessible private fields, but it is not guaranteed that this support will continue into future versions; + the restrictions documented at the link above are the canonical source. + +* **New Network Map Service**: + This release introduces the new network map architecture. The network map service has been completely redesigned and + implemented to enable future increased network scalability and redundancy, reduced runtime operational overhead, + support for multiple notaries, and administration of network compatibility zones (CZ) and business networks. + + A Corda Compatibility Zone (CZ) is defined as a grouping of participants and services (notaries, oracles, + doorman, network map server) configured within an operational Corda network to be interoperable and compatible with + each other. + + We introduce the concept of network parameters, which will be used in a future version of Corda to specify precisely + the set of constants (or ranges of constants) upon which a set of nodes need to agree in order to be assured of seamless + inter-operation. Additional security controls ensure that all network map data is now signed, thus reducing the power + of the network operator to tamper with the map. + + This release also adds Hardware Security Module (HSM) support to the doorman service (certificate authority). + By integrating with external HSMs, we have further strengthened the security of issuing network certificates and + signing of network map related data. + + Further information can be found in the :doc:`changelog` and :doc:`network-map` documentation. + +* **Third party database support**: + R3 Corda has been tested against Azure SQL and SQL Server 2017 databases (in addition to the existing default support + of H2 for development mode). This preview adds preliminary support for :ref:`PostgreSQL 9.6 `. + Support for Oracle 11g RC02 and Oracle 12c is currently under development. All required database settings can be + specified in the node configuration file. For configuration details see :doc:`node-database`. + +* **Integrated database migration tooling**: + We have adopted and integrated `Liquibase `_ , an open source database-independent library + for tracking, managing and applying database schema changes in order to ease the evolution (creation and migration) of + CorDapp custom contract schemas and facilitate the operational administration of a Corda nodes database. + We provide tooling to export DDL and data (as SQL statements) to a file to be inspected and/or manually applied by a DBA. + Please see :ref:`database migration ` for further details. + +* **Pluggable user authentication and fine-grained access control**: + All RPC functions are now subject to permission checks (previously these only applied when starting flows). + We have also included experimental support for external user credentials data source and password encryption using the + `Apache Shiro `_ framework. Please see :ref:`RPC security management ` for further details. + +* **Preliminary preview of new bridge management functionality**: + The bridge manager component is responsible for dynamically establishing remote connectivity with participant nodes + in a Corda peer to peer network. A new Bridge manager has been designed and implemented to be used integrally + within a :ref:`Corda node ` or deployed (in the final R3 Corda 3.0 release) as a standalone component in DMZ operational deployments, + where security concerns require separation of infrastructure messaging subsystems. + +* **Preliminary preview of flow triage functionality**: + The explorer GUI was extended with a panel similar to the ``flow watch`` CRaSH shell command. It provides users with a view of all + flows currently executed on the node, with information about success/failure. The "Flow Triage" panel will be enhanced in the future + to enable operators to take corrective actions upon flow failures (eg. retry, terminate, amend and replay). + +* **Experimental preview of a new operational Corda network grouping concept: Business Networks**: + Business Networks are introduced as a way to partition the global population of nodes (a Compatibility Zone) into + independent, possibly overlapping, groups. A Business Network operator (BNO) will have control over which nodes will + be admitted into a Business Network. Some nodes may choose not to register themselves in the global Network Map, and + will therefore remain invisible to nodes outside of their Business Network. Further documentation will be forthcoming + by the final R3 Corda 3.0 release. + + See the "Business Network reference implementation" prototype example in the Explorer tool (instructions in README.md). + +In addition to enhancements focused on non-functional capabilities, this release encompasses a number of functional +improvements, including: + +* Doorman Service + In order to automate a node's network joining process, a new Doorman service has been introduced with this release. + The Doorman's main purpose is to restrict network access only to those nodes whose identity has been confirmed and their network joining request approved. + It issues node-level certificates which are then used by other nodes in the network to confirm a nodes identity and network permissions. + More information on Doorman and how to run it can be found in :doc:`running-doorman`. + +* Hardware Security Module (HSM) for Doorman + To allow for increased security, R3 Corda introduces HSM integration. Doorman certificates (together with their keys) + can now be stored on secured hardware constraining the way those certificates are accessed. Any usage of those certificates + (e.g. data signing or node-level certificate generation) falls into a restrictive process that is automatically audited + and can be configured to involve human-in-the-loop in order to prevent unauthorised access. The HSM integration is embodied + in our new Signing Service. More on this in :doc:`signing-service`. + * X.509 certificates now have an extension that specifies the Corda role the certificate is used for, and the role hierarchy is now enforced in the validation code. This only has impact on those developing integrations with external - PKI solutions, in most cases it is managed transparently by Corda. A formal specification of the extension can be + PKI solutions. In most cases it is managed transparently by Corda. A formal specification of the extension can be found at see :doc:`permissioning-certificate-specification`. -* **Enum Class Evolution** - With the addition of AMQP serialization Corda now supports enum constant evolution. +* Custom Serializers + To allow interop with third party libraries that cannot be recompiled we add functionality that allows custom serializers + to be written for those classes. If needed, a proxy object can be created as an interim step that allows Corda's internal + serializers to operate on those types. A good example of this is the SIMM valuation demo which has a number of such + serializers defined in the plugin/custom serializers package - 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. +Please refer to the :doc:`changelog` for detailed explanations of all new features. -* **AMQP Enabled** +Finally, please note that although this developer preview has not yet been security audited, it is currently being subjected +to a full external secure code review and penetration test. -AMQP Serialization is now enabled for both peer to peer communication and writing states to the vault. This change -brings a stable format Corda can support internally throughout it's lifetime that meets the needs of Corda and our -users. +As per previous major releases, we have provided a comprehensive upgrade notes (:doc:`upgrade-notes`) to ease the upgrade +of CorDapps to R3 Corda 3.0 Developer Preview. In line with our commitment to API stability, code level changes +are fairly minimal, and mostly related to improvements to our nearly API stable test framework. -* **Custom Serializers** +From a build perspective, switching CorDapps built using Corda (the "Open Source" code) to R3 Corda is mostly effortless, +and simply requires setting two gradle build file variables: -To allow interop with third party libraries that cannot be recompiled we add functionality that allows custom serializers -to be written for those classes. If needed, a proxy object can be created as an interim step that allows Corda's internal -serializers to operate on those types. +.. sourcecode:: shell -A good example of this is the SIMM valuation demo which has a number of such serializers defined in the plugin/customserializers package + ext.corda_release_version = 'R3.CORDA-3.0.0-DEV-PREVIEW' + ext.corda_release_distribution = 'com.r3.corda' -Release 2.0 ----------- +Please note this release is distributed under license and should not be used in a Production environment yet. + +We look forward to hearing your feedback on this Developer Preview. + +Corda 2.0 +--------- Following quickly on the heels of the release of Corda 1.0, Corda version 2.0 consolidates a number of security updates for our dependent libraries alongside the reintroduction of the Observer node functionality. This was absent from version 1 but based on user feedback its re-introduction removes the need for complicated "isRelevant()" checks. @@ -46,11 +173,11 @@ and via the versioning APIs. * **Observer Nodes** Adds the facility for transparent forwarding of transactions to some third party observer, such as a regulator. By having -that entity simply run an Observer node they can simply recieve a stream of digitally signed, de-duplicated reports that +that entity simply run an Observer node they can simply receive a stream of digitally signed, de-duplicated reports that can be used for reporting. -Release 1.0 ------------ +Corda 1.0 +--------- Corda 1.0 is finally here! This critical step in the Corda journey enables the developer community, clients, and partners to build on Corda with confidence. @@ -154,253 +281,3 @@ We have provided a comprehensive :doc:`upgrade-notes` to ease the transition of Upgrading to this release is strongly recommended, and you will be safe in the knowledge that core APIs will no longer break. Thank you to all contributors for this release! - -Milestone 14 ------------- - -This release continues with the goal to improve API stability and developer friendliness. There have also been more -bug fixes and other improvements across the board. - -The CorDapp template repository has been replaced with a specific repository for -`Java `_ and `Kotlin `_ -to improve the experience of starting a new project and to simplify the build system. - -It is now possible to specify multiple IP addresses and legal identities for a single node, allowing node operators -more flexibility in setting up nodes. - -A format has been introduced for CorDapp JARs that standardises the contents of CorDapps across nodes. This new format -now requires CorDapps to contain their own external dependencies. This paves the way for significantly improved -dependency management for CorDapps with the release of `Jigsaw (Java Modules) `_. For those using non-gradle build systems it is important -to read :doc:`cordapp-build-systems` to learn more. Those using our ``cordformation`` plugin simply need to update -to the latest version (``0.14.0``) to get the fixes. - -We've now begun the process of demarcating which classes are part of our public API and which ones are internal. -Everything found in ``net.corda.core.internal`` and other packages in the ``net.corda`` namespace which has ``.internal`` in it are -considered internal and not for public use. In a future release any CorDapp using these packages will fail to load, and -when we migrate to Jigsaw these will not be exported. - -The transaction finalisation flow (``FinalityFlow``) has had hooks added for alternative implementations, for example in -scenarios where no single participant in a transaction is aware of the well known identities of all parties. - -DemoBench has a fix for a rare but inconvenient crash that can occur when sharing your display across multiple devices, -e.g. a projector while performing demonstrations in front of an audience. - -Guava types are being removed because Guava does not have backwards compatibility across versions, which has serious -issues when multiple libraries depend on different versions of the library. - -The identity service API has been tweaked, primarily so anonymous identity registration now takes in -AnonymousPartyAndPath rather than the individual components of the identity, as typically the caller will have -an AnonymousPartyAndPath instance. See change log for further detail. - -Upgrading to this release is strongly recommended in order to keep up with the API changes, removal and additions. - -Milestone 13 ------------- - -Following our first public beta in M12, this release continues the work on API stability and user friendliness. Apart -from bug fixes and code refactoring, there are also significant improvements in the Vault Query and the -Identity Service (for more detailed information about what has changed, see :doc:`changelog`). -More specifically: - -The long awaited new **Vault Query** service makes its debut in this release and provides advanced vault query -capabilities using criteria specifications (see ``QueryCriteria``), sorting, and pagination. Criteria specifications -enable selective filtering with and/or composition using multiple operator primitives on standard attributes stored in -Corda internal vault tables (eg. vault_states, vault_fungible_states, vault_linear_states), and also on custom contract -state schemas defined by CorDapp developers when modelling new contract types. Custom queries are specifiable using a -simple but sophisticated builder DSL (see ``QueryCriteriaUtils``). The new Vault Query service is usable by flows and by -RPC clients alike via two simple API functions: ``queryBy()`` and ``trackBy()``. The former provides point-in-time -snapshot queries whilst the later supplements the snapshot with dynamic streaming of updates. -See :doc:`api-vault-query` for full details. - -We have written a comprehensive Hello, World! tutorial, showing developers how to build a CorDapp from start -to finish. The tutorial shows how the core elements of a CorDapp - states, contracts and flows - fit together -to allow your node to handle new business processes. It also explains how you can use our contract and -flow testing frameworks to massively reduce CorDapp development time. - -Certificate checks have been enabled for much of the identity service. These are part of the confidential (anonymous) -identities work, and ensure that parties are actually who they claim to be by checking their certificate path back to -the network trust root (certificate authority). - -To deal with anonymized keys, we've also implemented a deterministic key derivation function that combines logic -from the HMAC-based Extract-and-Expand Key Derivation Function (HKDF) protocol and the BIP32 hardened -parent-private-key -> child-private-key scheme. This function currently supports the following algorithms: -ECDSA secp256K1, ECDSA secpR1 (NIST P-256) and EdDSA ed25519. We are now very close to fully supporting anonymous -identities so as to increase privacy even against validating notaries. - -We have further tightened the set of objects which Corda will attempt to serialise from the stack during flow -checkpointing. As flows are arbitrary code in which it is convenient to do many things, we ended up pulling in a lot of -objects that didn't make sense to put in a checkpoint, such as ``Thread`` and ``Connection``. To minimize serialization -cost and increase security by not allowing certain classes to be serialized, we now support class blacklisting -that will return an ``IllegalStateException`` if such a class is encountered during a checkpoint. Blacklisting supports -superclass and superinterface inheritance and always precedes ``@CordaSerializable`` annotation checking. - -We've also started working on improving user experience when searching, by adding a new RPC to support fuzzy matching -of X.500 names. - -Milestone 12 - First Public Beta --------------------------------- - -One of our busiest releases, lots of changes that take us closer to API stability (for more detailed information about -what has changed, see :doc:`changelog`). In this release we focused mainly on making developers' lives easier. Taking -into account feedback from numerous training courses and meet-ups, we decided to add ``CollectSignaturesFlow`` which -factors out a lot of code which CorDapp developers needed to write to get their transactions signed. -The improvement is up to 150 fewer lines of code in each flow! To have your transaction signed by different parties, you -need only now call a subflow which collects the parties' signatures for you. - -Additionally we introduced classpath scanning to wire-up flows automatically. Writing CorDapps has been made simpler by -removing boiler-plate code that was previously required when registering flows. Writing services such as oracles has also been simplified. - -We made substantial RPC performance improvements (please note that this is separate to node performance, we are focusing -on that area in future milestones): - -- 15-30k requests per second for a single client/server RPC connection. - * 1Kb requests, 1Kb responses, server and client on same machine, parallelism 8, measured on a Dell XPS 17(i7-6700HQ, 16Gb RAM) -- The framework is now multithreaded on both client and server side. -- All remaining bottlenecks are in the messaging layer. - -Security of the key management service has been improved by removing support for extracting private keys, in order that -it can support use of a hardware security module (HSM) for key storage. Instead it exposes functionality for signing data -(typically transactions). The service now also supports multiple signature schemes (not just EdDSA). - -We've added the beginnings of flow versioning. Nodes now reject flow requests if the initiating side is not using the same -flow version. In a future milestone release will add the ability to support backwards compatibility. - -As with the previous few releases we have continued work extending identity support. There are major changes to the ``Party`` -class as part of confidential identities, and how parties and keys are stored in transaction state objects. -See :doc:`changelog` for full details. - -Added new Byzantine fault tolerant (BFT) decentralised notary demo, based on the `BFT-SMaRT protocol `_ -For how to run the demo see: :ref:`notary-demo` - -We continued to work on tools that enable diagnostics on the node. The newest addition to Corda Shell is ``flow watch`` command which -lets the administrator see all flows currently running with result or error information as well as who is the flow initiator. -Here is the view from DemoBench: - -.. image:: resources/flowWatchCmd.png - -We also started work on the strategic wire format (not integrated). - -Milestone 11 ------------- - -Special thank you to `Gary Rowe `_ for his contribution to Corda's Contracts DSL in M11. - -Work has continued on confidential identities, introducing code to enable the Java standard libraries to work with -composite key signatures. This will form the underlying basis of future work to standardise the public key and signature -formats to enable interoperability with other systems, as well as enabling the use of composite signatures on X.509 -certificates to prove association between transaction keys and identity keys. - -The identity work will require changes to existing code and configurations, to replace party names with full X.500 -distinguished names (see RFC 1779 for details on the construction of distinguished names). Currently this is not -enforced, however it will be in a later milestone. - -* "myLegalName" in node configurations will need to be replaced, for example "Bank A" is replaced with - "CN=Bank A,O=Bank A,L=London,C=GB". Obviously organisation, location and country ("O", "L" and "C" respectively) - must be given values which are appropriate to the node, do not just use these example values. -* "networkMap" in node configurations must be updated to match any change to the legal name of the network map. -* If you are using mock parties for testing, try to standardise on the ``DUMMY_NOTARY``, ``DUMMY_BANK_A``, etc. provided - in order to ensure consistency. - -We anticipate enforcing the use of distinguished names in node configurations from M12, and across the network from M13. - -We have increased the maximum message size that we can send to Corda over RPC from 100 KB to 10 MB. - -The Corda node now disables any use of ObjectInputStream to prevent Java deserialisation within flows. This is a security fix, -and prevents the node from deserialising arbitrary objects. - -We've introduced the concept of platform version which is a single integer value which increments by 1 if a release changes -any of the public APIs of the entire Corda platform. This includes the node's public APIs, the messaging protocol, -serialisation, etc. The node exposes the platform version it's on and we envision CorDapps will use this to be able to -run on older versions of the platform to the one they were compiled against. Platform version borrows heavily from Android's -API Level. - -We have revamped the DemoBench user interface. DemoBench will now also be installed as "Corda DemoBench" for both Windows -and MacOSX. The original version was installed as just "DemoBench", and so will not be overwritten automatically by the -new version. - -Milestone 10 ------------- - -Special thank you to `Qian Hong `_, `Marek Skocovsky `_, -`Karel Hajek `_, and `Jonny Chiu `_ for their contributions -to Corda in M10. - -A new interactive **Corda Shell** has been added to the node. The shell lets developers and node administrators -easily command the node by running flows, RPCs and SQL queries. It also provides a variety of commands to monitor -the node. The Corda Shell is based on the popular `CRaSH project `_ and new commands can -be easily added to the node by simply dropping Groovy or Java files into the node's ``shell-commands`` directory. -We have many enhancements planned over time including SSH access, more commands and better tab completion. - -The new "DemoBench" makes it easy to configure and launch local Corda nodes. It is a standalone desktop app that can be -bundled with its own JRE and packaged as either EXE (Windows), DMG (MacOS) or RPM (Linux-based). It has the following -features: - - #. New nodes can be added at the click of a button. Clicking "Add node" creates a new tab that lets you edit the most - important configuration properties of the node before launch, such as its legal name and which CorDapps will be loaded. - #. Each tab contains a terminal emulator, attached to the pseudoterminal of the node. This lets you see console output. - #. You can launch an Corda Explorer instance for each node at the click of a button. Credentials are handed to the Corda - Explorer so it starts out logged in already. - #. Some basic statistics are shown about each node, informed via the RPC connection. - #. Another button launches a database viewer in the system browser. - #. The configurations of all running nodes can be saved into a single ``.profile`` file that can be reloaded later. - -Soft Locking is a new feature implemented in the vault to prevent a node constructing transactions that attempt to use the -same input(s) simultaneously. Such transactions would result in naturally wasted effort when the notary rejects them as -double spend attempts. Soft locks are automatically applied to coin selection (eg. cash spending) to ensure that no two -transactions attempt to spend the same fungible states. - -The basic Amount API has been upgraded to have support for advanced financial use cases and to better integrate with -currency reference data. - -We have added optional out-of-process transaction verification. Any number of external verifier processes may be attached -to the node which can handle loadbalanced verification requests. - -We have also delivered the long waited Kotlin 1.1 upgrade in M10! The new features in Kotlin allow us to write even more -clean and easy to manage code, which greatly increases our productivity. - -This release contains a large number of improvements, new features, library upgrades and bug fixes. For a full list of -changes please see :doc:`changelog`. - -Milestone 9 ------------ - -This release focuses on improvements to resiliency of the core infrastructure, with highlights including a Byzantine -fault tolerant (BFT) decentralised notary, based on the BFT-SMaRT protocol and isolating the web server from the -Corda node. - -With thanks to open source contributor Thomas Schroeter for providing the BFT notary prototype, Corda can now resist -malicious attacks by members of a distributed notary service. If your notary service cluster has seven members, two can -become hacked or malicious simultaneously and the system continues unaffected! This work is still in development stage, -and more features are coming in the next snapshot! - -The web server has been split out of the Corda node as part of our ongoing hardening of the node. We now provide a Jetty -servlet container pre-configured to contact a Corda node as a backend service out of the box, which means individual -webapps can have their REST APIs configured for the specific security environment of that app without affecting the -others, and without exposing the sensitive core of the node to malicious Javascript. - -We have launched a global training programme, with two days of classes from the R3 team being hosted in London, New York -and Singapore. R3 members get 5 free places and seats are going fast, so sign up today. - -We've started on support for confidential identities, based on the key randomisation techniques pioneered by the Bitcoin -and Ethereum communities. Identities may be either anonymous when a transaction is a part of a chain of custody, or fully -legally verified when a transaction is with a counterparty. Type safety is used to ensure the verification level of a -party is always clear and avoid mistakes. Future work will add support for generating new identity keys and providing a -certificate path to show ownership by the well known identity. - -There are even more privacy improvements when a non-validating notary is used; the Merkle tree algorithm is used to hide -parts of the transaction that a non-validating notary doesn't need to see, whilst still allowing the decentralised -notary service to sign the entire transaction. - -The serialisation API has been simplified and improved. Developers now only need to tag types that will be placed in -smart contracts or sent between parties with a single annotation... and sometimes even that isn't necessary! - -Better permissioning in the cash CorDapp, to allow node users to be granted different permissions depending on whether -they manage the issuance, movement or ledger exit of cash tokens. - -We've continued to improve error handling in flows, with information about errors being fed through to observing RPC -clients. - -There have also been dozens of bug fixes, performance improvements and usability tweaks. Upgrading is definitely -worthwhile and will only take a few minutes for most apps. - -For a full list of changes please see :doc:`changelog`. diff --git a/docs/source/running-a-node.rst b/docs/source/running-a-node.rst index 34fde7652b..062daed76f 100644 --- a/docs/source/running-a-node.rst +++ b/docs/source/running-a-node.rst @@ -64,3 +64,13 @@ To enable remote debugging of the node, run the following from the terminal wind ``java -Dcapsule.jvm.args="-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005" -jar corda.jar`` This command line will start the debugger on port 5005 and pause the process awaiting debugger attachment. + +Starting a node with JMX monitoring enabled +------------------------------------------- +To enable export of JMX metrics over HTTP via `Jolokia `_, run the following from the terminal window: + +``java -Dcapsule.jvm.args="-javaagent:drivers/jolokia-jvm-1.3.7-agent.jar=port=7005" -jar corda.jar`` + +This command line will start the node with JMX metrics accessible via HTTP on port 7005. + +See :ref:`Monitoring your node ` for further details. \ No newline at end of file diff --git a/docs/source/running-doorman.rst b/docs/source/running-doorman.rst index 8abe8f4a2b..8bf93f2594 100644 --- a/docs/source/running-doorman.rst +++ b/docs/source/running-doorman.rst @@ -37,7 +37,7 @@ Allowed parameters are: :databaseProperties: database properties -:dataSourceProperties: datasoruce properties +:dataSourceProperties: datasource properties :jiraConfig: The Jira configuration diff --git a/docs/source/serialization.rst b/docs/source/serialization.rst index ed5a278feb..badb1e536c 100644 --- a/docs/source/serialization.rst +++ b/docs/source/serialization.rst @@ -1,6 +1,8 @@ Object serialization ==================== +.. contents:: + What is serialization (and deserialization)? -------------------------------------------- @@ -44,6 +46,8 @@ It's reproduced here as an example of both ways you can do this for a couple of .. warning:: We will be replacing the use of Kryo in the serialization framework and so additional changes here are likely. +.. _amqp_ref: + AMQP ==== @@ -76,7 +80,7 @@ Finally, for the checkpointing of flows Corda will continue to use the existing This separation of serialization schemes into different contexts allows us to use the most suitable framework for that context rather than attempting to force a one size fits all approach. Where ``Kryo`` is more suited to the serialization of a programs stack frames, being more flexible -than our AMQP framework in what it can construct and serialize, that flexibility makes it exceptionally difficult to make secure. Conversly +than our AMQP framework in what it can construct and serialize, that flexibility makes it exceptionally difficult to make secure. Conversely our AMQP framework allows us to concentrate on a robust a secure framework that can be reasoned about thus made safer with far fewer unforeseen security holes. @@ -218,6 +222,8 @@ checked exceptions, or ``CordaRuntimeException``, for unchecked exceptions. Any not conform to ``CordaThrowable`` will be converted to a ``CordaRuntimeException`` with the original exception type and other properties retained within it. +.. _amqp_custom_types_ref: + Custom Types ------------ @@ -282,22 +288,6 @@ serialised form val e2 = e.serialize().deserialize() // e2.c will be 20, not 100!!! -.. warning:: Private properties in Kotlin classes render the class unserializable *unless* a public - getter is manually defined. For example: - - .. container:: codeset - - .. sourcecode:: kotlin - - data class C(val a: Int, private val b: Int) { - // Without this C cannot be serialized - public fun getB() = b - } - - .. note:: This is particularly relevant as IDE's can often point out where they believe a - property can be made private without knowing this can break Corda serialization. Should - this happen then a run time warning will be generated when the class fails to serialize - Setter Instantiation '''''''''''''''''''' @@ -330,6 +320,75 @@ For example: public void setC(int c) { this.c = c; } } +Inaccessible Private Properties +``````````````````````````````` + +Whilst the Corda AMQP serialization framework supports private object properties without publicly +accessible getter methods this development idiom is strongly discouraged. + +For example. + + .. container:: codeset + + Kotlin: + + .. sourcecode:: kotlin + + data class C(val a: Int, private val b: Int) + + Java: + + .. sourcecode:: Java + + class C { + public Integer a; + private Integer b; + + C(Integer a, Integer b) { + this.a = a; + this.b = b; + } + } + +When designing stateful objects is should be remembered that they are not, despite appearances, traditional +programmatic constructs. They are signed over, transformed, serialised, and relationally mapped. As such, +all elements should be publicly accessible by design + +.. warning:: IDEs will indiciate erroneously that properties can be given something other than public + visibility. Ignore this as whilst it will work, as discussed above there are many reasons why this isn't + a good idea and those are beyond the scope of the IDEs inference rules + +Providing a public getter, as per the following example, is acceptable + + .. container:: codeset + + Kotlin: + + .. sourcecode:: kotlin + + data class C(val a: Int, private val b: Int) { + public fun getB() = b + } + + Java: + + .. sourcecode:: Java + + class C { + public Integer a; + private Integer b; + + C(Integer a, Integer b) { + this.a = a; + this.b = b; + } + + public Integer getB() { + return b; + } + } + + Enums ````` diff --git a/docs/source/shell.rst b/docs/source/shell.rst index 86833f002b..3a8fb199c9 100644 --- a/docs/source/shell.rst +++ b/docs/source/shell.rst @@ -25,6 +25,8 @@ The shell via the local terminal In development mode, the shell will display in the node's terminal window. It may be disabled by passing the ``--no-local-shell`` flag when running the node. +.. _ssh_server: + The shell via SSH ----------------- The shell is also accessible via SSH. diff --git a/docs/source/tutorial-clientrpc-api.rst b/docs/source/tutorial-clientrpc-api.rst index 66c9846dae..9e98dec373 100644 --- a/docs/source/tutorial-clientrpc-api.rst +++ b/docs/source/tutorial-clientrpc-api.rst @@ -109,15 +109,10 @@ See more on plugins in :doc:`running-a-node`. Security -------- RPC credentials associated with a Client must match the permission set configured on the server node. -This refers to both authentication (username and password) and role-based authorisation (a permissioned set of RPC operations an +This refers to both authentication (username and password) and authorisation (a permissioned set of RPC operations an authenticated user is entitled to run). -.. note:: Permissions are represented as *String's* to allow RPC implementations to add their own permissioning. Currently - the only permission type defined is *StartFlow*, which defines a list of whitelisted flows an authenticated use may - execute. An administrator user (or a developer) may also be assigned the ``ALL`` permission, which grants access to - any flow. - -In the instructions above the server node permissions are configured programmatically in the driver code: +In the instructions below the server node permissions are configured programmatically in the driver code: .. code-block:: text @@ -125,7 +120,9 @@ In the instructions above the server node permissions are configured programmati val user = User("user", "password", permissions = setOf(startFlow())) val node = startNode("CN=Alice Corp,O=Alice Corp,L=London,C=GB", rpcUsers = listOf(user)).get() -When starting a standalone node using a configuration file we must supply the RPC credentials as follows: +When starting a standalone node using a configuration file we must supply the RPC credentials in the node configuration, +like illustrated in the sample configuration below, or indicate an external database storing user accounts (see +:doc:`clientrpc` for more details): .. code-block:: text @@ -133,6 +130,7 @@ When starting a standalone node using a configuration file we must supply the RP { username=user, password=password, permissions=[ StartFlow.net.corda.finance.flows.CashFlow ] } ] + When using the gradle Cordformation plugin to configure and deploy a node you must supply the RPC credentials in a similar manner: diff --git a/docs/source/upgrade-notes.rst b/docs/source/upgrade-notes.rst index baa2328b4e..c6088e2786 100644 --- a/docs/source/upgrade-notes.rst +++ b/docs/source/upgrade-notes.rst @@ -9,38 +9,369 @@ first public Beta (:ref:`Milestone 12 `), to :ref:`V1.0 ? = null`` field to your class, and + add JPA mappings. For ex., see this example: + +.. sourcecode:: kotlin + + @Entity + @Table(name = "cash_states_v2", + indexes = arrayOf(Index(name = "ccy_code_idx2", columnList = "ccy_code"))) + class PersistentCashState( + + @ElementCollection + @Column(name = "participants") + @CollectionTable(name="cash_states_v2_participants", joinColumns = arrayOf( + JoinColumn(name = "output_index", referencedColumnName = "output_index"), + JoinColumn(name = "transaction_id", referencedColumnName = "transaction_id"))) + override var participants: MutableSet? = null, + +Configuration +^^^^^^^^^^^^^ +Applies to both gradle deployNodes tasks and/or corda node configuration (node.conf). + +* Remove any references to ``networkMap``. + +.. sourcecode:: shell + + networkMap "O=Agent,L=Dallas,C=US" + +* Remove any references to ``advertisedServices`` (including notaries). + +.. sourcecode:: shell + + advertisedServices = ["corda.notary.validating"] + +* Add an explicit notary definition in the Notary node configuration only: + +.. sourcecode:: shell + + notary = [validating : true] Testing -~~~~~~~ +^^^^^^^ + +Contract tests +~~~~~~~~~~~~~~ + +* You must now create a ``MockServices`` object. + + ``MockServices`` provides a mock identity, key and storage service. ``MockServices`` takes as its first argument a + list of the CorDapp packages to scan: + + .. sourcecode:: kotlin + + private val ledgerServices = MockServices(listOf("net.corda.examples.obligation", "net.corda.testing.contracts")) + + ``MockServices`` replaces the use of ``setCordappPackages`` and ``unsetCordappPackages``. + +* ``ledger`` is now defined as a ``MockServices`` method. This means that: + + .. sourcecode:: kotlin + + ledger { + + Becomes: + + .. sourcecode:: kotlin + + ledgerServices.ledger { + +* Within a mock ledger transaction, ``ContractState`` instances are passed to ``input`` and ``output`` as objects + rather than lambdas. For example: + + .. sourcecode:: kotlin + + ledgerServices.ledger { + transaction { + input(OBLIGATION_CONTRACT_ID, DummyState()) + output(OBLIGATION_CONTRACT_ID, oneDollarObligation) + } + } + +* Within a mock ledger transaction, ``CommandData`` instances are passed to ``input`` and ``output`` as objects + rather than lambdas, and the public keys must be passed as a list if there is more than one. For example: + + .. sourcecode:: kotlin + + ledgerServices.ledger { + transaction { + command(alice.publicKey, ObligationContract.Commands.Issue()) + command(listOf(alice.publicKey, bob.publicKey), ObligationContract.Commands.Issue()) + } + } + +* The predefined test identities (e.g. ``ALICE`` and ``MINI_CORP``) have been removed. + + You must now define the test identities explicitly. For example: + + .. sourcecode:: kotlin + + val alice = TestIdentity(CordaX500Name(organisation = "Alice", locality = "TestLand", country = "GB")) + + ``TestIdentity`` exposes methods to get the ``name``, ``keyPair``, ``publicKey``, ``party`` and ``identity`` of the + underlying ``TestIdentity`` + +* Explicit invocation of transaction transformation (ie. using ``TransactionBuilder``) requires serialization engine + to be initialized. In unit test this can be achieved by using the following jUnit rule: + + .. sourcecode:: kotlin + + @Rule + @JvmField + val testSerialization = SerializationEnvironmentRule() + +Flow tests +~~~~~~~~~~ * The registration mechanism for CorDapps in ``MockNetwork`` unit tests has changed. - It is now done via the ``cordappPackages`` constructor parameter of MockNetwork. - This takes a list of `String` values which should be the - package names of the CorDapps containing the contract verification code you wish to load. + It is now done via the ``cordappPackages`` constructor parameter of MockNetwork. This takes a list of ``String`` + values which should be the package names of the CorDapps containing the contract verification code you wish to load. The ``unsetCordappPackages`` method is now redundant and has been removed. +* Creation of Notaries in ``MockNetwork`` unit tests has changed. + + Previously the API call ``createNotaryNode(legalName = CordaX500ame(...))`` would be used to create a notary: + + .. sourcecode:: kotlin + + val notary = mockNetwork.createNotaryNode(legalName = CordaX500Name("Notary", "London", "UK")) + + Notaries are now defined as part of ``MockNetwork`` creation using ``notarySpecs``, as in the following example: + + .. sourcecode:: kotlin + + mockNetwork = MockNetwork(notarySpecs = listOf(MockNetwork.NotarySpec(CordaX500Name("Notary","London","UK")))) + +* A notary is no longer specified when creating a standard node using the ``createPartyNode`` API call. + + Previously: + + .. sourcecode:: kotlin + + mockNetwork.createPartyNode(notary.network.myAddress, CordaX500Name("Node", "Madrid", "ES")) + + Becomes: + + .. sourcecode:: kotlin + + mockNetwork.createPartyNode(CordaX500Name("Node", "Madrid", "ES")) + +* Utility node creation API method ``createSomeNodes(...)`` has been removed, and nodes must be created individually. + + Previously: + + .. sourcecode:: java + + MockNetwork.BasketOfNodes nodes = net.createSomeNodes(3); + nodeA = nodes.getPartyNodes().get(0); + nodeB = nodes.getPartyNodes().get(1); + nodeC = nodes.getPartyNodes().get(2); + + Becomes: + + .. sourcecode:: java + + nodeA = net.createNode(new MockNodeParameters()); + nodeB = net.createNode(new MockNodeParameters()); + nodeC = net.createNode(new MockNodeParameters()); + List> nodes = Arrays.asList(nodeA, nodeB, nodeC); + +* Flow framework instantiation of a flow has a slight variation in start syntax: + + Previously: + + .. sourcecode:: java + + CordaFuture future = nodeA.getServices().startFlow(flow).getResultFuture(); + + Becomes: + + .. sourcecode:: java + + CordaFuture future = startFlow(nodeA.getServices(), flow).getResultFuture(); + +* ``StartedNodeServices.startFlow`` must now be imported from ``net.corda.testing.node`` + +* Do not use ``node.internals`` to register flows: + + Previous code would often look as follows: + + .. sourcecode:: kotlin + + protected fun registerFlowsAndServices(node: StartedNode) { + val mockNode = node.internals + mockNode.registerInitiatedFlow(MyCustomFlow::class.java) + } + + Becomes: + + .. sourcecode:: kotlin + + protected fun registerFlowsAndServices(mockNode: StartedNode) { + mockNode.registerInitiatedFlow(MyCustomFlow::class.java) + } + +* Do not use ``node.internals`` to register Corda services + + Previously: + + .. sourcecode:: kotlin + + node.internals.installCordaService(CustomService::class.java) + + Becomes: + + .. sourcecode:: kotlin + + node.services.cordaService(CustomService::class.java) + +Better yet, use node factory to organize both register flows and services, for example, create class as follows: + + .. sourcecode:: kotlin + + class PrimesOracleNode(args: MockNodeArgs) : MockNetwork.MockNode(args) { + override fun start() = super.start().apply { + registerInitiatedFlow(QueryHandler::class.java) + registerInitiatedFlow(SignHandler::class.java) + services.cordaService(net.corda.examples.oracle.service.service.Oracle::class.java) + } + } + + and then pass it to ``createNode``: + + .. sourcecode:: kotlin + + val oracle = mockNet.createNode(MockNodeParameters(legalName = CordaX500Name("Oracle", "New York", "US")), ::PrimesOracleNode) + +Node driver +~~~~~~~~~~~ + +* ``User`` has been moved from ``net.corda.nodeapi.User`` to ``net.corda.nodeapi.internal.config.User`` + +* Notaries are defined by passing a list of ``NotarySpec`` objects to ``driver`` using the ``notarySpecs`` argument, + instead of being defined manually in the driver block. + + ``notarySpecs`` defaults to providing a single validating notary + +* The ``waitForAllNodesToFinish`` function has been removed. It has been replaced with a ``waitForAllNodesToFinish`` + argument to ``driver`` + +* No longer specify advertised services to the ``DriverDSL`` when starting nodes: + + Previously: + + .. sourcecode:: kotlin + + driver { + startNode(providedName = CordaX500Name("Controller", "London", "GB"), advertisedServices = setOf(ServiceInfo(ValidatingNotaryService.type))) + + Becomes: + + .. sourcecode:: kotlin + + driver { + startNode(providedName = CordaX500Name("Controller", "London", "GB")), + +Finance +^^^^^^^ + +* ``CASH_PROGRAM_ID`` has been moved to ``Cash.PROGRAM_ID``, where ``Cash`` is defined in the + ``import net.corda.finance.contracts.asset`` package + V1.0 to V2.0 ------------ @@ -63,14 +394,14 @@ Build * MockNetwork has moved. - A new test driver module dependency needs to be including in your project: `corda-node-driver`. To continue using the + A new test driver module dependency needs to be including in your project: ``corda-node-driver``. To continue using the mock network for testing, add the following entry to your gradle build file: .. sourcecode:: shell - testCompile "net.corda:corda-node-driver:$corda_release_version" + testCompile "$corda_release_distribution:corda-node-driver:$corda_release_version" -.. note:: you may only need `testCompile "net.corda:corda-test-utils:$corda_release_version"` if not using the Driver DSL. +.. note:: you may only need `testCompile "$corda_release_distribution:corda-test-utils:$corda_release_version"` if not using the Driver DSL. Configuration ^^^^^^^^^^^^^ @@ -91,7 +422,7 @@ Use the automatic imports feature of IntelliJ to intelligently resolve the new i * Missing imports for contract types. - CommercialPaper and Cash are now contained within the `finance` module, as are associated helpers functions. + CommercialPaper and Cash are now contained within the ``finance`` module, as are associated helpers functions. For example: ``import net.corda.contracts.ICommercialPaperState`` becomes ``import net.corda.finance.contracts.ICommercialPaperState`` @@ -105,7 +436,7 @@ Use the automatic imports feature of IntelliJ to intelligently resolve the new i * Missing imports for utility functions. - Many common types and helper methods have been consolidated into `net.corda.core.utilities` package. + Many common types and helper methods have been consolidated into ``net.corda.core.utilities`` package. For example: ``import net.corda.core.crypto.commonName`` becomes ``import net.corda.core.utilities.commonName`` @@ -170,7 +501,7 @@ Flow framework Node services (ServiceHub) ^^^^^^^^^^^^^^^^^^^^^^^^^^ -* VaultQueryService: unresolved reference to `vaultQueryService`. +* VaultQueryService: unresolved reference to ``vaultQueryService``. Replace all references to ``.vaultQueryService`` with ``.vaultService``. Previously there were two vault APIs. Now there is a single unified API with the same functions: ``VaultService``. @@ -191,7 +522,7 @@ Node services (ServiceHub) RPC Client ^^^^^^^^^^ -* Missing API methods on `CordaRPCOps` interface. +* Missing API methods on ``CordaRPCOps`` interface. * Calls to ``verifiedTransactionsFeed()`` and ``verifiedTransactions()`` have been replaced with: ``internalVerifiedTransactionsSnapshot()`` and ``internalVerifiedTransactionsFeed()`` respectively @@ -199,7 +530,7 @@ RPC Client This is in preparation for the planned integration of Intel SGX™, which will encrypt the transactions feed. Apps that use this API will not work on encrypted ledgers: you should probably be using the vault query API instead. - * Accessing the `networkMapCache` via ``services.nodeInfo().legalIdentities`` returns a list of identities. + * Accessing the ``networkMapCache`` via ``services.nodeInfo().legalIdentities`` returns a list of identities. The first element in the list is the Party object referring to a node's single identity. This is in preparation for allowing a node to host multiple separate identities in future. @@ -207,15 +538,15 @@ RPC Client Testing ^^^^^^^ -Please note that `Clauses` have been removed completely as of V1.0. +Please note that ``Clauses`` have been removed completely as of V1.0. We will be revisiting this capability in a future release. * CorDapps must be explicitly registered in ``MockNetwork`` unit tests. This is done by calling ``setCordappPackages``, an extension helper function in the ``net.corda.testing`` package, - on the first line of your `@Before` method. This takes a variable number of `String` arguments which should be the + on the first line of your ``@Before`` method. This takes a variable number of ``String`` arguments which should be the package names of the CorDapps containing the contract verification code you wish to load. - You should unset CorDapp packages in your `@After` method by using ``unsetCordappPackages()`` after `stopNodes()`. + You should unset CorDapp packages in your ``@After`` method by using ``unsetCordappPackages()`` after ``stopNodes()``. * CorDapps must be explicitly registered in ``DriverDSL`` and ``RPCDriverDSL`` integration tests. @@ -225,7 +556,7 @@ We will be revisiting this capability in a future release. Finance ^^^^^^^ -* `FungibleAsset` interface simplification. +* ``FungibleAsset`` interface simplification. The ``FungibleAsset`` interface has been made simpler. The ``Commands`` grouping interface that included the ``Move``, ``Issue`` and ``Exit`` interfaces have all been removed, while the ``move`` function has @@ -233,10 +564,10 @@ Finance The following errors may be reported: - * override nothing (FungibleAsset): `move` - * not a subtype of overridden FungibleAsset: `withNewOwner` - * no longer need to override `override val contractHash: SecureHash? = null` - * need to override `override val contract: Class? = null` + * override nothing (FungibleAsset): ``move`` + * not a subtype of overridden FungibleAsset: ``withNewOwner`` + * no longer need to override ``override val contractHash: SecureHash? = null`` + * need to override ``override val contract: Class? = null`` Miscellaneous @@ -266,7 +597,7 @@ Gotchas Core data structures ^^^^^^^^^^^^^^^^^^^^ -* `TransactionBuilder` changes. +* ``TransactionBuilder`` changes. Use convenience class ``StateAndContract`` instead of ``TransactionBuilder.withItems()`` for passing around a state and its contract. @@ -274,7 +605,7 @@ Core data structures * Transaction building DSL changes: * now need to explicitly pass the ContractClassName into all inputs and outputs. - * `ContractClassName` refers to the class containing the “verifier” method. + * ``ContractClassName`` refers to the class containing the “verifier” method. * Contract verify method signature change. @@ -344,15 +675,15 @@ Build * Gradle dependency reference changes. - Module name has changed to include `corda` in the artifacts jar name: + Module name has changed to include ``corda`` in the artifacts jar name: .. sourcecode:: shell - compile "net.corda:core:$corda_release_version" -> compile "net.corda:corda-core:$corda_release_version" - compile "net.corda:finance:$corda_release_version" -> compile "net.corda:corda-finance:$corda_release_version" - compile "net.corda:jackson:$corda_release_version" -> compile "net.corda:corda-jackson:$corda_release_version" - compile "net.corda:node:$corda_release_version" -> compile "net.corda:corda-node:$corda_release_version" - compile "net.corda:rpc:$corda_release_version" -> compile "net.corda:corda-rpc:$corda_release_version" + compile "$corda_release_distribution:core:$corda_release_version" -> compile "$corda_release_distribution:corda-core:$corda_release_version" + compile "$corda_release_distribution:finance:$corda_release_version" -> compile "$corda_release_distribution:corda-finance:$corda_release_version" + compile "$corda_release_distribution:jackson:$corda_release_version" -> compile "$corda_release_distribution:corda-jackson:$corda_release_version" + compile "$corda_release_distribution:node:$corda_release_version" -> compile "$corda_release_distribution:corda-node:$corda_release_version" + compile "$corda_release_distribution:rpc:$corda_release_version" -> compile "$corda_release_distribution:corda-rpc:$corda_release_version" Node services (ServiceHub) ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -367,10 +698,10 @@ Finance * Financial asset contracts (Cash, CommercialPaper, Obligations) are now a standalone CorDapp within the **finance** module. - Need to import from respective package within `finance` module: + Need to import from respective package within ``finance`` module: eg. ``net.corda.finance.contracts.asset.Cash`` - Likewise, need to import associated asset flows from respective package within `finance` module: + Likewise, need to import associated asset flows from respective package within ``finance`` module: eg. ``net.corda.finance.flows.CashIssueFlow`` ``net.corda.finance.flows.CashIssueAndPaymentFlow`` ``net.corda.finance.flows.CashExitFlow`` @@ -378,4 +709,4 @@ Finance * Moved ``finance`` gradle project files into a ``net.corda.finance`` package namespace. This may require adjusting imports of Cash flow references and also of ``StartFlow`` permission in ``gradle.build`` files. - Associated flows (`Cash*Flow`, `TwoPartyTradeFlow`, `TwoPartyDealFlow`) must now be imported from this package. + Associated flows (``Cash*Flow``, ``TwoPartyTradeFlow``, ``TwoPartyDealFlow``) must now be imported from this package. diff --git a/gradle-plugins/cordapp/src/main/kotlin/net/corda/plugins/CordappPlugin.kt b/gradle-plugins/cordapp/src/main/kotlin/net/corda/plugins/CordappPlugin.kt index 624194fd32..62119cf0f5 100644 --- a/gradle-plugins/cordapp/src/main/kotlin/net/corda/plugins/CordappPlugin.kt +++ b/gradle-plugins/cordapp/src/main/kotlin/net/corda/plugins/CordappPlugin.kt @@ -60,9 +60,9 @@ class CordappPlugin : Plugin { excludes.none { exclude -> (exclude["group"] == dep.group) && (exclude["name"] == dep.name) } } filteredDeps.forEach { - // net.corda or com.r3.corda.enterprise may be a core dependency which shouldn't be included in this cordapp so give a warning + // net.corda or com.r3.corda may be a core dependency which shouldn't be included in this cordapp so give a warning val group = it.group?.toString() ?: "" - if (group.startsWith("net.corda.") || group.startsWith("com.r3.corda.enterprise.")) { + if (group.startsWith("net.corda.") || group.startsWith("com.r3.corda.")) { project.logger.warn("You appear to have included a Corda platform component ($it) using a 'compile' or 'runtime' dependency." + "This can cause node stability problems. Please use 'corda' instead." + "See http://docs.corda.net/cordapp-build-systems.html") diff --git a/gradle-plugins/cordformation/src/main/kotlin/net/corda/plugins/Cordformation.kt b/gradle-plugins/cordformation/src/main/kotlin/net/corda/plugins/Cordformation.kt index 26878fa357..43444ca270 100644 --- a/gradle-plugins/cordformation/src/main/kotlin/net/corda/plugins/Cordformation.kt +++ b/gradle-plugins/cordformation/src/main/kotlin/net/corda/plugins/Cordformation.kt @@ -55,7 +55,8 @@ class Cordformation : Plugin { override fun apply(project: Project) { Utils.createCompileConfiguration("cordapp", project) Utils.createRuntimeConfiguration(CORDFORMATION_TYPE, project) - val jolokiaVersion = project.rootProject.ext("jolokia_version") + // TODO: improve how we re-use existing declared external variables from root gradle.build + val jolokiaVersion = try { project.rootProject.ext("jolokia_version") } catch (e: Exception) { "1.3.7" } project.dependencies.add(CORDFORMATION_TYPE, "org.jolokia:jolokia-jvm:$jolokiaVersion:agent") } } diff --git a/gradle-plugins/cordformation/src/main/kotlin/net/corda/plugins/Node.kt b/gradle-plugins/cordformation/src/main/kotlin/net/corda/plugins/Node.kt index f79249f82e..e7e5b3fc1c 100644 --- a/gradle-plugins/cordformation/src/main/kotlin/net/corda/plugins/Node.kt +++ b/gradle-plugins/cordformation/src/main/kotlin/net/corda/plugins/Node.kt @@ -128,7 +128,8 @@ class Node(private val project: Project) : CordformNode() { * Installs the jolokia monitoring agent JAR to the node/drivers directory */ private fun installAgentJar() { - val jolokiaVersion = project.rootProject.ext("jolokia_version") + // TODO: improve how we re-use existing declared external variables from root gradle.build + val jolokiaVersion = try { project.rootProject.ext("jolokia_version") } catch (e: Exception) { "1.3.7" } val agentJar = project.configuration("runtime").files { (it.group == "org.jolokia") && (it.name == "jolokia-jvm") && diff --git a/network-management/README.md b/network-management/README.md index 33929abdd0..be4a252456 100644 --- a/network-management/README.md +++ b/network-management/README.md @@ -28,12 +28,12 @@ To run the HSM signing server: ``` cd network-management -java -jar capsule-hsm/build/libs/hsm-.jar --config-file hsm.conf +java -jar capsule-hsm/build/libs/hsm-.jar --configFile hsm.conf ``` For a list of options the HSM signing server takes, run with the `--help` option: ``` -java -jar capsule-hsm/build/libs/hsm-3.0-.jar --help +java -jar capsule-hsm/build/libs/hsm-.jar --help ``` #Configuring network management service diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentCertificateRequestStorage.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentCertificateRequestStorage.kt index 339fcb7978..ed987f7358 100644 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentCertificateRequestStorage.kt +++ b/network-management/src/main/kotlin/com/r3/corda/networkmanage/common/persistence/PersistentCertificateRequestStorage.kt @@ -145,7 +145,7 @@ class PersistentCertificateRequestStorage(private val database: CordaPersistence // Also, at the moment we assume that once the CSR is approved it cannot be rejected. // What if we approved something by mistake. val duplicates = session.createQuery(query).resultList.filter { - it.status != RequestStatus.REJECTED + it.status !=RequestStatus.REJECTED } return Pair(legalName, if (duplicates.isEmpty()) null else "Duplicate legal name") diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/webservice/NodeInfoWebService.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/webservice/NodeInfoWebService.kt index 2ac26743e2..7a98513b96 100644 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/webservice/NodeInfoWebService.kt +++ b/network-management/src/main/kotlin/com/r3/corda/networkmanage/doorman/webservice/NodeInfoWebService.kt @@ -41,7 +41,9 @@ class NodeInfoWebService(private val nodeInfoStorage: NodeInfoStorage, private val networkMapCache: LoadingCache> = CacheBuilder.newBuilder() .expireAfterWrite(config.cacheTimeout, TimeUnit.MILLISECONDS) - .build(CacheLoader.from { _ -> Pair(networkMapStorage.getCurrentNetworkMap(), networkMapStorage.getCurrentNetworkParameters()) }) + .build(CacheLoader.from { _ -> + Pair(networkMapStorage.getCurrentNetworkMap() + , networkMapStorage.getCurrentNetworkParameters()) }) @POST @Path("publish") @@ -60,7 +62,7 @@ class NodeInfoWebService(private val nodeInfoStorage: NodeInfoStorage, is NetworkMapNotInitialisedException -> status(Response.Status.SERVICE_UNAVAILABLE).entity(e.message) is InvalidPlatformVersionException -> status(Response.Status.BAD_REQUEST).entity(e.message) is IllegalArgumentException, is InvalidKeyException, is SignatureException -> status(Response.Status.UNAUTHORIZED).entity(e.message) - // Rethrow e if its not one of the expected exception, the server will return http 500 internal error. + // Rethrow e if its not one of the expected exception, the server will return http 500 internal error. else -> throw e } }.build() diff --git a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/configuration/Configuration.kt b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/configuration/Configuration.kt index 6986f3a862..a3215904fd 100644 --- a/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/configuration/Configuration.kt +++ b/network-management/src/main/kotlin/com/r3/corda/networkmanage/hsm/configuration/Configuration.kt @@ -61,7 +61,7 @@ data class Parameters(val dataSourceProperties: Properties, fun parseParameters(vararg args: String): Parameters { val argConfig = args.toConfigWithOptions { accepts("basedir", "Overriding configuration filepath, default to current directory.").withRequiredArg().defaultsTo(".").describedAs("filepath") - accepts("config-file", "Overriding configuration file.").withRequiredArg().describedAs("filepath") + accepts("configFile", "Overriding configuration file.").withRequiredArg().defaultsTo("node.conf").describedAs("filepath") } // The config-file option is changed to configFile diff --git a/network-management/src/main/resources/migration/network-manager.changelog-init.xml b/network-management/src/main/resources/migration/network-manager.changelog-init.xml index 59a5f4985e..d1110bb60a 100644 --- a/network-management/src/main/resources/migration/network-manager.changelog-init.xml +++ b/network-management/src/main/resources/migration/network-manager.changelog-init.xml @@ -40,6 +40,7 @@ + diff --git a/network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/doorman/DoormanIntegrationTest.kt b/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/persistence/PersitenceNodeInfoStorageTest.kt similarity index 100% rename from network-management/src/integration-test/kotlin/com/r3/corda/networkmanage/doorman/DoormanIntegrationTest.kt rename to network-management/src/test/kotlin/com/r3/corda/networkmanage/common/persistence/PersitenceNodeInfoStorageTest.kt diff --git a/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/signer/NetworkMapSignerTest.kt b/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/signer/NetworkMapSignerTest.kt index 71926c7fac..602c04bff2 100644 --- a/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/signer/NetworkMapSignerTest.kt +++ b/network-management/src/test/kotlin/com/r3/corda/networkmanage/common/signer/NetworkMapSignerTest.kt @@ -12,6 +12,7 @@ import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair import net.corda.nodeapi.internal.network.NetworkMap import net.corda.nodeapi.internal.network.SignedNetworkMap import net.corda.testing.common.internal.testNetworkParameters +import net.corda.testing.common.internal.testNetworkParameters import net.corda.testing.internal.createDevIntermediateCaCertPath import org.junit.Before import org.junit.Test diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/crypto/X509Utilities.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/crypto/X509Utilities.kt index fb2e512d38..d17d9cb26f 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/crypto/X509Utilities.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/crypto/X509Utilities.kt @@ -7,8 +7,6 @@ import net.corda.core.crypto.random63BitValue import net.corda.core.internal.CertRole import net.corda.core.internal.reader import net.corda.core.internal.writer -import net.corda.core.identity.CordaX500Name -import net.corda.core.internal.* import net.corda.core.utilities.days import net.corda.core.utilities.millis import org.bouncycastle.asn1.* 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 663a153cbd..9293729306 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 @@ -96,7 +96,7 @@ class EvolutionSerializer( old.fields.forEach { val returnType = it.getTypeAsClass(factory.classloader) oldArgs[it.name] = OldParam( - returnType, idx++, PropertySerializer.make(it.name, null, returnType, factory)) + returnType, idx++, PropertySerializer.make(it.name, PublicPropertyReader(null), returnType, factory)) } val readers = constructor.parameters.map { diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/ObjectSerializer.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/ObjectSerializer.kt index 6cba3bbea5..a9d099b2e3 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/ObjectSerializer.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/ObjectSerializer.kt @@ -26,6 +26,8 @@ open class ObjectSerializer(val clazz: Type, factory: SerializerFactory) : AMQPS propertiesForSerialization(kotlinConstructor, clazz, factory) } + fun getPropertySerializers() = propertySerializers + private val typeName = nameForType(clazz) override val typeDescriptor = Symbol.valueOf("$DESCRIPTOR_DOMAIN:${fingerprintForType(type, factory)}") diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/PropertySerializer.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/PropertySerializer.kt index d296a8fd91..af7c089552 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/PropertySerializer.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/PropertySerializer.kt @@ -1,17 +1,74 @@ package net.corda.nodeapi.internal.serialization.amqp -import net.corda.core.utilities.contextLogger +import net.corda.core.utilities.loggerFor import org.apache.qpid.proton.amqp.Binary import org.apache.qpid.proton.codec.Data import java.lang.reflect.Method import java.lang.reflect.Type +import java.lang.reflect.Field import kotlin.reflect.full.memberProperties import kotlin.reflect.jvm.javaGetter +import kotlin.reflect.jvm.kotlinProperty + +abstract class PropertyReader { + abstract fun read(obj: Any?): Any? + abstract fun isNullable(): Boolean +} + +class PublicPropertyReader(private val readMethod: Method?) : PropertyReader() { + init { + readMethod?.isAccessible = true + } + + private fun Method.returnsNullable(): Boolean { + try { + val returnTypeString = this.declaringClass.kotlin.memberProperties.firstOrNull { it.javaGetter == this }?.returnType?.toString() ?: "?" + return returnTypeString.endsWith('?') || returnTypeString.endsWith('!') + } catch (e: kotlin.reflect.jvm.internal.KotlinReflectionInternalError) { + // This might happen for some types, e.g. kotlin.Throwable? - the root cause of the issue is: https://youtrack.jetbrains.com/issue/KT-13077 + // TODO: Revisit this when Kotlin issue is fixed. + + loggerFor().error("Unexpected internal Kotlin error", e) + return true + } + } + + override fun read(obj: Any?): Any? { + return readMethod!!.invoke(obj) + } + + override fun isNullable(): Boolean = readMethod?.returnsNullable() ?: false +} + +class PrivatePropertyReader(val field: Field, parentType: Type) : PropertyReader() { + init { + loggerFor().warn("Create property Serializer for private property '${field.name}' not " + + "exposed by a getter on class '$parentType'\n" + + "\tNOTE: This behaviour will be deprecated at some point in the future and a getter required") + } + + override fun read(obj: Any?): Any? { + field.isAccessible = true + val rtn = field.get(obj) + field.isAccessible = false + return rtn + } + + override fun isNullable() = try { + field.kotlinProperty?.returnType?.isMarkedNullable ?: false + } catch (e: kotlin.reflect.jvm.internal.KotlinReflectionInternalError) { + // This might happen for some types, e.g. kotlin.Throwable? - the root cause of the issue is: https://youtrack.jetbrains.com/issue/KT-13077 + // TODO: Revisit this when Kotlin issue is fixed. + loggerFor().error("Unexpected internal Kotlin error", e) + true + } +} + /** * Base class for serialization of a property of an object. */ -sealed class PropertySerializer(val name: String, val readMethod: Method?, val resolvedType: Type) { +sealed class PropertySerializer(val name: String, val propertyReader: PropertyReader, val resolvedType: Type) { abstract fun writeClassInfo(output: SerializationOutput) abstract fun writeProperty(obj: Any?, data: Data, output: SerializationOutput) abstract fun readProperty(obj: Any?, schemas: SerializationSchemas, input: DeserializationInput): Any? @@ -44,25 +101,11 @@ sealed class PropertySerializer(val name: String, val readMethod: Method?, val r } private fun generateMandatory(): Boolean { - return isJVMPrimitive || readMethod?.returnsNullable() == false - } - - private fun Method.returnsNullable(): Boolean { - try { - val returnTypeString = this.declaringClass.kotlin.memberProperties.firstOrNull { it.javaGetter == this }?.returnType?.toString() ?: "?" - return returnTypeString.endsWith('?') || returnTypeString.endsWith('!') - } catch (e: kotlin.reflect.jvm.internal.KotlinReflectionInternalError) { - // This might happen for some types, e.g. kotlin.Throwable? - the root cause of the issue is: https://youtrack.jetbrains.com/issue/KT-13077 - // TODO: Revisit this when Kotlin issue is fixed. - logger.error("Unexpected internal Kotlin error", e) - return true - } + return isJVMPrimitive || !(propertyReader.isNullable()) } companion object { - private val logger = contextLogger() - fun make(name: String, readMethod: Method?, resolvedType: Type, factory: SerializerFactory): PropertySerializer { - readMethod?.isAccessible = true + fun make(name: String, readMethod: PropertyReader, resolvedType: Type, factory: SerializerFactory): PropertySerializer { if (SerializerFactory.isPrimitive(resolvedType)) { return when (resolvedType) { Char::class.java, Character::class.java -> AMQPCharPropertySerializer(name, readMethod) @@ -78,7 +121,8 @@ sealed class PropertySerializer(val name: String, val readMethod: Method?, val r * A property serializer for a complex type (another object). */ class DescribedTypePropertySerializer( - name: String, readMethod: Method?, + name: String, + readMethod: PropertyReader, resolvedType: Type, private val lazyTypeSerializer: () -> AMQPSerializer<*>) : PropertySerializer(name, readMethod, resolvedType) { // This is lazy so we don't get an infinite loop when a method returns an instance of the class. @@ -90,12 +134,15 @@ sealed class PropertySerializer(val name: String, val readMethod: Method?, val r } } - override fun readProperty(obj: Any?, schemas: SerializationSchemas, input: DeserializationInput): Any? = ifThrowsAppend({ nameForDebug }) { + override fun readProperty( + obj: Any?, + schemas: SerializationSchemas, + input: DeserializationInput): Any? = ifThrowsAppend({ nameForDebug }) { input.readObjectOrNull(obj, schemas, resolvedType) } override fun writeProperty(obj: Any?, data: Data, output: SerializationOutput) = ifThrowsAppend({ nameForDebug }) { - output.writeObjectOrNull(readMethod!!.invoke(obj), data, resolvedType) + output.writeObjectOrNull(propertyReader.read(obj), data, resolvedType) } private val nameForDebug = "$name(${resolvedType.typeName})" @@ -104,7 +151,10 @@ sealed class PropertySerializer(val name: String, val readMethod: Method?, val r /** * A property serializer for most AMQP primitive type (Int, String, etc). */ - class AMQPPrimitivePropertySerializer(name: String, readMethod: Method?, resolvedType: Type) : PropertySerializer(name, readMethod, resolvedType) { + class AMQPPrimitivePropertySerializer( + name: String, + readMethod: PropertyReader, + resolvedType: Type) : PropertySerializer(name, readMethod, resolvedType) { override fun writeClassInfo(output: SerializationOutput) {} override fun readProperty(obj: Any?, schemas: SerializationSchemas, input: DeserializationInput): Any? { @@ -112,7 +162,7 @@ sealed class PropertySerializer(val name: String, val readMethod: Method?, val r } override fun writeProperty(obj: Any?, data: Data, output: SerializationOutput) { - val value = readMethod!!.invoke(obj) + val value = propertyReader.read(obj) if (value is ByteArray) { data.putObject(Binary(value)) } else { @@ -126,7 +176,7 @@ sealed class PropertySerializer(val name: String, val readMethod: Method?, val r * value of the character is stored in numeric UTF-16 form and on deserialisation requires explicit * casting back to a char otherwise it's treated as an Integer and a TypeMismatch occurs */ - class AMQPCharPropertySerializer(name: String, readMethod: Method?) : + class AMQPCharPropertySerializer(name: String, readMethod: PropertyReader) : PropertySerializer(name, readMethod, Character::class.java) { override fun writeClassInfo(output: SerializationOutput) {} @@ -135,7 +185,7 @@ sealed class PropertySerializer(val name: String, val readMethod: Method?, val r } override fun writeProperty(obj: Any?, data: Data, output: SerializationOutput) { - val input = readMethod!!.invoke(obj) + val input = propertyReader.read(obj) if (input != null) data.putShort((input as Char).toShort()) else data.putNull() } } diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/SerializationHelper.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/SerializationHelper.kt index 5e3e28711a..e7b21f5e38 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/SerializationHelper.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/SerializationHelper.kt @@ -20,6 +20,7 @@ import kotlin.reflect.full.findAnnotation import kotlin.reflect.full.primaryConstructor import kotlin.reflect.jvm.isAccessible import kotlin.reflect.jvm.javaType +import kotlin.reflect.jvm.kotlinProperty /** * Annotation indicating a constructor to be used to reconstruct instances of a class during deserialization. @@ -29,8 +30,8 @@ import kotlin.reflect.jvm.javaType annotation class ConstructorForDeserialization data class ConstructorDestructorMethods( - val getters : Collection, - val setters : Collection) + val getters: Collection, + val setters: Collection) /** * Code for finding the constructor we will use for deserialization. @@ -100,26 +101,31 @@ private fun propertiesForSerializationFromConstructor( for (param in kotlinConstructor.parameters) { val name = param.name ?: throw NotSerializableException("Constructor parameter of $clazz has no name.") - val matchingProperty = properties[name] ?: - try { - clazz.getDeclaredField(param.name) - throw NotSerializableException("Property '$name' or its getter is non public, this renders class '$clazz' unserializable") - } catch (e: NoSuchFieldException) { - throw NotSerializableException("No property matching constructor parameter named '$name' of '$clazz'. " + - "If using Java, check that you have the -parameters option specified in the Java compiler. " + - "Alternately, provide a proxy serializer (SerializationCustomSerializer) if recompiling isn't an option") - } + if (name in properties) { + val matchingProperty = properties[name]!! - // Check that the method has a getter in java. - val getter = matchingProperty.readMethod ?: throw NotSerializableException("Property has no getter method for $name of $clazz. " + - "If using Java and the parameter name looks anonymous, check that you have the -parameters option specified in the Java compiler." + - "Alternately, provide a proxy serializer (SerializationCustomSerializer) if recompiling isn't an option") - val returnType = resolveTypeVariables(getter.genericReturnType, type) - if (constructorParamTakesReturnTypeOfGetter(returnType, getter.genericReturnType, param)) { - rc += PropertySerializer.make(name, getter, returnType, factory) + // Check that the method has a getter in java. + val getter = matchingProperty.readMethod ?: throw NotSerializableException("Property has no getter method for $name of $clazz. " + + "If using Java and the parameter name looks anonymous, check that you have the -parameters option specified in the Java compiler." + + "Alternately, provide a proxy serializer (SerializationCustomSerializer) if recompiling isn't an option") + val returnType = resolveTypeVariables(getter.genericReturnType, type) + if (constructorParamTakesReturnTypeOfGetter(returnType, getter.genericReturnType, param)) { + rc += PropertySerializer.make(name, PublicPropertyReader(getter), returnType, factory) + } else { + throw NotSerializableException("Property type $returnType for $name of $clazz differs from constructor parameter type ${param.type.javaType}") + } } else { - throw NotSerializableException("Property type $returnType for $name of $clazz differs from constructor parameter type ${param.type.javaType}") + try { + val field = (clazz.getDeclaredField(param.name)) + + rc += PropertySerializer.make(name, PrivatePropertyReader(field, type), field.genericType, factory) + } catch (e: NoSuchFieldException) { + throw NotSerializableException("No property matching constructor parameter named '$name' of '$clazz'. " + + "If using Java, check that you have the -parameters option specified in the Java compiler. " + + "Alternately, provide a proxy serializer (SerializationCustomSerializer) if recompiling isn't an option") + } } + } return ConstructorDestructorMethods(rc, emptyList()) @@ -130,11 +136,11 @@ private fun propertiesForSerializationFromConstructor( * and use those */ private fun propertiesForSerializationFromSetters( - properties : Map, + properties: Map, type: Type, factory: SerializerFactory): ConstructorDestructorMethods { - val getters : MutableList = ArrayList(properties.size) - val setters : MutableList = ArrayList(properties.size) + val getters: MutableList = ArrayList(properties.size) + val setters: MutableList = ArrayList(properties.size) properties.forEach { property -> val getter: Method? = property.value.readMethod @@ -146,8 +152,8 @@ private fun propertiesForSerializationFromSetters( // the getter / setter vs property as if there is a difference then that property isn't reported // by the BEAN inspector and thus we don't consider that case here - getters += PropertySerializer.make(property.key, getter, resolveTypeVariables(getter.genericReturnType, type), - factory) + getters += PropertySerializer.make(property.key, PublicPropertyReader(getter), + resolveTypeVariables(getter.genericReturnType, type), factory) setters += setter } @@ -159,15 +165,22 @@ private fun constructorParamTakesReturnTypeOfGetter(getterReturnType: Type, rawG return typeToken.isSupertypeOf(getterReturnType) || typeToken.isSupertypeOf(rawGetterReturnType) } -private fun propertiesForSerializationFromAbstract(clazz: Class<*>, type: Type, factory: SerializerFactory): ConstructorDestructorMethods { +private fun propertiesForSerializationFromAbstract( + clazz: Class<*>, + type: Type, + factory: SerializerFactory): ConstructorDestructorMethods { // Kotlin reflection doesn't work with Java getters the way you might expect, so we drop back to good ol' beans. - val properties = Introspector.getBeanInfo(clazz).propertyDescriptors.filter { it.name != "class" }.sortedBy { it.name }.filterNot { it is IndexedPropertyDescriptor } + val properties = Introspector.getBeanInfo(clazz).propertyDescriptors + .filter { it.name != "class" } + .sortedBy { it.name } + .filterNot { it is IndexedPropertyDescriptor } val rc: MutableList = ArrayList(properties.size) for (property in properties) { // Check that the method has a getter in java. - val getter = property.readMethod ?: throw NotSerializableException("Property has no getter method for ${property.name} of $clazz.") + val getter = property.readMethod ?: throw NotSerializableException( + "Property has no getter method for ${property.name} of $clazz.") val returnType = resolveTypeVariables(getter.genericReturnType, type) - rc += PropertySerializer.make(property.name, getter, returnType, factory) + rc += PropertySerializer.make(property.name, PublicPropertyReader(getter), returnType, factory) } return ConstructorDestructorMethods(rc, emptyList()) } 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 0dbc3f8be9..a6c587bc6e 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 @@ -40,6 +40,7 @@ open class SerializerFactory(val whitelist: ClassWhitelist, cl: ClassLoader) { val transformsCache = ConcurrentHashMap>>() open val classCarpenter = ClassCarpenter(cl, whitelist) + val classloader: ClassLoader get() = classCarpenter.classloader @@ -381,3 +382,4 @@ open class SerializerFactory(val whitelist: ClassWhitelist, cl: ClassLoader) { override fun toString(): String = "?" } } + diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/ThrowableSerializer.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/ThrowableSerializer.kt index 5700c08be7..93d8b0fbed 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/ThrowableSerializer.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/amqp/custom/ThrowableSerializer.kt @@ -25,7 +25,7 @@ class ThrowableSerializer(factory: SerializerFactory) : CustomSerializer.Proxy> serializersByDescriptor = + (ConcurrentHashMap>) f.get(factory); + + assertEquals(1, serializersByDescriptor.size()); + ObjectSerializer cSerializer = ((ObjectSerializer)serializersByDescriptor.values().toArray()[0]); + assertEquals(1, cSerializer.getPropertySerializers().component1().size()); + Object[] propertyReaders = cSerializer.getPropertySerializers().component1().toArray(); + assertTrue (((PropertySerializer)propertyReaders[0]).getPropertyReader() instanceof PrivatePropertyReader); + } + + @Test + public void singlePrivateWithConstructorAndGetter() + throws NotSerializableException, NoSuchFieldException, IllegalAccessException { + SerializerFactory factory = new SerializerFactory(AllWhitelist.INSTANCE, ClassLoader.getSystemClassLoader()); + SerializationOutput ser = new SerializationOutput(factory); + DeserializationInput des = new DeserializationInput(factory); + + C2 c = new C2("dripping taps"); + C2 c2 = des.deserialize(ser.serialize(c), C2.class); + + assertEquals (c.a, c2.a); + + // + // Now ensure we actually got a private property serializer + // + Field f = SerializerFactory.class.getDeclaredField("serializersByDescriptor"); + f.setAccessible(true); + ConcurrentHashMap> serializersByDescriptor = + (ConcurrentHashMap>) f.get(factory); + + assertEquals(1, serializersByDescriptor.size()); + ObjectSerializer cSerializer = ((ObjectSerializer)serializersByDescriptor.values().toArray()[0]); + assertEquals(1, cSerializer.getPropertySerializers().component1().size()); + Object[] propertyReaders = cSerializer.getPropertySerializers().component1().toArray(); + assertTrue (((PropertySerializer)propertyReaders[0]).getPropertyReader() instanceof PublicPropertyReader); + } +} diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/AMQPTestUtils.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/AMQPTestUtils.kt index 08d7af6ebb..8bbe597b26 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/AMQPTestUtils.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/AMQPTestUtils.kt @@ -1,10 +1,8 @@ package net.corda.nodeapi.internal.serialization.amqp -import net.corda.core.serialization.SerializedBytes import org.apache.qpid.proton.codec.Data import net.corda.nodeapi.internal.serialization.AllWhitelist import net.corda.nodeapi.internal.serialization.EmptyWhitelist -import java.io.NotSerializableException fun testDefaultFactory() = SerializerFactory(AllWhitelist, ClassLoader.getSystemClassLoader()) fun testDefaultFactoryWithWhitelist() = SerializerFactory(EmptyWhitelist, ClassLoader.getSystemClassLoader()) diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/PrivatePropertyTests.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/PrivatePropertyTests.kt new file mode 100644 index 0000000000..51405e8c26 --- /dev/null +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/amqp/PrivatePropertyTests.kt @@ -0,0 +1,117 @@ +package net.corda.nodeapi.internal.serialization.amqp + +import junit.framework.TestCase.assertTrue +import junit.framework.TestCase.assertEquals +import org.junit.Test +import org.apache.qpid.proton.amqp.Symbol +import java.util.concurrent.ConcurrentHashMap + +class PrivatePropertyTests { + private val factory = testDefaultFactory() + + @Test + fun testWithOnePrivateProperty() { + data class C(private val b: String) + + val c1 = C("Pants are comfortable sometimes") + val c2 = DeserializationInput(factory).deserialize(SerializationOutput(factory).serialize(c1)) + assertEquals(c1, c2) + } + + @Test + fun testWithOnePrivatePropertyNullableNotNull() { + data class C(private val b: String?) + + val c1 = C("Pants are comfortable sometimes") + val c2 = DeserializationInput(factory).deserialize(SerializationOutput(factory).serialize(c1)) + assertEquals(c1, c2) + } + + @Test + fun testWithOnePrivatePropertyNullableNull() { + data class C(private val b: String?) + + val c1 = C(null) + val c2 = DeserializationInput(factory).deserialize(SerializationOutput(factory).serialize(c1)) + assertEquals(c1, c2) + } + + @Test + fun testWithOnePublicOnePrivateProperty() { + data class C(val a: Int, private val b: Int) + + val c1 = C(1, 2) + val c2 = DeserializationInput(factory).deserialize(SerializationOutput(factory).serialize(c1)) + assertEquals(c1, c2) + } + + @Test + fun testWithOnePublicOnePrivateProperty2() { + data class C(val a: Int, private val b: Int) + + val c1 = C(1, 2) + val schemaAndBlob = SerializationOutput(factory).serializeAndReturnSchema(c1) + assertEquals(1, schemaAndBlob.schema.types.size) + + val field = SerializerFactory::class.java.getDeclaredField("serializersByDescriptor") + field.isAccessible = true + @Suppress("UNCHECKED_CAST") + val serializersByDescriptor = field.get(factory) as ConcurrentHashMap> + + val schemaDescriptor = schemaAndBlob.schema.types.first().descriptor.name + serializersByDescriptor.filterKeys { (it as Symbol) == schemaDescriptor }.values.apply { + assertEquals(1, this.size) + assertTrue(this.first() is ObjectSerializer) + val propertySerializers = (this.first() as ObjectSerializer).propertySerializers.getters.toList() + assertEquals(2, propertySerializers.size) + // a was public so should have a synthesised getter + assertTrue(propertySerializers[0].propertyReader is PublicPropertyReader) + + // b is private and thus won't have teh getter so we'll have reverted + // to using reflection to remove the inaccessible property + assertTrue(propertySerializers[1].propertyReader is PrivatePropertyReader) + } + } + + @Test + fun testGetterMakesAPublicReader() { + data class C(val a: Int, private val b: Int) { + @Suppress("UNUSED") + fun getB() = b + } + + val c1 = C(1, 2) + val schemaAndBlob = SerializationOutput(factory).serializeAndReturnSchema(c1) + assertEquals(1, schemaAndBlob.schema.types.size) + + val field = SerializerFactory::class.java.getDeclaredField("serializersByDescriptor") + field.isAccessible = true + @Suppress("UNCHECKED_CAST") + val serializersByDescriptor = field.get(factory) as ConcurrentHashMap> + + val schemaDescriptor = schemaAndBlob.schema.types.first().descriptor.name + serializersByDescriptor.filterKeys { (it as Symbol) == schemaDescriptor }.values.apply { + assertEquals(1, this.size) + assertTrue(this.first() is ObjectSerializer) + val propertySerializers = (this.first() as ObjectSerializer).propertySerializers.getters.toList() + assertEquals(2, propertySerializers.size) + + // as before, a is public so we'll use the getter method + assertTrue(propertySerializers[0].propertyReader is PublicPropertyReader) + + // the getB() getter explicitly added means we should use the "normal" public + // method reader rather than the private oen + assertTrue(propertySerializers[1].propertyReader is PublicPropertyReader) + } + } + + @Test + fun testNested() { + data class Inner(private val a: Int) + data class Outer(private val i: Inner) + + val c1 = Outer(Inner(1010101)) + val c2 = DeserializationInput(factory).deserialize(SerializationOutput(factory).serialize(c1)) + assertEquals(c1, c2) + } +} \ No newline at end of file diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/carpenter/ClassCarpenterTestUtils.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/carpenter/ClassCarpenterTestUtils.kt index 8773140f6d..a27b6440d3 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/carpenter/ClassCarpenterTestUtils.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/serialization/carpenter/ClassCarpenterTestUtils.kt @@ -35,9 +35,16 @@ fun Schema.mangleNames(names: List): Schema { return Schema(types = newTypes) } +/** + * Custom implementation of a [SerializerFactory] where we need to give it a class carpenter + * rather than have it create its own + */ +class SerializerFactoryExternalCarpenter(override val classCarpenter: ClassCarpenter) + : SerializerFactory (classCarpenter.whitelist, classCarpenter.classloader) + open class AmqpCarpenterBase(whitelist: ClassWhitelist) { var cc = ClassCarpenter(whitelist = whitelist) - var factory = SerializerFactory(AllWhitelist, cc.classloader) + var factory = SerializerFactoryExternalCarpenter(cc) fun serialise(clazz: Any) = SerializationOutput(factory).serialize(clazz) fun testName(): String = Thread.currentThread().stackTrace[2].methodName diff --git a/node/capsule/build.gradle b/node/capsule/build.gradle index 17ad12f9f4..dc388b16ec 100644 --- a/node/capsule/build.gradle +++ b/node/capsule/build.gradle @@ -6,7 +6,7 @@ apply plugin: 'net.corda.plugins.publish-utils' apply plugin: 'us.kirchmeier.capsule' apply plugin: 'com.jfrog.artifactory' -description 'Corda Enterprise' +description 'R3 Corda' configurations { runtimeArtifacts.extendsFrom runtime @@ -28,7 +28,7 @@ targetCompatibility = 1.6 task buildCordaJAR(type: FatCapsule, dependsOn: project(':node').compileJava) { applicationClass 'net.corda.node.Corda' - archiveName "corda-enterprise-${corda_release_version}.jar" + archiveName "corda-r3-${corda_release_version}.jar" applicationSource = files( project(':node').configurations.runtime, project(':node').jar, diff --git a/node/src/integration-test/kotlin/net/corda/node/services/MySQLNotaryServiceTests.kt b/node/src/integration-test/kotlin/net/corda/node/services/MySQLNotaryServiceTests.kt index a7fd1c2ca5..273f18690a 100644 --- a/node/src/integration-test/kotlin/net/corda/node/services/MySQLNotaryServiceTests.kt +++ b/node/src/integration-test/kotlin/net/corda/node/services/MySQLNotaryServiceTests.kt @@ -17,9 +17,10 @@ import net.corda.node.services.config.NotaryConfig import net.corda.nodeapi.internal.DevIdentityGenerator import net.corda.nodeapi.internal.network.NetworkParametersCopier import net.corda.nodeapi.internal.network.NotaryInfo -import net.corda.testing.* +import net.corda.testing.chooseIdentity import net.corda.testing.common.internal.testNetworkParameters import net.corda.testing.contracts.DummyContract +import net.corda.testing.dummyCommand import net.corda.testing.internal.IntegrationTest import net.corda.testing.internal.IntegrationTestSchemas import net.corda.testing.node.MockNetwork @@ -27,7 +28,10 @@ import net.corda.testing.node.MockNodeParameters import net.corda.testing.node.MockServices.Companion.makeTestDataSourceProperties import net.corda.testing.node.inMemoryH2DataSourceConfig import net.corda.testing.node.startFlow -import org.junit.* +import org.junit.After +import org.junit.Before +import org.junit.ClassRule +import org.junit.Test import java.math.BigInteger import java.util.* import kotlin.test.assertEquals diff --git a/node/src/integration-test/kotlin/net/corda/services/messaging/P2PMessagingTest.kt b/node/src/integration-test/kotlin/net/corda/services/messaging/P2PMessagingTest.kt index b6bf5c02b7..e69fcda1e4 100644 --- a/node/src/integration-test/kotlin/net/corda/services/messaging/P2PMessagingTest.kt +++ b/node/src/integration-test/kotlin/net/corda/services/messaging/P2PMessagingTest.kt @@ -17,6 +17,11 @@ import net.corda.node.internal.StartedNode import net.corda.node.services.messaging.MessagingService import net.corda.node.services.messaging.ReceivedMessage import net.corda.node.services.messaging.send +import net.corda.node.services.transactions.RaftValidatingNotaryService +import net.corda.testing.* +import net.corda.node.services.messaging.* +import net.corda.testing.ALICE_NAME +import net.corda.testing.chooseIdentity import net.corda.testing.ALICE_NAME import net.corda.testing.chooseIdentity import net.corda.testing.driver.DriverDSL 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 1b22b01d76..ada9654021 100644 --- a/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt +++ b/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt @@ -187,7 +187,7 @@ abstract class AbstractNode(val configuration: NodeConfiguration, initCertificate() val schemaService = NodeSchemaService(cordappLoader.cordappSchemas) val (identity, identityKeyPair) = obtainIdentity(notaryConfig = null) - return initialiseDatabasePersistence(schemaService, makeIdentityService(identity.certificate)) { database -> + return initialiseDatabasePersistence(schemaService, makeIdentityService(identity.certificate)) { database -> // TODO The fact that we need to specify an empty list of notaries just to generate our node info looks like // a code smell. val persistentNetworkMapCache = PersistentNetworkMapCache(database, notaries = emptyList()) 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 7a71ea615f..cb1d09dc6c 100644 --- a/node/src/main/kotlin/net/corda/node/internal/Node.kt +++ b/node/src/main/kotlin/net/corda/node/internal/Node.kt @@ -265,6 +265,9 @@ open class Node(configuration: NodeConfiguration, printBasicNodeInfo("Database connection url is", "jdbc:h2:$url/node") } } + else if (databaseUrl != null) { + printBasicNodeInfo("Database connection url is", databaseUrl) + } return super.initialiseDatabasePersistence(schemaService, identityService, insideTransaction) } 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 c3942b3fc9..1e44787b60 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 @@ -1,8 +1,5 @@ package net.corda.node.services.config -import com.typesafe.config.* -import net.corda.core.crypto.Crypto -import net.corda.core.crypto.SignatureScheme import com.typesafe.config.Config import com.typesafe.config.ConfigFactory import com.typesafe.config.ConfigParseOptions diff --git a/node/src/main/kotlin/net/corda/node/services/keys/KMSUtils.kt b/node/src/main/kotlin/net/corda/node/services/keys/KMSUtils.kt index dad6a7b2a7..70c555b824 100644 --- a/node/src/main/kotlin/net/corda/node/services/keys/KMSUtils.kt +++ b/node/src/main/kotlin/net/corda/node/services/keys/KMSUtils.kt @@ -36,13 +36,8 @@ fun freshCertificate(identityService: IdentityServiceInternal, require(issuerRole == CertRole.LEGAL_IDENTITY) { "Confidential identities can only be issued from well known identities, provided issuer ${issuer.name} has role $issuerRole" } val issuerCert = issuer.certificate val window = X509Utilities.getCertificateValidityWindow(Duration.ZERO, 3650.days, issuerCert) - val ourCertificate = X509Utilities.createCertificate( - CertificateType.CONFIDENTIAL_LEGAL_IDENTITY, - issuerCert.subjectX500Principal, - issuerSigner, - issuer.name.x500Principal, - subjectPublicKey, - window) + val ourCertificate = X509Utilities.createCertificate(CertificateType.CONFIDENTIAL_LEGAL_IDENTITY, issuerCert.subjectX500Principal, + issuerSigner, issuer.name.x500Principal, subjectPublicKey, window) val ourCertPath = X509CertificateFactory().generateCertPath(listOf(ourCertificate) + issuer.certPath.certificates) val anonymisedIdentity = PartyAndCertificate(ourCertPath) identityService.justVerifyAndRegisterIdentity(anonymisedIdentity) diff --git a/node/src/main/kotlin/net/corda/node/services/persistence/RunOnceService.kt b/node/src/main/kotlin/net/corda/node/services/persistence/RunOnceService.kt index a3528f8f9c..a720865dd3 100644 --- a/node/src/main/kotlin/net/corda/node/services/persistence/RunOnceService.kt +++ b/node/src/main/kotlin/net/corda/node/services/persistence/RunOnceService.kt @@ -8,7 +8,8 @@ import net.corda.nodeapi.internal.persistence.NODE_DATABASE_PREFIX import org.hibernate.Session import java.text.SimpleDateFormat import java.time.Duration -import java.util.Date +import java.time.LocalDateTime +import java.time.temporal.ChronoField import java.util.concurrent.ScheduledExecutorService import java.util.concurrent.TimeUnit import java.util.concurrent.atomic.AtomicBoolean @@ -47,7 +48,7 @@ class RunOnceService(private val database: CordaPersistence, private val machine @Entity @Table(name = TABLE) - class MutualExclusion(machineNameInit: String, pidInit: String) { + class MutualExclusion(machineNameInit: String, pidInit: String, timeStampInit: LocalDateTime) { @Column(name = ID, insertable = false, updatable = false) @Id val id: Char = 'X' @@ -59,8 +60,7 @@ class RunOnceService(private val database: CordaPersistence, private val machine val pid = pidInit @Column(name = TIMESTAMP) - @Temporal(TemporalType.TIMESTAMP) - val timestamp: Date? = null + val timestamp = timeStampInit } fun start() { @@ -130,7 +130,7 @@ class RunOnceService(private val database: CordaPersistence, private val machine } private fun updateTimestamp(session: Session, mutualExclusion: MutualExclusion): Boolean { - val minWaitTime = simpleDateFormat.format(Date(mutualExclusion.timestamp!!.time + waitInterval)) + val minWaitTime = mutualExclusion.timestamp.plus(waitInterval, ChronoField.MILLI_OF_SECOND.baseUnit) val query = session.createNativeQuery("UPDATE $TABLE SET $MACHINE_NAME = :machineName, $TIMESTAMP = CURRENT_TIMESTAMP, $PID = :pid " + "WHERE $ID = 'X' AND " + 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 9131143e9f..cfcc60b334 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 @@ -167,11 +167,7 @@ class InMemoryIdentityServiceTests { val issuerKeyPair = generateKeyPair() val issuer = getTestPartyAndCertificate(x500Name, issuerKeyPair.public) val txKeyPair = Crypto.generateKeyPair() - val txCert = X509Utilities.createCertificate( - CertificateType.CONFIDENTIAL_LEGAL_IDENTITY, - issuer.certificate, - issuerKeyPair, - x500Name.x500Principal, + val txCert = X509Utilities.createCertificate(CertificateType.CONFIDENTIAL_LEGAL_IDENTITY, issuer.certificate, issuerKeyPair, x500Name.x500Principal, txKeyPair.public) val txCertPath = X509CertificateFactory().generateCertPath(listOf(txCert) + issuer.certPath.certificates) return Pair(issuer, PartyAndCertificate(txCertPath)) diff --git a/node/src/test/kotlin/net/corda/node/services/persistence/RunOnceServiceTest.kt b/node/src/test/kotlin/net/corda/node/services/persistence/RunOnceServiceTest.kt index 05568dc4dd..d440cecf79 100644 --- a/node/src/test/kotlin/net/corda/node/services/persistence/RunOnceServiceTest.kt +++ b/node/src/test/kotlin/net/corda/node/services/persistence/RunOnceServiceTest.kt @@ -14,7 +14,7 @@ import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.contrib.java.lang.system.ExpectedSystemExit -import java.util.* +import java.time.LocalDateTime import java.util.concurrent.ScheduledExecutorService import java.util.concurrent.ScheduledFuture import javax.persistence.Query @@ -64,7 +64,9 @@ class RunOnceServiceTest { fun `row updated when change of master node`() { runOnceServiceMachine1.start() - var firstTimestamp: Date? = null + var secondTimestamp = LocalDateTime.now() + var firstTimestamp = LocalDateTime.now() + database.transaction { val query = session.createNativeQuery(selectQuery, RunOnceService.MutualExclusion::class.java) val result = machine1RowCheck(query) @@ -76,14 +78,13 @@ class RunOnceServiceTest { runOnceServiceMachine2.start() - var secondTimestamp: Date? = null database.transaction { val query = session.createNativeQuery(selectQuery, RunOnceService.MutualExclusion::class.java) val result = machine2RowCheck(query) secondTimestamp = result.timestamp } - assertTrue(secondTimestamp!!.toInstant().isAfter(firstTimestamp!!.toInstant())) + assertTrue(secondTimestamp.isAfter(firstTimestamp)) } @Test @@ -105,7 +106,9 @@ class RunOnceServiceTest { fun `row updated when last run was same machine`() { runOnceServiceMachine1.start() - var firstTimestamp: Date? = null + var secondTimestamp = LocalDateTime.now() + var firstTimestamp = LocalDateTime.now() + database.transaction { val query = session.createNativeQuery(selectQuery, RunOnceService.MutualExclusion::class.java) val result = machine1RowCheck(query) @@ -117,14 +120,13 @@ class RunOnceServiceTest { runOnceServiceMachine1.start() - var secondTimestamp: Date? = null database.transaction { val query = session.createNativeQuery(selectQuery, RunOnceService.MutualExclusion::class.java) val result = machine1RowCheck(query) secondTimestamp = result.timestamp } - assertTrue(secondTimestamp!!.toInstant().isAfter(firstTimestamp!!.toInstant())) + assertTrue(secondTimestamp.isAfter(firstTimestamp)) } @Test @@ -132,7 +134,9 @@ class RunOnceServiceTest { whenever(mockUpdateExecutor.scheduleAtFixedRate(any(), any(), any(), any())).thenAnswer { invocation -> val runnable = invocation.arguments[0] as Runnable - var firstTimestamp: Date? = null + var secondTimestamp = LocalDateTime.now() + var firstTimestamp = LocalDateTime.now() + database.transaction { val query = session.createNativeQuery(selectQuery, RunOnceService.MutualExclusion::class.java) val result = machine1RowCheck(query) @@ -141,14 +145,13 @@ class RunOnceServiceTest { runnable.run() - var secondTimestamp: Date? = null database.transaction { val query = session.createNativeQuery(selectQuery, RunOnceService.MutualExclusion::class.java) val result = machine1RowCheck(query) secondTimestamp = result.timestamp } - assertTrue(secondTimestamp!!.toInstant().isAfter(firstTimestamp!!.toInstant())) + assertTrue(secondTimestamp.isAfter(firstTimestamp)) mock>() } @@ -228,7 +231,7 @@ class RunOnceServiceTest { assertEquals('X', result.id) assertEquals("machine1", result.machineName) assertEquals("123", result.pid) - assertTrue(result.timestamp is Date) + assertTrue(result.timestamp is LocalDateTime) return result } @@ -238,7 +241,7 @@ class RunOnceServiceTest { assertEquals('X', result.id) assertEquals("machine2", result.machineName) assertEquals("789", result.pid) - assertTrue(result.timestamp is Date) + assertTrue(result.timestamp is LocalDateTime) return result } } \ No newline at end of file diff --git a/samples/notary-demo/src/main/kotlin/net/corda/notarydemo/RaftNotaryCordform.kt b/samples/notary-demo/src/main/kotlin/net/corda/notarydemo/RaftNotaryCordform.kt index abceabbe77..998a48e36c 100644 --- a/samples/notary-demo/src/main/kotlin/net/corda/notarydemo/RaftNotaryCordform.kt +++ b/samples/notary-demo/src/main/kotlin/net/corda/notarydemo/RaftNotaryCordform.kt @@ -8,9 +8,9 @@ import net.corda.core.utilities.NetworkHostAndPort import net.corda.node.services.config.NotaryConfig import net.corda.node.services.config.RaftConfig import net.corda.nodeapi.internal.DevIdentityGenerator -import net.corda.testing.node.internal.demorun.* import net.corda.testing.ALICE_NAME import net.corda.testing.BOB_NAME +import net.corda.testing.node.internal.demorun.* import java.nio.file.Paths fun main(args: Array) = RaftNotaryCordform().deployNodes() diff --git a/sgx-jvm/remote-attestation/build.gradle b/sgx-jvm/remote-attestation/build.gradle index 3b6df1617c..b75ad87ce9 100644 --- a/sgx-jvm/remote-attestation/build.gradle +++ b/sgx-jvm/remote-attestation/build.gradle @@ -52,7 +52,7 @@ allprojects { systemProperties["attestation.home"] = "$buildDir/logs" } - group 'com.r3.corda.enterprise' + group 'com.r3.corda' version '1.0-SNAPSHOT' repositories { 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 331f1b940d..cc070cc9e0 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 @@ -5,7 +5,6 @@ import com.google.common.jimfs.Jimfs import com.nhaarman.mockito_kotlin.doReturn import com.nhaarman.mockito_kotlin.whenever import net.corda.core.DoNotImplement -import net.corda.core.crypto.entropyToKeyPair import net.corda.core.crypto.Crypto import net.corda.core.crypto.random63BitValue import net.corda.core.identity.CordaX500Name diff --git a/tools/demobench/README.md b/tools/demobench/README.md index ad1550b9e5..d1a47a1e0e 100644 --- a/tools/demobench/README.md +++ b/tools/demobench/README.md @@ -110,6 +110,9 @@ Now choose `File/Open` from the main menu, and select the profile that you have just saved. DemoBench should close the two existing tabs and then relaunch the Notary and Bank nodes. +If you want to edit the content, please make sure that when zipping content back, +the notary node is the first directory (ZIP files content is ordered) + ## Exiting DemoBench Close DemoBench as a normal application on your platform; it should close any 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 ae5b6deeb1..7b94e95058 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 @@ -10,6 +10,7 @@ import net.corda.nodeapi.internal.config.User import net.corda.nodeapi.internal.config.toConfig import java.nio.file.Path import java.nio.file.StandardCopyOption +import java.util.Properties /** * This is a subset of FullNodeConfiguration, containing only those configs which we need. The node uses reference.conf @@ -25,7 +26,10 @@ data class NodeConfig( val h2port: Int, val rpcUsers: List = listOf(defaultUser), /** This is an extra config used by the Cash app. */ - val issuableCurrencies: List = emptyList() + val issuableCurrencies: List = emptyList(), + /** Pass-through for generating node.conf with external DB */ + val dataSourceProperties: Properties? = null, + val database: Properties? = null ) { companion object { val renderOptions: ConfigRenderOptions = ConfigRenderOptions.defaults().setOriginComments(false) diff --git a/tools/demobench/src/main/kotlin/net/corda/demobench/model/NodeController.kt b/tools/demobench/src/main/kotlin/net/corda/demobench/model/NodeController.kt index fddcfdf19a..b98f530819 100644 --- a/tools/demobench/src/main/kotlin/net/corda/demobench/model/NodeController.kt +++ b/tools/demobench/src/main/kotlin/net/corda/demobench/model/NodeController.kt @@ -10,10 +10,10 @@ import net.corda.core.internal.noneOrSingle import net.corda.core.utilities.NetworkHostAndPort import net.corda.demobench.plugin.CordappController import net.corda.demobench.pty.R3Pty +import net.corda.nodeapi.internal.DevIdentityGenerator import net.corda.nodeapi.internal.network.NetworkParameters import net.corda.nodeapi.internal.network.NetworkParametersCopier import net.corda.nodeapi.internal.network.NotaryInfo -import net.corda.nodeapi.internal.DevIdentityGenerator import tornadofx.* import java.io.IOException import java.lang.management.ManagementFactory diff --git a/tools/explorer/README.md b/tools/explorer/README.md index 6098215838..b755455465 100644 --- a/tools/explorer/README.md +++ b/tools/explorer/README.md @@ -34,16 +34,44 @@ The Participant nodes are only able to spend cash (eg. move cash). **These Corda nodes will be created on the following port on localhost.** - * Notary -> 20003 (Does not accept logins) - * Alice -> 20006 - * Bob -> 20009 - * UK Bank Plc -> 20012 (*Issuer node*) - * USA Bank Corp -> 20015 (*Issuer node*) + * Notary -> 20001 (Does not accept logins) + * Alice -> 20004 + * Bob -> 20007 + * UK Bank Plc -> 20010 (*Issuer node*) + * USA Bank Corp -> 20013 (*Issuer node*) Explorer login credentials to the Issuer nodes are defaulted to ``manager`` and ``test``. -Explorer login credentials to the Participants nodes are defaulted to ``user1`` and ``test``. +Explorer login credentials to the Participant nodes are defaulted to ``user1`` and ``test``. Please note you are not allowed to login to the notary. +## Running Simulation Nodes + +Building on the demonstration Corda network topology described above, simulation mode performs continuous +issue, move and exit cash operations across all participant nodes. + +**Windows:** + + gradlew.bat tools:explorer:runSimulationNodes + +**Other:** + + ./gradlew tools:explorer:runSimulationNodes + +## Running Flow Triage scenario + +Once again, building on the demonstration Corda network topology described above, this scenario mode triggers +an exception within a flow which can then be visualized using the "Flow Triage" panel within the Explorer. +The "Flow Triage" panel will be enhanced in the future to enable operators to take corrective actions upon flow failures +(eg. retry, terminate, amend and replay) + +**Windows:** + + gradlew.bat tools:explorer:runFlowTriageNodes + +**Other:** + + ./gradlew tools:explorer:runFlowTriageNodes + ## Business Network reference implementation An additional "IOU" panel is now visible in the main Explorer dashboard to demonstrate the new Business Networks concept using a sample IOU product. @@ -71,4 +99,4 @@ Please note Business Networks functionality only applies to the same IOU CorDapp - Support other contract types. -More information can be found in the [Project website](https://corda.net) and [Documentation](https://docs.corda.net). +More information can be found in the [Project website](https://corda.net) and [Documentation](https://docs.corda.net). \ No newline at end of file diff --git a/tools/explorer/src/main/kotlin/net/corda/explorer/Main.kt b/tools/explorer/src/main/kotlin/net/corda/explorer/Main.kt index 4750b08b05..6e1333b730 100644 --- a/tools/explorer/src/main/kotlin/net/corda/explorer/Main.kt +++ b/tools/explorer/src/main/kotlin/net/corda/explorer/Main.kt @@ -65,10 +65,10 @@ class Main : App(MainView::class) { if (!isLoggedIn) { stage.hide() loginView.login() - addOptionalViews() - (find(primaryView) as MainView).initializeControls() - stage.show() } + addOptionalViews() + (find(primaryView) as MainView).initializeControls() + stage.show() } private fun addOptionalViews() {