From 9afcbb16a20a15722687657bdeb5ffdf59b23dd4 Mon Sep 17 00:00:00 2001 From: Shams Asari Date: Wed, 14 Mar 2018 07:04:25 +0000 Subject: [PATCH 1/7] Unwrapping InvocationTargetException during config parsing (#2811) --- .../nodeapi/internal/config/ConfigUtilities.kt | 10 ++++++---- .../nodeapi/internal/config/ConfigParsingTest.kt | 16 ++++++++++++++-- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/config/ConfigUtilities.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/config/ConfigUtilities.kt index dbf880905b..3e1d013c40 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/config/ConfigUtilities.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/config/ConfigUtilities.kt @@ -9,6 +9,7 @@ import net.corda.core.internal.uncheckedCast import net.corda.core.utilities.NetworkHostAndPort import org.slf4j.LoggerFactory import java.lang.reflect.Field +import java.lang.reflect.InvocationTargetException import java.lang.reflect.Modifier.isStatic import java.lang.reflect.ParameterizedType import java.net.Proxy @@ -62,19 +63,20 @@ fun Config.parseAs(clazz: KClass): T { val path = defaultToOldPath(property) getValueInternal(path, param.type) } - return constructor.callBy(args) + try { + return constructor.callBy(args) + } catch (e: InvocationTargetException) { + throw e.cause!! + } } class UnknownConfigurationKeysException private constructor(val unknownKeys: Set) : IllegalArgumentException(message(unknownKeys)) { - init { require(unknownKeys.isNotEmpty()) { "Absence of unknown keys should not raise UnknownConfigurationKeysException." } } companion object { - fun of(offendingKeys: Set): UnknownConfigurationKeysException = UnknownConfigurationKeysException(offendingKeys) - private fun message(offendingKeys: Set) = "Unknown configuration keys: ${offendingKeys.joinToString(", ", "[", "]")}." } } diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/config/ConfigParsingTest.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/config/ConfigParsingTest.kt index 265de97530..7c74624790 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/config/ConfigParsingTest.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/config/ConfigParsingTest.kt @@ -7,8 +7,7 @@ import com.typesafe.config.ConfigValueFactory import net.corda.core.identity.CordaX500Name import net.corda.core.internal.div import net.corda.core.utilities.NetworkHostAndPort -import org.assertj.core.api.Assertions.assertThat -import org.assertj.core.api.Assertions.assertThatThrownBy +import org.assertj.core.api.Assertions.* import org.junit.Test import java.net.URL import java.nio.file.Path @@ -188,6 +187,14 @@ class ConfigParsingTest { assertThat(NullableData(null).toConfig()).isEqualTo(empty()) } + @Test + fun `data class with checks`() { + val config = config("positive" to -1) + assertThatExceptionOfType(IllegalArgumentException::class.java) + .isThrownBy { config.parseAs() } + .withMessageContaining("-1") + } + @Test fun `old config property`() { assertThat(config("oldValue" to "old").parseAs().newValue).isEqualTo("old") @@ -291,6 +298,11 @@ class ConfigParsingTest { data class DataListData(val list: List) data class DefaultData(val a: Int, val defaultOfTwo: Int = 2) data class NullableData(val nullable: String?) + data class PositiveData(private val positive: Int) { + init { + require(positive > 0) { "$positive is not positive" } + } + } data class OldData( @OldConfig("oldValue") val newValue: String) From 1a6f7bc2c00b5cb1cac1847473a2afab57e9601c Mon Sep 17 00:00:00 2001 From: Michal Kit Date: Wed, 14 Mar 2018 08:05:00 +0000 Subject: [PATCH 2/7] Whitelisting CRLReason class (#2803) --- .../corda/nodeapi/internal/serialization/DefaultWhitelist.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/DefaultWhitelist.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/DefaultWhitelist.kt index 2507678682..f4bc9d4551 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/DefaultWhitelist.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/serialization/DefaultWhitelist.kt @@ -7,6 +7,7 @@ import org.apache.activemq.artemis.api.core.SimpleString import rx.Notification import rx.exceptions.OnErrorNotImplementedException import sun.security.x509.X509CertImpl +import java.security.cert.CRLReason import java.util.* /** @@ -62,6 +63,7 @@ object DefaultWhitelist : SerializationWhitelist { StackTraceElement::class.java, // Implementation of X509Certificate. - X509CertImpl::class.java + X509CertImpl::class.java, + CRLReason::class.java ) } From 42d1fcc7b2a7dff1db2a8e7a93d0577a19b921b4 Mon Sep 17 00:00:00 2001 From: szymonsztuka Date: Wed, 14 Mar 2018 10:34:42 +0100 Subject: [PATCH 3/7] Ignore 2 flaky SSH via StandaloneShell tests temporarily. (#2810) --- .../net/corda/tools/shell/InteractiveShellIntegrationTest.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/shell/src/integration-test/kotlin/net/corda/tools/shell/InteractiveShellIntegrationTest.kt b/tools/shell/src/integration-test/kotlin/net/corda/tools/shell/InteractiveShellIntegrationTest.kt index 37b9be0e04..c8dc67869e 100644 --- a/tools/shell/src/integration-test/kotlin/net/corda/tools/shell/InteractiveShellIntegrationTest.kt +++ b/tools/shell/src/integration-test/kotlin/net/corda/tools/shell/InteractiveShellIntegrationTest.kt @@ -21,6 +21,7 @@ import org.apache.activemq.artemis.api.core.ActiveMQSecurityException import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThatThrownBy import org.bouncycastle.util.io.Streams +import org.junit.Ignore import org.junit.Test import kotlin.test.assertTrue @@ -131,6 +132,7 @@ class InteractiveShellIntegrationTest { } } + @Ignore @Test fun `ssh runs flows via standalone shell`() { val user = User("u", "p", setOf(Permissions.startFlow(), @@ -173,6 +175,7 @@ class InteractiveShellIntegrationTest { } } + @Ignore @Test fun `ssh run flows via standalone shell over ssl to node`() { val user = User("mark", "dadada", setOf(Permissions.startFlow(), From df536cee86ead13aa7a6049074d81c0dac2d4aca Mon Sep 17 00:00:00 2001 From: Katelyn Baker Date: Wed, 14 Mar 2018 10:05:38 +0000 Subject: [PATCH 4/7] CORDA-966 - RELEASE - Merge release notes from release branch to master (#2775) --- docs/source/changelog.rst | 21 ++- docs/source/clientrpc.rst | 2 + docs/source/release-notes.rst | 330 ++++++++++++++++++++++++++++++---- 3 files changed, 307 insertions(+), 46 deletions(-) diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst index 8638c8c397..7626d7d312 100644 --- a/docs/source/changelog.rst +++ b/docs/source/changelog.rst @@ -1,21 +1,22 @@ Changelog ========= +Unreleased +---------- + Here are brief summaries of what's changed between each snapshot release. This includes guidance on how to upgrade code from the previous milestone release. -UNRELEASED ----------- - * Parsing of ``NodeConfiguration`` will now fail if unknown configuration keys are found. * The web server now has its own ``web-server.conf`` file, separate from ``node.conf``. * Introduced a placeholder for custom properties within ``node.conf``; the property key is "custom". -* Added ``NetworkMapCache.getNodesByLegalName`` for querying nodes belonging to a distributed service such as a notary cluster - where they all share a common identity. ``NetworkMapCache.getNodeByLegalName`` has been tightened to throw if more than - one node with the legal name is found. +.. _changelog_v3: + +Version 3.0 +----------- * Per CorDapp configuration is now exposed. ``CordappContext`` now exposes a ``CordappConfig`` object that is populated at CorDapp context creation time from a file source during runtime. @@ -31,7 +32,6 @@ UNRELEASED * Separated our pre-existing Artemis broker into an RPC broker and a P2P broker. * Refactored ``NodeConfiguration`` to expose ``NodeRpcOptions`` (using top-level "rpcAddress" property still works with warning). - * Modified ``CordaRPCClient`` constructor to take a ``SSLConfiguration?`` additional parameter, defaulted to ``null``. * Introduced ``CertificateChainCheckPolicy.UsernameMustMatchCommonName`` sub-type, allowing customers to optionally enforce username == CN condition on RPC SSL certificates. @@ -93,6 +93,10 @@ UNRELEASED * Single node notaries no longer have a second separate notary identity. Their main identity *is* their notary identity. Use ``NetworkMapCache.notaryIdentities`` to get the list of available notaries. + * Added ``NetworkMapCache.getNodesByLegalName`` for querying nodes belonging to a distributed service such as a notary cluster + where they all share a common identity. ``NetworkMapCache.getNodeByLegalName`` has been tightened to throw if more than + one node with the legal name is found. + * The common name in the node's X500 legal name is no longer reserved and can be used as part of the node's name. * Moved ``NodeInfoSchema`` to internal package as the node info's database schema is not part of the public API. This @@ -213,6 +217,9 @@ UNRELEASED will help make it clearer which parts of the api are stable. Scripts have been provided to smooth the upgrade process for existing projects in the ``tools\scripts`` directory of the Corda repo. +* ``TransactionSignature`` includes a new ``partialMerkleTree`` property, required for future support of signing over + multiple transactions at once. + .. _changelog_v1: Release 1.0 diff --git a/docs/source/clientrpc.rst b/docs/source/clientrpc.rst index 38602ad5b7..dda114e2ba 100644 --- a/docs/source/clientrpc.rst +++ b/docs/source/clientrpc.rst @@ -126,6 +126,8 @@ You can provide an RPC user with the permission to perform any RPC operation (in ... ] +.. _rpc_security_mgmt_ref: + RPC security management ----------------------- diff --git a/docs/source/release-notes.rst b/docs/source/release-notes.rst index 5bd286f858..40455396f8 100644 --- a/docs/source/release-notes.rst +++ b/docs/source/release-notes.rst @@ -1,49 +1,301 @@ Release notes ============= -Here are release notes for each snapshot release from M9 onwards. +Release 3.0 +----------- -Unreleased ----------- -* X.509 certificates now have an extension that specifies the Corda role the certificate is used for, and the role +Corda 3.0 is here and brings with it a commitment to a wire stable platform, a path for contract and node upgradability, +and a host of other exciting features. The aim of which is to enhance the developer and user experience whilst providing +for the long term usability of deployed Corda instances. This release will provide functionality to ensure anyone wishing +to move to the anticipated release of R3 Corda can do so seamlessly and with the assurance that stateful data persisted to +the vault will remain understandable between newer and older nodes. + +Special Thanks +~~~~~~~~~~~~~~ + +As ever, we are grateful to the enthusiastic user and developer community that has grown up to surround Corda. +As an open project we are always grateful to take code contributions from individual users where they feel they +can add functionality useful to themselves and the wider community. + +As such we'd like to extend special thanks to + + * Ben Wyeth for providing a mechanism for registering a callback on app shutdown + + Ben's contribution can be found on GitHub + `here `_ + + * Tomas Tauber for adding support for running Corda atop PostgresSQL in place of the in-memory H2 service + + Tomas's contribution can be found on GitHub + `here `_ + + .. warning:: This is an experimental feature that has not been tested as part of our standard release testing. + + * Rose Molina Atienza for correcting our careless spelling slip + + Rose's change can be found on GitHub + `here `_ + +Significant Changes in 3.0 +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* **Wire Stability**: + + Wire stability brings the same promise to developers for their data that API stability did for their code. From this + point any state generated by a Corda system will always be retrievable, understandable, and seen as valid by any + subsequently released version (versions 3.0 and above). + + Systems can thus be deployed safe in the knowledge that valuable and important information will always be accessible through + upgrade and change. Practically speaking this means from this point forward upgrading all, or part, of a Corda network + will not require the replaying of data; "it will just work". + + This has been facilitated by the switch over from Kryo to Corda's own AMQP based serialization framework, a framework + designed to interoperate with stateful information and allow the evolution of such contract states over time as developers + refine and improve their systems written atop the core Corda platform. + + * **AMQP Serialization** + + 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. This was 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 can be + 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. + + Whilst this is an important step for Corda, in no way is this the end of the serialisation story. We have many new + features and tools planned for future releases, but feel it is more important to deliver the guarantees discussed above + as early as possible to allow the community to develop with greater confidence. + + .. important:: Whilst Corda has stabilised its wire protocol and infrastructure for peer to peer communication and persistent storage + of states, the RPC framework will, for this release, not be covered by this guarantee. The moving of the client and + server contexts away from Kryo to our stable AMQP implementation is planned for the next release of Corda + + * **Artemis and Bridges** + + Corda has now achieved the long stated goal of using the AMQP 1.0 open protocol standard as its communication protocol + between peers. This forms a strong and flexible framework upon which we can deliver future enhancements that will allow + for much smoother integrations between Corda and third party brokers, languages, and messaging systems. In addition, + this is also an important step towards formally defining the official peer to peer messaging protocol of Corda, something + required for more in-depth security audits of the Corda protocol. + +* **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). + + A Corda Compatibility Zone 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 to specify precisely the set of constants (or ranges of constants) upon + which the nodes within a network 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. + + There is also support for a group of nodes to operate locally, which is achieved by copying each + node's signed info file to the other nodes' directories. We've added a bootstrapping tool to facilitate this use case. + + .. important:: This replaces the Network Map service that was present in Corda 1.0 and Corda 2.0. + + Further information can be found in the :doc:`changelog`, :doc:`network-map` and :doc:`setting-up-a-corda-network` documentation. + +* **Contract Upgrade** + + Support for the upgrading of contracts has been significantly extended in this release. + + Contract states express which attached JARs can define and verify them using _constraints_. In older versions the only supported + constraint was a hash constraint. This provides similar behaviour as public blockchain systems like Bitcoin and Ethereum, in + which code is entirely fixed once deployed and cannot be changed later. In Corda there is an upgrade path that involves the + cooperation of all involved parties (as advertised by the states themselves), but this requires explicit transactions to be + applied to all states and be signed by all parties. + + .. tip:: This is a fairly heavyweight operation. As such, consideration should be given as to the most opportune time at + which it should be performed. + + Hash constraints provide for maximum decentralisation and minimum trust, at the cost of flexibility. In Corda 3.0 we add a + new constraint, a _network parameters_ constraint, that allows the list of acceptable contract JARs to be maintained by the + operator of the compatibility zone rather than being hard-coded. This allows for simple upgrades at the cost of the introduction + of an element of centralisation. + + Zone constraints provide a less restrictive but more centralised control mechanism. This can be useful when you want + the ability to upgrade an app and you don’t mind the upgrade taking effect “just in time” when a transaction happens + to be required for other business reasons. These allow you to specify that the network parameters of a compatibility zone + (see :doc:`network-map`) is expected to contain a map of class name to hashes of JARs that are allowed to provide that + class. The process for upgrading an app then involves asking the zone operator to add the hash of your new JAR to the + parameters file, and trigger the network parameters upgrade process. This involves each node operator running a shell + command to accept the new parameters file and then restarting the node. Node owners who do not restart their node in + time effectively stop being a part of the network. + + .. note:: In prior versions of Corda, states included the hash of their defining application JAR (in the Hash Constraint). + In this release, transactions have the JAR containing the contract and states attached to them, so the code will be copied + over the network to the recipient if that peer lacks a copy of the app. + + Prior to running the verification code of a contract the JAR within which the verification code of the contract resides + is tested for compliance to the contract constraints: + - For the ``HashConstraint``: the hash of the deployed CorDapp jar must be the same as the hash found in the Transaction. + - For the ``ZoneConstraint``: the Transaction must come with a whitelisted attachment for each Contract State. + If this step fails the normal transaction verification failure path is followed. + + Corda 3.0 lays the groundwork for future releases, when contract verification will be done against the attached contract JARs + rather than requiring a locally deployed CorDapp of the exact version specified by the transaction. The future vision for this + feature will entail the dynamic downloading of the appropriate version of the smart contract and its execution within a + sandboxed environment. + + .. warning:: This change means that your app JAR must now fit inside the 10mb attachment size limit. To avoid redundantly copying + unneeded code over the network and to simplify upgrades, consider splitting your application into two or more JARs - one that + contains states and contracts (which we call the app "kernel"), and another that contains flows, services, web apps etc. For + example, our `Cordapp template `_ is structured like that. + Only the first will be attached. Also be aware that any dependencies your app kernel has must be bundled into a fat JAR, + as JAR dependencies are not supported in Corda 3.0. + + Future versions of Corda will add support for signature based constraints, in which any JAR signed by a given identity + can be attached to the transaction. This final constraint type provides a balance of all requirements: smooth rolling upgrades + can be performed without any additional steps or transactions being signed, at the cost of trusting the app developer more and + some additional complexity around managing app signing. + + Please see the :doc:`upgrading-cordapps` for more information on upgrading contracts. + +* **Test API Stability** + + A great deal of work has been carried out to refine the APIs provided to test CorDapps, making them simpler, more intuitive, + and generally easier to use. In addition, these APIs have been added to the *locked* list of the APIs we guarantee to be stable + over time. This should greatly increase productivity when upgrading between versions, as your testing environments will work + without alteration. + + Please see the :doc:`upgrade-notes` for more information on transitioning older tests to the new framework. + +Other Functional Improvements +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* **Clean Node Shutdown** + + We, alongside user feedback, concluded there was a strong need for the ability to have a clean inflection point where a node + could be shutdown without any in-flight transactions pending to allow for a clean system for upgrade purposes. As such, a flows + draining mode has been added. When activated, this places the node into a state of quiescence that guarantees no new work will + be started and all outstanding work completed prior to shutdown. + + A clean shutdown can thus be achieved by: + + 1. Subscribing to state machine updates + 2. Trigger flows draining mode by ``rpc.setFlowsDrainingModeEnabled(true)`` + 3. Wait until the subscription setup as phase 1 lets you know that no more checkpoints are around + 4. Shut the node down however you want + + .. note:: Once set, this mode is a persistent property that will be preserved across node restarts. It must be explicitly disabled + before a node will accept new RPC flow connections. + +* **X.509 certificates** + + These 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 - found at :doc:`permissioning`. + 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. +* **Configurable authorization and authentication data sources** - 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. + Corda can now be configured to load RPC user credentials and permissions from an external database and supports password + encryption based on the `Apache Shiro framework `_. See :ref:`RPC security management + ` for documentation. -* **AMQP Enabled**: - AMQP Serialization is now enabled for both peer to peer communication and the writing of 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. +* **SSH Server** - Details on the AMQP serialization framework can be found in the :doc:`serialization` document :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 pages :doc:`serialization-default-evolution` and :doc:`serialization-enum-evolution` - respectively. Recommendations on how best to code CorDapps using your own :ref:`custom types `. + Remote administration of Corda nodes through the CRaSH shell is now available via SSH, please see :doc:`shell` for more details. - .. 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. (https://docs.corda.net/releases/release-V1.0/serialization.html). +* **RPC over SSL** - In particular, you are advised to review the section titled "Custom Types". To aid with the transition, we have included support - in this release for default construction of objects and their instantiation through getters as well as 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. + Corda now allows for the configuration of its RPC calls to be made over SSL. See :doc:`corda-configuration-file` for details + how to configure this. -* **Custom Serializers** +* **Improved Notary configuration** - 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. + The configuration of notaries has been simplified into a single ``notary`` configuration object. See + :doc:`corda-configuration-file` for more details. - A good example of this is the SIMM valuation demo which has a number of such serializers defined in the plugin/customserializers package + .. note:: ``extraAdvertisedServiceIds``, ``notaryNodeAddress``, ``notaryClusterAddresses`` and ``bftSMaRt`` configs have been + removed. + +* **Database Tables Naming Scheme** + + To align with common conventions across all supported Corda and R3 Corda databases some table names have been changed. + + In addition, for existing contract ORM schemas that extend from CommonSchemaV1.LinearState or CommonSchemaV1.FungibleState, + you will need to explicitly map the participants collection to a database table. Previously this mapping was done in the + superclass, but that makes it impossible to properly configure the table name. The required change is to add the override var + ``participants: MutableSet? = null`` field to your class, and add JPA mappings. + +* **Pluggable Custom Serializers** + + With the introduction of AMQP we have introduced the requirement that to be seamlessly serializable classes, specifically + Java classes (as opposed to Kotlin), must be compiled with the ``-parameter`` flag. However, we recognise that this + isn't always possible, especially dealing with third party libraries in tightly controlled business environments. + + To work around this problem as simply as possible CorDapps now support the creation of pluggable proxy serializers for + such classes. These should be written such that they create an intermediary representation that Corda can serialise that + is mappable directly to and from the unserializable class. + + A number of examples are provided by the SIMM Valuation Demo in + + ``samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/plugin/customserializers`` + + Documentation can be found in :doc:`cordapp-custom-serializers` + + +Security Auditing +~~~~~~~~~~~~~~~~~ + + This version of Corda is the first to have had select components subjected to the newly established security review process + by R3's internal security team. Security review will be an on-going process that seeks to provide assurance that the + security model of Corda has been implemented to the highest standard, and is in line with industry best practice. + + As part of this security review process, an independent external security audit of the HTTP based components of the code + was undertaken and its recommendations were acted upon. The security assurance process will develop in parallel to the + Corda platform and will combine code review, automated security testing and secure development practices to ensure Corda + fulfils its security guarantees. + +Security fixes +~~~~~~~~~~~~~~ + + * Due to a potential privacy leak, there has been a breaking change in the error object returned by the + notary service when trying to consume the same state twice: `NotaryError.Conflict` no longer contains the identity + of the party that initiated the first spend of the state, and specifies the hash of the consuming transaction id for + a state instead of the id itself. + + Without this change, knowing the reference of a particular state, an attacker could construct an invalid + double-spend transaction, and obtain the information on the transaction and the party that consumed it. It could + repeat this process with the newly obtained transaction id by guessing its output indexes to obtain the forward + transaction graph with associated identities. When anonymous identities are used, this could also reveal the identity + of the owner of an asset. + +Minor Changes +~~~~~~~~~~~~~ + + * Upgraded gradle to 4.4.1. + + .. note:: To avoid potential incompatibility issues we recommend you also upgrade your CorDapp's gradle + plugin to match. Details on how to do this can be found on the official + `gradle website `_ + + * Cash Spending now allows for sending multiple amounts to multiple parties with a single API call + + - documentation can be found within the JavaDocs on ``TwoPartyTradeFlow``. + * Overall improvements to error handling (RPC, Flows, Network Client). + * TLS authentication now supports mixed RSA and ECDSA keys. + * PrivacySalt computation is faster as it does not depend on the OS's entropy pool directly. + * Numerous bug fixes and documentation tweaks. + * Removed dependency on Jolokia WAR file. Release 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. @@ -73,14 +325,14 @@ will only evolve to include new features. As of Corda 1.0, the following modules export public APIs for which we guarantee to maintain backwards compatibility, unless an incompatible change is required for security reasons: - * **core**: - Contains the bulk of the APIs to be used for building CorDapps: contracts, transactions, flows, identity, node services, + * **core**: + Contains the bulk of the APIs to be used for building CorDapps: contracts, transactions, flows, identity, node services, cryptographic libraries, and general utility functions. - * **client-rpc**: + * **client-rpc**: An RPC client interface to Corda, for use by both UI facing clients and integration with external systems. - * **client-jackson**: + * **client-jackson**: Utilities and serialisers for working with JSON representations of basic types. Our extensive testing frameworks will continue to evolve alongside future Corda APIs. As part of our commitment to ease of use and modularity @@ -96,8 +348,8 @@ Please read :doc:`corda-api` for complete details. Significant changes implemented in reaching Corda API stability include: * **Flow framework**: - The Flow framework communications API has been redesigned around session based communication with the introduction of a new - ``FlowSession`` to encapsulate the counterparty information associated with a flow. + The Flow framework communications API has been redesigned around session based communication with the introduction of a new + ``FlowSession`` to encapsulate the counterparty information associated with a flow. All shipped Corda flows have been upgraded to use the new `FlowSession`. Please read :doc:`api-flows` for complete details. * **Complete API cleanup**: @@ -112,14 +364,14 @@ Significant changes implemented in reaching Corda API stability include: optional `LegalProseReference` annotation to specify a URI is used. * **Java usability**: - All code has been updated to enable simple access to static API parameters. Developers no longer need to + All code has been updated to enable simple access to static API parameters. Developers no longer need to call getter methods, and can reference static API variables directly. In addition to API stability this release encompasses a number of major functional improvements, including: * **Contract constraints**: Provides a means with which to enforce a specific implementation of a State's verify method during transaction verification. - When loading an attachment via the attachment classloader, constraints of a transaction state are checked against the + When loading an attachment via the attachment classloader, constraints of a transaction state are checked against the list of attachment hashes provided, and the attachment is rejected if the constraints are not matched. * **Signature Metadata support**: @@ -156,7 +408,7 @@ In addition to API stability this release encompasses a number of major function identities will occur as we make the integration of this privacy feature into applications even easier for developers. * **Re-designed network map service**: - The foundations for a completely redesigned network map service have been implemented to enable future increased network + The foundations for a completely redesigned network map service have been implemented to enable future increased network scalability and redundancy, support for multiple notaries, and administration of network compatibility zones and business networks. Finally, please note that the 1.0 release has not yet been security audited. From 350218657275ad5c859b9bc0f05d9e5c677a63f2 Mon Sep 17 00:00:00 2001 From: bpaunescu Date: Wed, 14 Mar 2018 11:45:18 +0000 Subject: [PATCH 5/7] Bogdan - small rework of RPC client sending (#2812) * rework message handling while connection is down: do not send anything, throw on all obs and futures when failure detected * RPC calls will throw if used during failover; adapted tests --- .../net/corda/client/rpc/RPCStabilityTests.kt | 88 +------------------ .../rpc/internal/RPCClientProxyHandler.kt | 50 ++++++----- 2 files changed, 29 insertions(+), 109 deletions(-) diff --git a/client/rpc/src/integration-test/kotlin/net/corda/client/rpc/RPCStabilityTests.kt b/client/rpc/src/integration-test/kotlin/net/corda/client/rpc/RPCStabilityTests.kt index d616f34bb3..246358999c 100644 --- a/client/rpc/src/integration-test/kotlin/net/corda/client/rpc/RPCStabilityTests.kt +++ b/client/rpc/src/integration-test/kotlin/net/corda/client/rpc/RPCStabilityTests.kt @@ -7,16 +7,13 @@ import net.corda.core.crypto.random63BitValue import net.corda.core.internal.concurrent.fork import net.corda.core.internal.concurrent.transpose import net.corda.core.messaging.RPCOps -import net.corda.core.node.NodeInfo import net.corda.core.serialization.SerializationDefaults import net.corda.core.serialization.serialize import net.corda.core.utilities.* import net.corda.node.services.messaging.RPCServerConfiguration import net.corda.nodeapi.RPCApi -import net.corda.testing.core.ALICE_NAME import net.corda.testing.core.SerializationEnvironmentRule import net.corda.testing.internal.testThreadFactory -import net.corda.testing.node.User import net.corda.testing.node.internal.* import org.apache.activemq.artemis.api.core.SimpleString import org.junit.After @@ -28,15 +25,12 @@ import rx.Observable import rx.subjects.PublishSubject import rx.subjects.UnicastSubject import java.time.Duration -import java.time.Instant import java.util.concurrent.ConcurrentLinkedQueue import java.util.concurrent.Executors import java.util.concurrent.ScheduledExecutorService import java.util.concurrent.TimeUnit import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.atomic.AtomicLong -import kotlin.concurrent.thread -import kotlin.test.assertNotNull class RPCStabilityTests { @Rule @@ -253,42 +247,13 @@ class RPCStabilityTests { assertEquals("pong", client.ping()) serverFollower.shutdown() startRpcServer(ops = ops, customPort = serverPort).getOrThrow() + Thread.sleep(1000) //wait for the server to come back up val pingFuture = pool.fork(client::ping) assertEquals("pong", pingFuture.getOrThrow(10.seconds)) clientFollower.shutdown() // Driver would do this after the new server, causing hang. } } - @Test - fun `client reconnects to server and resends buffered messages`() { - rpcDriver(startNodesInProcess = false) { - var nodeInfo: NodeInfo? = null - var nodeTime: Instant? = null - val alice = startNode(providedName = ALICE_NAME, - rpcUsers = listOf(User("alice", "alice", setOf("ALL")))).getOrThrow() - CordaRPCClient(alice.rpcAddress).use("alice", "alice") { connection -> - val proxy = connection.proxy - alice.stop() - val nodeInfoThread = thread { - nodeInfo = proxy.nodeInfo() - } - - val currentTimeThread = thread { - nodeTime = proxy.currentNodeTime() - } - - Thread.sleep(5000) - startNode(providedName = ALICE_NAME, - rpcUsers = listOf(User("alice", "alice", setOf("ALL"))), - customOverrides = mapOf("rpcSettings" to mapOf("address" to "localhost:${alice.rpcAddress.port}"))) - currentTimeThread.join() - nodeInfoThread.join() - assertNotNull(nodeInfo) - assertNotNull(nodeTime) - } - } - } - @Test fun `connection failover fails, rpc calls throw`() { rpcDriver { @@ -356,57 +321,6 @@ class RPCStabilityTests { } } - interface ThreadOps : RPCOps { - fun sendMessage(id: Int, msgNo: Int): String - } - - @Test - fun `multiple threads with 1000 messages for each thread`() { - val messageNo = 1000 - val threadNo = 8 - val ops = object : ThreadOps { - override val protocolVersion = 0 - override fun sendMessage(id: Int, msgNo: Int): String { - return "($id-$msgNo)" - } - } - - rpcDriver(startNodesInProcess = false) { - val serverFollower = shutdownManager.follower() - val serverPort = startRpcServer(rpcUser = User("alice", "alice", setOf("ALL")), - ops = ops).getOrThrow().broker.hostAndPort!! - - serverFollower.unfollow() - val proxy = RPCClient(serverPort).start(ThreadOps::class.java, "alice", "alice").proxy - val expectedMap = mutableMapOf() - val resultsMap = mutableMapOf() - - (1 until threadNo).forEach { nr -> - (1 until messageNo).forEach { msgNo -> - expectedMap[nr] = expectedMap.getOrDefault(nr, StringBuilder()).append("($nr-$msgNo)") - } - } - - val threads = mutableMapOf() - (1 until threadNo).forEach { nr -> - val thread = thread { - (1 until messageNo).forEach { msgNo -> - resultsMap[nr] = resultsMap.getOrDefault(nr, StringBuilder()).append(proxy.sendMessage(nr, msgNo)) - } - } - threads[nr] = thread - } - // give the threads a chance to start sending some messages - Thread.sleep(50) - serverFollower.shutdown() - startRpcServer(rpcUser = User("alice", "alice", setOf("ALL")), - ops = ops, customPort = serverPort).getOrThrow() - threads.values.forEach { it.join() } - (1 until threadNo).forEach { assertEquals(expectedMap[it].toString(), resultsMap[it].toString()) } - } - - } - interface TrackSubscriberOps : RPCOps { fun subscribe(): Observable } diff --git a/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/RPCClientProxyHandler.kt b/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/RPCClientProxyHandler.kt index 274dd63941..54b931ed8d 100644 --- a/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/RPCClientProxyHandler.kt +++ b/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/RPCClientProxyHandler.kt @@ -41,6 +41,8 @@ import java.util.* import java.util.concurrent.* import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.atomic.AtomicLong +import java.util.concurrent.locks.ReentrantReadWriteLock +import kotlin.concurrent.withLock import kotlin.reflect.jvm.javaMethod /** @@ -161,9 +163,6 @@ class RPCClientProxyHandler( build() } - // Used to buffer client requests if the server is unavailable - private val outgoingRequestBuffer = ConcurrentHashMap() - private var sessionFactory: ClientSessionFactory? = null private var producerSession: ClientSession? = null private var consumerSession: ClientSession? = null @@ -173,6 +172,9 @@ class RPCClientProxyHandler( private val deduplicationChecker = DeduplicationChecker(rpcConfiguration.deduplicationCacheExpiry) private val deduplicationSequenceNumber = AtomicLong(0) + private val lock = ReentrantReadWriteLock() + private var sendingEnabled = true + /** * Start the client. This creates the per-client queue, starts the consumer session and the reaper. */ @@ -215,6 +217,11 @@ class RPCClientProxyHandler( throw RPCException("RPC Proxy is closed") } + lock.readLock().withLock { + if (!sendingEnabled) + throw RPCException("RPC server is not available.") + } + val replyId = InvocationId.newInstance() callSiteMap?.set(replyId, Throwable("")) try { @@ -233,13 +240,8 @@ class RPCClientProxyHandler( "Generated several RPC requests with same ID $replyId" } - outgoingRequestBuffer[replyId] = request - // try and send the request sendMessage(request) - val result = replyFuture.getOrThrow() - // at this point the server responded, remove the buffered request - outgoingRequestBuffer.remove(replyId) - return result + return replyFuture.getOrThrow() } catch (e: RuntimeException) { // Already an unchecked exception, so just rethrow it throw e @@ -407,8 +409,12 @@ class RPCClientProxyHandler( private fun failoverHandler(event: FailoverEventType) { when (event) { FailoverEventType.FAILURE_DETECTED -> { - log.warn("RPC server unavailable. RPC calls are being buffered.") - log.warn("Terminating observables.") + lock.writeLock().withLock { + sendingEnabled = false + } + + log.warn("RPC server unavailable.") + log.warn("Terminating observables and in flight RPCs.") val m = observableContext.observableMap.asMap() m.keys.forEach { k -> observationExecutorPool.run(k) { @@ -416,24 +422,24 @@ class RPCClientProxyHandler( } } observableContext.observableMap.invalidateAll() + + rpcReplyMap.forEach { _, replyFuture -> + replyFuture.setException(RPCException("Connection failure detected.")) + } + + rpcReplyMap.clear() + callSiteMap?.clear() } FailoverEventType.FAILOVER_COMPLETED -> { - log.info("RPC server available. Draining request buffer.") - outgoingRequestBuffer.keys.forEach { replyId -> - outgoingRequestBuffer[replyId]?.let { sendMessage(it) } + lock.writeLock().withLock { + sendingEnabled = true } + log.info("RPC server available.") } FailoverEventType.FAILOVER_FAILED -> { - log.error("Could not reconnect to the RPC server. All buffered requests will be discarded and RPC calls " + - "will throw an RPCException.") - rpcReplyMap.forEach { id, replyFuture -> - replyFuture.setException(RPCException("Could not re-connect to RPC server. Failover failed.")) - } - outgoingRequestBuffer.clear() - rpcReplyMap.clear() - callSiteMap?.clear() + log.error("Could not reconnect to the RPC server.") } } } From dc250bc7013b22abefad4d157e706bc7a06a2054 Mon Sep 17 00:00:00 2001 From: Joel Dudley Date: Wed, 14 Mar 2018 11:45:26 +0000 Subject: [PATCH 6/7] Minor clarification of network map docs. --- docs/source/network-map.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/network-map.rst b/docs/source/network-map.rst index c5f83f7d29..e0986d52f6 100644 --- a/docs/source/network-map.rst +++ b/docs/source/network-map.rst @@ -22,9 +22,9 @@ HTTP network map protocol ------------------------- 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 entries are downloaded and cached. Entries which no longer exist are deleted from the node's cache. +to the server at that URL (and each time it changes on startup) and then proceeds to download the entire network map from +the same server. 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 entries are downloaded and cached. Entries which no longer exist are deleted from the node's cache. The set of REST end-points for the network map service are as follows. From 1407f01600e09350f047b8ee5893c76f1cccefda Mon Sep 17 00:00:00 2001 From: Chris Rankin Date: Wed, 14 Mar 2018 12:47:38 +0000 Subject: [PATCH 7/7] Upgrade to corda-gradle-plugins 4.0.8 (#2815) * Add missing @DoNotImplement annotations. * Upgrade to corda-gradle-plugins 4.0.8 --- .ci/api-current.txt | 30 +++++++++++++++--------------- constants.properties | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.ci/api-current.txt b/.ci/api-current.txt index 51726ff636..8a30c60338 100644 --- a/.ci/api-current.txt +++ b/.ci/api-current.txt @@ -3918,7 +3918,7 @@ public final class net.corda.testing.driver.NotaryHandle extends java.lang.Objec @org.jetbrains.annotations.NotNull public final net.corda.core.utilities.NetworkHostAndPort nextHostAndPort() public abstract int nextPort() ## -public static final class net.corda.testing.driver.PortAllocation$Incremental extends net.corda.testing.driver.PortAllocation +@net.corda.core.DoNotImplement public static final class net.corda.testing.driver.PortAllocation$Incremental extends net.corda.testing.driver.PortAllocation public (int) @org.jetbrains.annotations.NotNull public final concurrent.atomic.AtomicInteger getPortCounter() public int nextPort() @@ -3943,7 +3943,7 @@ public final class net.corda.testing.driver.WebserverHandle extends java.lang.Ob public () public abstract int getClusterSize() ## -public static final class net.corda.testing.node.ClusterSpec$Raft extends net.corda.testing.node.ClusterSpec +@net.corda.core.DoNotImplement public static final class net.corda.testing.node.ClusterSpec$Raft extends net.corda.testing.node.ClusterSpec public (int) public final int component1() @org.jetbrains.annotations.NotNull public final net.corda.testing.node.ClusterSpec$Raft copy(int) @@ -4003,13 +4003,13 @@ public static final class net.corda.testing.node.InMemoryMessagingNetwork$MockMe @net.corda.core.DoNotImplement public abstract static class net.corda.testing.node.InMemoryMessagingNetwork$ServicePeerAllocationStrategy extends java.lang.Object public abstract Object pickNext(net.corda.testing.node.InMemoryMessagingNetwork$DistributedServiceHandle, List) ## -public static final class net.corda.testing.node.InMemoryMessagingNetwork$ServicePeerAllocationStrategy$Random extends net.corda.testing.node.InMemoryMessagingNetwork$ServicePeerAllocationStrategy +@net.corda.core.DoNotImplement public static final class net.corda.testing.node.InMemoryMessagingNetwork$ServicePeerAllocationStrategy$Random extends net.corda.testing.node.InMemoryMessagingNetwork$ServicePeerAllocationStrategy public () public (SplittableRandom) @org.jetbrains.annotations.NotNull public final SplittableRandom getRandom() public Object pickNext(net.corda.testing.node.InMemoryMessagingNetwork$DistributedServiceHandle, List) ## -public static final class net.corda.testing.node.InMemoryMessagingNetwork$ServicePeerAllocationStrategy$RoundRobin extends net.corda.testing.node.InMemoryMessagingNetwork$ServicePeerAllocationStrategy +@net.corda.core.DoNotImplement public static final class net.corda.testing.node.InMemoryMessagingNetwork$ServicePeerAllocationStrategy$RoundRobin extends net.corda.testing.node.InMemoryMessagingNetwork$ServicePeerAllocationStrategy public () public Object pickNext(net.corda.testing.node.InMemoryMessagingNetwork$DistributedServiceHandle, List) ## @@ -4297,7 +4297,7 @@ public final class net.corda.client.rpc.CordaRPCClientConfiguration extends java ## public static final class net.corda.client.rpc.CordaRPCClientConfiguration$Companion extends java.lang.Object ## -public final class net.corda.client.rpc.CordaRPCConnection extends java.lang.Object implements net.corda.client.rpc.RPCConnection +@net.corda.core.DoNotImplement public final class net.corda.client.rpc.CordaRPCConnection extends java.lang.Object implements net.corda.client.rpc.RPCConnection public (net.corda.client.rpc.RPCConnection) public void close() public void forceClose() @@ -4354,7 +4354,7 @@ public static final class net.corda.testing.contracts.DummyContract$Companion ex @kotlin.jvm.JvmStatic @org.jetbrains.annotations.NotNull public final net.corda.core.transactions.TransactionBuilder move(List, net.corda.core.identity.AbstractParty) @kotlin.jvm.JvmStatic @org.jetbrains.annotations.NotNull public final net.corda.core.transactions.TransactionBuilder move(net.corda.core.contracts.StateAndRef, net.corda.core.identity.AbstractParty) ## -public static final class net.corda.testing.contracts.DummyContract$MultiOwnerState extends java.lang.Object implements net.corda.testing.contracts.DummyContract$State +@net.corda.core.DoNotImplement public static final class net.corda.testing.contracts.DummyContract$MultiOwnerState extends java.lang.Object implements net.corda.testing.contracts.DummyContract$State public (int, List) public final int component1() @org.jetbrains.annotations.NotNull public final List component2() @@ -4366,7 +4366,7 @@ public static final class net.corda.testing.contracts.DummyContract$MultiOwnerSt public int hashCode() public String toString() ## -public static final class net.corda.testing.contracts.DummyContract$SingleOwnerState extends java.lang.Object implements net.corda.testing.contracts.DummyContract$State, net.corda.core.contracts.OwnableState +@net.corda.core.DoNotImplement public static final class net.corda.testing.contracts.DummyContract$SingleOwnerState extends java.lang.Object implements net.corda.testing.contracts.DummyContract$State, net.corda.core.contracts.OwnableState public (int, net.corda.core.identity.AbstractParty) public final int component1() @org.jetbrains.annotations.NotNull public final net.corda.core.identity.AbstractParty component2() @@ -4442,15 +4442,15 @@ public final class net.corda.testing.core.Expect extends java.lang.Object ## @net.corda.core.DoNotImplement public abstract class net.corda.testing.core.ExpectCompose extends java.lang.Object ## -public static final class net.corda.testing.core.ExpectCompose$Parallel extends net.corda.testing.core.ExpectCompose +@net.corda.core.DoNotImplement public static final class net.corda.testing.core.ExpectCompose$Parallel extends net.corda.testing.core.ExpectCompose public (List) @org.jetbrains.annotations.NotNull public final List getParallel() ## -public static final class net.corda.testing.core.ExpectCompose$Sequential extends net.corda.testing.core.ExpectCompose +@net.corda.core.DoNotImplement public static final class net.corda.testing.core.ExpectCompose$Sequential extends net.corda.testing.core.ExpectCompose public (List) @org.jetbrains.annotations.NotNull public final List getSequence() ## -public static final class net.corda.testing.core.ExpectCompose$Single extends net.corda.testing.core.ExpectCompose +@net.corda.core.DoNotImplement public static final class net.corda.testing.core.ExpectCompose$Single extends net.corda.testing.core.ExpectCompose public (net.corda.testing.core.Expect) @org.jetbrains.annotations.NotNull public final net.corda.testing.core.Expect getExpect() ## @@ -4558,10 +4558,10 @@ public final class net.corda.testing.dsl.DuplicateOutputLabel extends net.corda. ## @net.corda.core.DoNotImplement public abstract class net.corda.testing.dsl.EnforceVerifyOrFail extends java.lang.Object ## -public static final class net.corda.testing.dsl.EnforceVerifyOrFail$Token extends net.corda.testing.dsl.EnforceVerifyOrFail +@net.corda.core.DoNotImplement public static final class net.corda.testing.dsl.EnforceVerifyOrFail$Token extends net.corda.testing.dsl.EnforceVerifyOrFail public static final net.corda.testing.dsl.EnforceVerifyOrFail$Token INSTANCE ## -public final class net.corda.testing.dsl.LedgerDSL extends java.lang.Object implements net.corda.testing.dsl.LedgerDSLInterpreter +@net.corda.core.DoNotImplement public final class net.corda.testing.dsl.LedgerDSL extends java.lang.Object implements net.corda.testing.dsl.LedgerDSLInterpreter public (net.corda.testing.dsl.LedgerDSLInterpreter, net.corda.core.identity.Party) @org.jetbrains.annotations.NotNull public net.corda.core.transactions.WireTransaction _transaction(String, net.corda.core.transactions.TransactionBuilder, kotlin.jvm.functions.Function1) public void _tweak(kotlin.jvm.functions.Function1) @@ -4591,7 +4591,7 @@ public final class net.corda.testing.dsl.LedgerDSL extends java.lang.Object impl @net.corda.core.DoNotImplement public interface net.corda.testing.dsl.OutputStateLookup @org.jetbrains.annotations.NotNull public abstract net.corda.core.contracts.StateAndRef retrieveOutputStateAndRef(Class, String) ## -public final class net.corda.testing.dsl.TestLedgerDSLInterpreter extends java.lang.Object implements net.corda.testing.dsl.LedgerDSLInterpreter +@net.corda.core.DoNotImplement public final class net.corda.testing.dsl.TestLedgerDSLInterpreter extends java.lang.Object implements net.corda.testing.dsl.LedgerDSLInterpreter public (net.corda.core.node.ServiceHub) @org.jetbrains.annotations.NotNull public net.corda.core.transactions.WireTransaction _transaction(String, net.corda.core.transactions.TransactionBuilder, kotlin.jvm.functions.Function1) public void _tweak(kotlin.jvm.functions.Function1) @@ -4636,7 +4636,7 @@ public static final class net.corda.testing.dsl.TestLedgerDSLInterpreter$WireTra public int hashCode() public String toString() ## -public final class net.corda.testing.dsl.TestTransactionDSLInterpreter extends java.lang.Object implements net.corda.testing.dsl.TransactionDSLInterpreter, net.corda.testing.dsl.OutputStateLookup +@net.corda.core.DoNotImplement public final class net.corda.testing.dsl.TestTransactionDSLInterpreter extends java.lang.Object implements net.corda.testing.dsl.TransactionDSLInterpreter, net.corda.testing.dsl.OutputStateLookup public (net.corda.testing.dsl.TestLedgerDSLInterpreter, net.corda.core.transactions.TransactionBuilder) public void _attachment(String) @org.jetbrains.annotations.NotNull public net.corda.testing.dsl.EnforceVerifyOrFail _tweak(kotlin.jvm.functions.Function1) @@ -4668,7 +4668,7 @@ public static final class net.corda.testing.dsl.TestTransactionDSLInterpreter$se @org.jetbrains.annotations.NotNull public net.corda.core.contracts.TransactionState loadState(net.corda.core.contracts.StateRef) @org.jetbrains.annotations.NotNull public Set loadStates(Set) ## -public final class net.corda.testing.dsl.TransactionDSL extends java.lang.Object implements net.corda.testing.dsl.TransactionDSLInterpreter +@net.corda.core.DoNotImplement public final class net.corda.testing.dsl.TransactionDSL extends java.lang.Object implements net.corda.testing.dsl.TransactionDSLInterpreter public (net.corda.testing.dsl.TransactionDSLInterpreter, net.corda.core.identity.Party) public void _attachment(String) @org.jetbrains.annotations.NotNull public net.corda.testing.dsl.EnforceVerifyOrFail _tweak(kotlin.jvm.functions.Function1) diff --git a/constants.properties b/constants.properties index 18351cbaaa..3f219493b2 100644 --- a/constants.properties +++ b/constants.properties @@ -1,4 +1,4 @@ -gradlePluginsVersion=4.0.6 +gradlePluginsVersion=4.0.8 kotlinVersion=1.2.20 platformVersion=4 guavaVersion=21.0