From e47e9d546dd63bbd858960608ea0d324651b02ad Mon Sep 17 00:00:00 2001 From: Joseph Zuniga-Daly <59851625+josephzunigadaly@users.noreply.github.com> Date: Tue, 3 Mar 2020 16:06:46 +0000 Subject: [PATCH 1/9] Fix the operator used by the notEqual predicate (#6022) * Fix the operator used by the notEqual predicate * Add timeouts to tests * Add change to changelog --- .../node/services/vault/QueryCriteriaUtils.kt | 2 +- docs/source/changelog.rst | 2 + .../vault/QueryCriteriaUtilsBuilderTest.kt | 165 ++++++++++++++++++ 3 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 node/src/test/kotlin/net/corda/node/services/vault/QueryCriteriaUtilsBuilderTest.kt diff --git a/core/src/main/kotlin/net/corda/core/node/services/vault/QueryCriteriaUtils.kt b/core/src/main/kotlin/net/corda/core/node/services/vault/QueryCriteriaUtils.kt index a698038242..70983a7056 100644 --- a/core/src/main/kotlin/net/corda/core/node/services/vault/QueryCriteriaUtils.kt +++ b/core/src/main/kotlin/net/corda/core/node/services/vault/QueryCriteriaUtils.kt @@ -303,7 +303,7 @@ object Builder { @JvmStatic @JvmOverloads - fun FieldInfo.notEqual(value: R, exactMatch: Boolean = true) = predicate(Builder.equal(value, exactMatch)) + fun FieldInfo.notEqual(value: R, exactMatch: Boolean = true) = predicate(Builder.notEqual(value, exactMatch)) @JvmStatic @Deprecated("Does not support fields from a MappedSuperclass. Use equivalent on a FieldInfo.") diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst index b05887084a..7b77cb085f 100644 --- a/docs/source/changelog.rst +++ b/docs/source/changelog.rst @@ -83,6 +83,8 @@ Unreleased * :doc:`design/data-model-upgrades/package-namespace-ownership` configurations can be now be set as described in :ref:`node_package_namespace_ownership`, when using the Cordformation plugin version 4.0.43. +* Fixed the operator used by the ``notEqual`` predicate + .. _changelog_v4.1: Version 4.1 diff --git a/node/src/test/kotlin/net/corda/node/services/vault/QueryCriteriaUtilsBuilderTest.kt b/node/src/test/kotlin/net/corda/node/services/vault/QueryCriteriaUtilsBuilderTest.kt new file mode 100644 index 0000000000..646a539762 --- /dev/null +++ b/node/src/test/kotlin/net/corda/node/services/vault/QueryCriteriaUtilsBuilderTest.kt @@ -0,0 +1,165 @@ +package net.corda.node.services.vault + +import net.corda.core.node.services.vault.BinaryComparisonOperator +import net.corda.core.node.services.vault.Builder.`in` +import net.corda.core.node.services.vault.Builder.equal +import net.corda.core.node.services.vault.Builder.greaterThan +import net.corda.core.node.services.vault.Builder.greaterThanOrEqual +import net.corda.core.node.services.vault.Builder.isNull +import net.corda.core.node.services.vault.Builder.lessThan +import net.corda.core.node.services.vault.Builder.lessThanOrEqual +import net.corda.core.node.services.vault.Builder.like +import net.corda.core.node.services.vault.Builder.notEqual +import net.corda.core.node.services.vault.Builder.notIn +import net.corda.core.node.services.vault.Builder.notLike +import net.corda.core.node.services.vault.Builder.notNull +import net.corda.core.node.services.vault.CollectionOperator +import net.corda.core.node.services.vault.ColumnPredicate +import net.corda.core.node.services.vault.ColumnPredicate.AggregateFunction +import net.corda.core.node.services.vault.ColumnPredicate.Between +import net.corda.core.node.services.vault.ColumnPredicate.BinaryComparison +import net.corda.core.node.services.vault.ColumnPredicate.CollectionExpression +import net.corda.core.node.services.vault.ColumnPredicate.EqualityComparison +import net.corda.core.node.services.vault.ColumnPredicate.Likeness +import net.corda.core.node.services.vault.ColumnPredicate.NullExpression +import net.corda.core.node.services.vault.CriteriaExpression.ColumnPredicateExpression +import net.corda.core.node.services.vault.EqualityComparisonOperator +import net.corda.core.node.services.vault.FieldInfo +import net.corda.core.node.services.vault.LikenessOperator +import net.corda.core.node.services.vault.NullOperator +import net.corda.core.node.services.vault.Operator +import net.corda.core.node.services.vault.getField +import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.api.ObjectAssert +import org.junit.Test +import javax.persistence.Entity + +class QueryCriteriaUtilsBuilderTest { + + /** JPA Entity class needed by `getField` */ + @Entity + private class TestEntity(val field: String) + + /** Returns a `FieldInfo` object to work on */ + private val fieldInfo: FieldInfo get() = getField("field", TestEntity::class.java) + + /** Thrown for the `ColumnPredicate` types that have no `operator` field */ + private class ColumnPredicateHasNoOperatorFieldException : Exception("This ColumnPredicate has no operator field") + + /** Returns the `operator` for the given `ColumnPredicate` */ + private fun ColumnPredicate.getOperator(): Operator = when (this) { + is AggregateFunction -> throw ColumnPredicateHasNoOperatorFieldException() + is Between -> throw ColumnPredicateHasNoOperatorFieldException() + is BinaryComparison<*> -> operator + is CollectionExpression -> operator + is EqualityComparison<*> -> operator + is Likeness -> operator + is NullExpression -> operator + } + + /** Returns the `operator` for the given `ColumnPredicateExpression` */ + private fun ColumnPredicateExpression.getOperator(): Operator = this.predicate.getOperator() + + /** Assert that the `ColumnPredicateExpression` uses the given `Operator`. */ + private fun , C> ObjectAssert.usesOperator(operator: Operator) { + extracting { + assertThat(it.getOperator()).isEqualTo(operator) + } + } + + /** Sample `String` value to pass to the predicate expression */ + private val stringValue = "" + + /** Sample `List` value to pass to the predicate expression */ + private val listValue = emptyList() + + @Test(timeout = 500) + fun `equal predicate uses EQUAL operator`() { + assertThat(fieldInfo.equal(stringValue)).usesOperator(EqualityComparisonOperator.EQUAL) + } + + @Test(timeout = 500) + fun `equal predicate (exactMatch=false) uses EQUAL_IGNORE_CASE operator`() { + assertThat(fieldInfo.equal(stringValue, exactMatch = false)).usesOperator(EqualityComparisonOperator.EQUAL_IGNORE_CASE) + } + + @Test(timeout = 500) + fun `notEqual predicate uses NOT_EQUAL operator`() { + assertThat(fieldInfo.notEqual(stringValue)).usesOperator(EqualityComparisonOperator.NOT_EQUAL) + } + + @Test(timeout = 500) + fun `notEqual predicate (exactMatch=false) uses NOT_EQUAL_IGNORE_CASE operator`() { + assertThat(fieldInfo.notEqual(stringValue, exactMatch = false)).usesOperator(EqualityComparisonOperator.NOT_EQUAL_IGNORE_CASE) + } + + @Test(timeout = 500) + fun `lessThan predicate uses LESS_THAN operator`() { + assertThat(fieldInfo.lessThan(stringValue)).usesOperator(BinaryComparisonOperator.LESS_THAN) + } + + @Test(timeout = 500) + fun `lessThanOrEqual predicate uses LESS_THAN_OR_EQUAL operator`() { + assertThat(fieldInfo.lessThanOrEqual(stringValue)).usesOperator(BinaryComparisonOperator.LESS_THAN_OR_EQUAL) + } + + @Test(timeout = 500) + fun `greaterThan predicate uses GREATER_THAN operator`() { + assertThat(fieldInfo.greaterThan(stringValue)).usesOperator(BinaryComparisonOperator.GREATER_THAN) + } + + @Test(timeout = 500) + fun `greaterThanOrEqual predicate uses GREATER_THAN_OR_EQUAL operator`() { + assertThat(fieldInfo.greaterThanOrEqual(stringValue)).usesOperator(BinaryComparisonOperator.GREATER_THAN_OR_EQUAL) + } + + @Test(timeout = 500) + fun `in predicate uses IN operator`() { + assertThat(fieldInfo.`in`(listValue)).usesOperator(CollectionOperator.IN) + } + + @Test(timeout = 500) + fun `in predicate (exactMatch=false) uses IN_IGNORE_CASE operator`() { + assertThat(fieldInfo.`in`(listValue, exactMatch = false)).usesOperator(CollectionOperator.IN_IGNORE_CASE) + } + + @Test(timeout = 500) + fun `notIn predicate uses NOT_IN operator`() { + assertThat(fieldInfo.notIn(listValue)).usesOperator(CollectionOperator.NOT_IN) + } + + @Test(timeout = 500) + fun `notIn predicate (exactMatch=false) uses NOT_IN_IGNORE_CASE operator`() { + assertThat(fieldInfo.notIn(listValue, exactMatch = false)).usesOperator(CollectionOperator.NOT_IN_IGNORE_CASE) + } + + @Test(timeout = 500) + fun `like predicate uses LIKE operator`() { + assertThat(fieldInfo.like(stringValue)).usesOperator(LikenessOperator.LIKE) + } + + @Test(timeout = 500) + fun `like predicate (exactMatch=false) uses LIKE_IGNORE_CASE operator`() { + assertThat(fieldInfo.like(stringValue, exactMatch = false)).usesOperator(LikenessOperator.LIKE_IGNORE_CASE) + } + + @Test(timeout = 500) + fun `notLike predicate uses NOT_LIKE operator`() { + assertThat(fieldInfo.notLike(stringValue)).usesOperator(LikenessOperator.NOT_LIKE) + } + + @Test(timeout = 500) + fun `notLike predicate (exactMatch=false) uses NOT_LIKE_IGNORE_CASE operator`() { + assertThat(fieldInfo.notLike(stringValue, exactMatch = false)).usesOperator(LikenessOperator.NOT_LIKE_IGNORE_CASE) + } + + @Test(timeout = 500) + fun `isNull predicate uses IS_NULL operator`() { + assertThat(fieldInfo.isNull()).usesOperator(NullOperator.IS_NULL) + } + + @Test(timeout = 500) + fun `notNull predicate uses NOT_NULL operator`() { + assertThat(fieldInfo.notNull()).usesOperator(NullOperator.NOT_NULL) + } +} From b02768aa6e51f56993a6db04b27e6b1b0f72aa84 Mon Sep 17 00:00:00 2001 From: Joseph Zuniga-Daly Date: Mon, 9 Mar 2020 15:08:40 +0000 Subject: [PATCH 2/9] CORDA-3394: Move unit test to correct location --- .../core}/node/services/vault/QueryCriteriaUtilsBuilderTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename {node/src/test/kotlin/net/corda => core/src/test/kotlin/net/corda/core}/node/services/vault/QueryCriteriaUtilsBuilderTest.kt (99%) diff --git a/node/src/test/kotlin/net/corda/node/services/vault/QueryCriteriaUtilsBuilderTest.kt b/core/src/test/kotlin/net/corda/core/node/services/vault/QueryCriteriaUtilsBuilderTest.kt similarity index 99% rename from node/src/test/kotlin/net/corda/node/services/vault/QueryCriteriaUtilsBuilderTest.kt rename to core/src/test/kotlin/net/corda/core/node/services/vault/QueryCriteriaUtilsBuilderTest.kt index 646a539762..86b6dfcea0 100644 --- a/node/src/test/kotlin/net/corda/node/services/vault/QueryCriteriaUtilsBuilderTest.kt +++ b/core/src/test/kotlin/net/corda/core/node/services/vault/QueryCriteriaUtilsBuilderTest.kt @@ -1,4 +1,4 @@ -package net.corda.node.services.vault +package net.corda.core.node.services.vault import net.corda.core.node.services.vault.BinaryComparisonOperator import net.corda.core.node.services.vault.Builder.`in` From 3973fe46f250af045e17f2b3413e8668f1c1e1ff Mon Sep 17 00:00:00 2001 From: Joel Dudley Date: Mon, 9 Mar 2020 15:11:53 +0000 Subject: [PATCH 3/9] Update contributing-philosophy.rst (#6044) --- docs/source/contributing-philosophy.rst | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/docs/source/contributing-philosophy.rst b/docs/source/contributing-philosophy.rst index 8d1eeab10d..dbed0dc099 100644 --- a/docs/source/contributing-philosophy.rst +++ b/docs/source/contributing-philosophy.rst @@ -11,8 +11,7 @@ modern business transactions. It is unique in its aim to build a platform for b retaining strict privacy. Corda provides an implementation of this vision in a code base which others are free to build on, contribute to or innovate around. The mission of Corda is further detailed in the `Corda introductory white paper`_. -The project is supported and maintained by the `R3 Alliance `_, or R3 for short, which consists of over two hundred firms -working together to build and maintain this open source enterprise-grade blockchain platform. +The project is supported and maintained by `R3 `_. Community Locations ------------------- @@ -44,12 +43,12 @@ Community maintainers ^^^^^^^^^^^^^^^^^^^^^ Current community maintainers: -* `Joel Dudley `_ - Contact me: +* `Rick Parker `_ - Contact me: * On the `Corda Slack team `_, either in the ``#community`` channel or by direct message using the handle - ``@joel`` + ``@parkri`` - * By email: joel.dudley at r3.com + * By email: rick.parker at r3.com We anticipate additional maintainers joining the project in the future from across the community. @@ -60,13 +59,12 @@ Over two hundred individuals have contributed to the development of Corda. You c Transparency and Conflict Policy -------------------------------- -The project is supported and maintained by the `R3 Alliance `_, which consists of over two hundred firms working together -to build and maintain this open source enterprise-grade blockchain platform. We develop in the open and publish our +The project is supported and maintained by `R3 `_. We develop in the open and publish our `Jira `_ to give everyone visibility. R3 also maintains and distributes a commercial distribution of Corda. Our vision is that distributions of Corda be compatible and interoperable, and our contribution and code review guidelines are designed in part to enable this. -As the R3 Alliance is maintainer of the project and also develops a commercial distribution of Corda, what happens if a member of the +As R3 is maintainer of the project and also develops a commercial distribution of Corda, what happens if a member of the community contributes a feature which the R3 team have implemented only in their commercial product? How is this apparent conflict managed? Our approach is simple: if the contribution meets the standards for the project (see above), then the existence of a competing commercial implementation will not be used as a reason to reject it. In other words, it is our policy that should a community feature be contributed From d61536c6ffa1c47bf28accea249a09aed8f786bb Mon Sep 17 00:00:00 2001 From: VCAMP Date: Wed, 11 Mar 2020 11:56:46 +0000 Subject: [PATCH 4/9] OS 4.4 release notes: added warning about integration testing changes (#6025) * OS 4.4 release notes: added warning about integration testing changes * OS 4.4 release notes: more datail on integration testing changes --- docs/source/release-notes.rst | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/docs/source/release-notes.rst b/docs/source/release-notes.rst index 67291c790e..029f89a10b 100644 --- a/docs/source/release-notes.rst +++ b/docs/source/release-notes.rst @@ -51,6 +51,26 @@ Security enhancements * The ability to SSH into the standalone shell has been removed * A new read-only RPC user role template has been documented in :doc:`shell` +Changes to integration testing ++++++++++++++++++++++++ + +The "out-of-process" nodes spawned through Driver DSL (see :doc:`tutorial-integration-testing`) will no longer accidentally contain your CorDapps on their application classpath. The list of items that will be automatically filtered out include: + +* Directories (only regular files are allowed) +* Jars with Maven classifiers ``tests`` or ``test`` +* Jars with any Cordapp attributes in their manifests (any of those listed in :doc:`cordapp-build-systems` or ``Target-Platform-Version`` and ``Min-Platform-Version`` if both are present) +* Jars with the ``Corda-Testing`` attribute in their manifests. The manifest of the following artifacts has been updated to include the ``Corda-Testing`` attribute: + + * ``corda-node-driver`` + * ``corda-test-utils`` + * ``corda-test-common`` + * ``corda-test-db`` + * ``corda-mock`` + +* Files whose names start with ``corda-mock``, ``junit``, ``testng`` or ``mockito`` + +Some of your existing integration tests might implicitly be relying on the presence of the above files, so please keep this in mind when upgrading your version of Corda. + Platform version change ~~~~~~~~~~~~~~~~~~~~~~~ From c565d47adcc2fecc78a845ba6d7c9de85e52f9c5 Mon Sep 17 00:00:00 2001 From: Stefano Franz Date: Thu, 12 Mar 2020 08:15:28 +0000 Subject: [PATCH 5/9] use proxied gradle to prevent slow lorrising due to too many requests (#6056) * use proxied gradle to prevent slow lorrising due to too many requests * fix typo --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 4483da647f..2e954d6bc7 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ #Wed Aug 21 10:48:19 BST 2019 -distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip +distributionUrl=https\://gradleproxy:gradleproxy@software.r3.com/artifactory/gradle-proxy/gradle-5.4.1-all.zip distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStorePath=wrapper/dists From 8973c5ba961e1bafed081c253d77932658f2f1e6 Mon Sep 17 00:00:00 2001 From: Razvan Codreanu <52859362+Schife@users.noreply.github.com> Date: Thu, 12 Mar 2020 10:04:22 +0000 Subject: [PATCH 6/9] TM-168 reusable configurations for distributed testing (#6048) * TM-168 reusable configurations for distributed testing * TM-168 switching to class * TM-168 switching to ext properties * TM-168 large scale set is too aggressive and prone to failure so switching to general purpose --- build.gradle | 80 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 48 insertions(+), 32 deletions(-) diff --git a/build.gradle b/build.gradle index d4e1cdee29..0772c6740a 100644 --- a/build.gradle +++ b/build.gradle @@ -633,61 +633,77 @@ buildScan { termsOfServiceAgree = 'yes' } +ext.generalPurpose = [ + numberOfShards: 10, + streamOutput: false, + coresPerFork: 2, + memoryInGbPerFork: 12, + nodeTaints: "small" +] + +ext.largeScaleSet = [ + numberOfShards: 15, + streamOutput: false, + coresPerFork: 6, + memoryInGbPerFork: 10, + nodeTaints: "big" +] + task allParallelIntegrationTest(type: ParallelTestGroup) { podLogLevel PodLogLevel.INFO testGroups "integrationTest" - numberOfShards 10 - streamOutput false - coresPerFork 2 - memoryInGbPerFork 12 + numberOfShards generalPurpose.numberOfShards + streamOutput generalPurpose.streamOutput + coresPerFork generalPurpose.coresPerFork + memoryInGbPerFork generalPurpose.memoryInGbPerFork + nodeTaints generalPurpose.nodeTaints distribute DistributeTestsBy.METHOD - nodeTaints "big" } task allParallelUnitTest(type: ParallelTestGroup) { podLogLevel PodLogLevel.INFO testGroups "test" - numberOfShards 10 - streamOutput false - coresPerFork 2 - memoryInGbPerFork 12 + numberOfShards generalPurpose.numberOfShards + streamOutput generalPurpose.streamOutput + coresPerFork generalPurpose.coresPerFork + memoryInGbPerFork generalPurpose.memoryInGbPerFork + nodeTaints generalPurpose.nodeTaints distribute DistributeTestsBy.CLASS - nodeTaints "small" } task allParallelUnitAndIntegrationTest(type: ParallelTestGroup) { testGroups "test", "integrationTest" - numberOfShards 15 - streamOutput false - coresPerFork 6 - memoryInGbPerFork 10 + numberOfShards generalPurpose.numberOfShards + streamOutput generalPurpose.streamOutput + coresPerFork generalPurpose.coresPerFork + memoryInGbPerFork generalPurpose.memoryInGbPerFork + nodeTaints generalPurpose.nodeTaints distribute DistributeTestsBy.METHOD - nodeTaints "big" } task parallelRegressionTest(type: ParallelTestGroup) { testGroups "test", "integrationTest", "smokeTest" - numberOfShards 15 - streamOutput false - coresPerFork 2 - memoryInGbPerFork 10 + numberOfShards generalPurpose.numberOfShards + streamOutput generalPurpose.streamOutput + coresPerFork generalPurpose.coresPerFork + memoryInGbPerFork generalPurpose.memoryInGbPerFork + nodeTaints generalPurpose.nodeTaints distribute DistributeTestsBy.METHOD - nodeTaints "big" } task allParallelSmokeTest(type: ParallelTestGroup) { testGroups "smokeTest" - numberOfShards 4 - streamOutput false - coresPerFork 6 - memoryInGbPerFork 10 - distribute DistributeTestsBy.CLASS - nodeTaints "big" + numberOfShards generalPurpose.numberOfShards + streamOutput generalPurpose.streamOutput + coresPerFork generalPurpose.coresPerFork + memoryInGbPerFork generalPurpose.memoryInGbPerFork + nodeTaints generalPurpose.nodeTaints + distribute DistributeTestsBy.METHOD } task allParallelSlowIntegrationTest(type: ParallelTestGroup) { testGroups "slowIntegrationTest" - numberOfShards 4 - streamOutput false - coresPerFork 6 - memoryInGbPerFork 10 - distribute DistributeTestsBy.CLASS - nodeTaints "big" + numberOfShards generalPurpose.numberOfShards + streamOutput generalPurpose.streamOutput + coresPerFork generalPurpose.coresPerFork + memoryInGbPerFork generalPurpose.memoryInGbPerFork + nodeTaints generalPurpose.nodeTaints + distribute DistributeTestsBy.METHOD } apply plugin: 'com.r3.testing.distributed-testing' apply plugin: 'com.r3.testing.image-building' From 9495efc50ca6b3db95704ea52f3c48687aabd8e0 Mon Sep 17 00:00:00 2001 From: Joel Dudley Date: Mon, 16 Mar 2020 12:27:55 +0000 Subject: [PATCH 7/9] Updates DJVM docs. (#6043) --- docs/source/key-concepts-djvm.rst | 77 ++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 23 deletions(-) diff --git a/docs/source/key-concepts-djvm.rst b/docs/source/key-concepts-djvm.rst index 649f24d573..bbd31a45d7 100644 --- a/docs/source/key-concepts-djvm.rst +++ b/docs/source/key-concepts-djvm.rst @@ -16,14 +16,6 @@ So, what does it mean for a piece of code to be fully deterministic? Ultimately as a function, is pure. In other words, given the same set of inputs, it will always produce the same set of outputs without inflicting any side-effects that might later affect the computation. -.. important:: The code in the DJVM module has not yet been integrated with the rest of the platform. It will eventually become a - part of the node and enforce deterministic and secure execution of smart contract code, which is mobile and may - propagate around the network without human intervention. - - Currently, it stands alone as an evaluation version. We want to give developers the ability to start trying it out and - get used to developing deterministic code under the set of constraints that we envision will be placed on contract code - in the future. - Non-Determinism ~~~~~~~~~~~~~~~ @@ -272,34 +264,73 @@ The DJVM doesn't support multi-threading and so synchronised methods and code bl use in sandboxed code. Consequently, we automatically transform them into ordinary methods and code blocks instead. -Future Work -~~~~~~~~~~~ +Trying out the DJVM +~~~~~~~~~~~~~~~~~~~ -Further work is planned: +.. warning:: The code in the DJVM module is still a beta release. It has been partially integrated with Corda to allow contract + verification. However, DJVM-enabled nodes cannot yet participate in a general Corda network containing nodes that do not use the DJVM. It + is provided to allow developers to try out the DJVM and experiment with developing deterministic code under the set of constraints that + we envision will be placed on contract code in the future. - * To enable controlled use of reflection APIs. +Tweaking Your Contract Code +........................... - * Currently, dynamic invocation is disallowed. Allow specific lambda and - string concatenation meta-factories used by Java code itself. +CorDapp developers may need to tweak their contract CorDapps for use inside the DJVM. This is because not every class, constructor or +method defined in the ``corda-core`` and ``corda-serialization`` modules is available when running inside the sandbox. - * Map more mathematical operations to use their 'exact' counterparts. +During development, you can choose to compile individual CorDapp modules against the DJVM by defining the following +``deterministic.gradle`` script plugin: - * General tightening of the enforced constraints. +.. code-block:: shell - * Cost accounting of runtime metrics such as memory allocation, branching and - exception handling. More specifically defining sensible runtime thresholds - and make further improvements to the instrumentation. + configurations { + compileClasspath { Configuration c -> deterministic(c) } + } - * More sophisticated runtime accounting as discussed in `Runtime Costing`_. + private final void deterministic(Configuration configuration) { + if (configuration.state == Configuration.State.UNRESOLVED) { + // Ensure that this module uses the deterministic Corda artifacts. + configuration.resolutionStrategy.dependencySubstitution { + substitute module("$corda_release_group:corda-serialization") with module("$corda_release_group:corda-serialization-deterministic:$corda_release_version") + substitute module("$corda_release_group:corda-core") with module("$corda_release_group:corda-core-deterministic:$corda_release_version") + } + } + } +And applying it to individual modules of your CorDapp using: -Command-line Tool -~~~~~~~~~~~~~~~~~ +.. code-block:: shell + + apply from: "${rootProject.projectDir}/deterministic.gradle" + +Uses of Corda's core or serialization APIs that are unavailable inside the sandbox will then cause compilation errors. + +Note however that successful compilation against ``corda-core-deterministic`` and ``corda-serialization-deterministic`` is +not sufficient. The only way to be sure that a piece of code is deterministic is to actually run it inside a DJVM sandbox, +as described below. + +Enabling Use of the DJVM for a Node +................................... + +You can enable the DJVM for your node by adding the following line to your node's ``node.conf`` file: + +.. code-block:: shell + + systemProperties = { "net.corda.djvm" = true } + +This will cause your node to sandbox every call to ``Contract.verify``. If your transaction contains a source of non-determinism, +transaction verification will fail. + +Alternatively, you can enable the DJVM when creating nodes via DemoBench by ticking the ``Deterministic Contract Verification`` checkbox +when creating the initial notary node. + +Using the Command-line Tool +........................... You can download and unpack ``corda-djvm-cli.zip`` from the R3 Artifactory. Alternatively, you can build it yourself from the source as follows. -Open your terminial and clone the DJVM repository from GitHub: +Open your terminal and clone the DJVM repository from GitHub: .. code-block:: shell From f476c1581d8d7a17b4bf43777786e330bfc01d4e Mon Sep 17 00:00:00 2001 From: Chris Rankin Date: Tue, 17 Mar 2020 08:48:45 +0000 Subject: [PATCH 8/9] CORDA-3377: Upgrade to DJVM 1.0. (#6071) --- constants.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/constants.properties b/constants.properties index 10bc33dcab..27a3493ced 100644 --- a/constants.properties +++ b/constants.properties @@ -30,7 +30,7 @@ snakeYamlVersion=1.19 caffeineVersion=2.7.0 metricsVersion=4.1.0 metricsNewRelicVersion=1.1.1 -djvmVersion=1.0-RC10 +djvmVersion=1.0 deterministicRtVersion=1.0-RC02 openSourceBranch=https://github.com/corda/corda/blob/release/os/4.4 openSourceSamplesBranch=https://github.com/corda/samples/blob/release-V4 From 861b76949975cc2e7c16a34f2ccf14bd81b5ff39 Mon Sep 17 00:00:00 2001 From: Dan Newton Date: Tue, 17 Mar 2020 13:55:10 +0000 Subject: [PATCH 9/9] NOTICK Update release-notes about database transaction limitations (#6052) * NOTICK Update release-notes about database transaction limitations --- docs/source/release-notes.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/source/release-notes.rst b/docs/source/release-notes.rst index 029f89a10b..d4fcf1ae94 100644 --- a/docs/source/release-notes.rst +++ b/docs/source/release-notes.rst @@ -79,6 +79,10 @@ Given the addition of new APIs, the platform version of Corda 4.4 has been bumpe For more information on platform version, please see :doc:`versioning`. For more details on upgrading a CorDapp to use platform version 5, please see :doc:`app-upgrade-notes`. +Known Issues +~~~~~~~~~~~~ + +Changes introduced in Corda 4.4 to increase ledger integrity have highlighted limitations regarding database transactions. To prevent flows from continuing to process after a database transaction has failed to commit or suffered from a pre-commit persistence exception, extra database flushes have been added. These extra flushes can cause exceptions to be thrown where they were not before (or cause different exception types to be raised compared to Corda 4.3 or previous versions). In general, CorDapp developers should not expect to be able to catch exceptions thrown during a database transaction and then continue with further DB operations as part of the same flow. A safer pattern involves allowing the flow to fail and be retried Issues Fixed ~~~~~~~~~~~~